Channel's audio engine was written by me, and I've been trying to find open source libraries to save files, but I just can't find them.
So there are the following simple and crude ways to deal with it:
First, WAV file format:
Initial address |
Occupancy space |
The Meaning of Local Address Number |
00H |
4byte |
RIFF, Resource Exchange File Logo. |
04H |
4byte |
The total number of bytes from the next address to the end of the file. The high byte is in the back, here is 001437ECH, and the decimal system is 1325036byte, which is exactly 1325044byte. |
08H |
4byte |
WAVE, representing wav file format. |
0CH |
4byte |
FMT, waveform format flag |
10H |
4byte |
00000010H, 16PCM, using 16bit data to represent a quantified result. |
14H |
2byte |
Linear PCM coding for 1 and compressed coding for more than 1. This is 0001H. |
16H |
2byte |
1 is mono channel, 2 is dual channel, here is 0001H. |
18H |
4byte |
Sampling frequency, here is 00002B11H, or 11025Hz. |
1CH |
4byte |
Byte rate = sampling frequency * number of audio channels * number of samples per sampling / 8,00005622H, that is 22050 Byte / S = 11025 * 1 * 16/2. |
20H |
2byte |
Block alignment = number of channels * the number of samples per sample / 8,0002H, or 2 = 1 * 16/8. |
22H |
2byte |
Sample data digits, 0010H or 16, a quantified sample accounts for 2 byte. |
24H |
4byte |
data, just a flag. |
28H |
4byte |
Wav file actual audio data occupies the size, here is 001437C8H or 1325000, plus 2CH is exactly 132544, the size of the entire file. |
2CH |
Indefinite |
Quantitative data. |
So instead, we can do a way to write WAV.
1 namespace Channel.Core 2 { 3 public class WriteWAVFile 4 { 5 #region Public_Properties 6 7 public enum WaveBitFormat 8 { 9 Bit8=1, 10 Bit16=2, 11 Bit32=4 12 } 13 public WaveBitFormat Waveformat { get; set; } 14 public float[] Data { get; set; } 15 public string Path { get; set; } 16 public bool zipped { get; set; } 17 public int zipObject { get; set; } 18 19 #endregion 20 21 #region MainMethod 22 23 public void WriteWave() 24 { 25 FileStream fs = new FileStream(Path, FileMode.OpenOrCreate); 26 //StreamWriter sw = new StreamWriter(fs); 27 fs.Position = 0; 28 29 //Write in'riff'File mark 30 byte[] riff = new byte[4]; 31 riff[0]= Convert.ToByte(82); 32 riff[1] = Convert.ToByte(73); 33 riff[2] = Convert.ToByte(70); 34 riff[3] = Convert.ToByte(70); 35 fs.WriteByte(riff[0]);//fs.Position++; 36 fs.WriteByte(riff[1]); //fs.Position++; 37 fs.WriteByte(riff[2]); //fs.Position++; 38 fs.WriteByte(riff[3]); //fs.Position++; 39 40 41 //Write file length 42 System.Numerics.BigInteger len = 0; 43 len = (int)Waveformat * Data.Length + 36; 44 byte[] length = len.ToByteArray(); 45 if(length.Count()==4) 46 { 47 fs.WriteByte(length[0]); //fs.Position++; 48 fs.WriteByte(length[1]); //fs.Position++; 49 fs.WriteByte(length[2]); //fs.Position++; 50 fs.WriteByte(length[3]); //fs.Position++; 51 } 52 else if (length.Count() == 3) 53 { 54 fs.WriteByte(length[0]); //fs.Position++; 55 fs.WriteByte(length[1]); //fs.Position++; 56 fs.WriteByte(length[2]); //fs.Position++; 57 fs.WriteByte(Convert.ToByte(0)); //fs.Position++; 58 } 59 else if(length.Count()==2) 60 { 61 fs.WriteByte(length[0]); //fs.Position++; 62 fs.WriteByte(length[1]); //fs.Position++; 63 fs.WriteByte(Convert.ToByte(0)); //fs.Position++; 64 fs.WriteByte(Convert.ToByte(0)); //fs.Position++; 65 } 66 67 //Write " wave fmt" 68 fs.WriteByte(Convert.ToByte(87)); //fs.Position++; 69 fs.WriteByte(Convert.ToByte(65)); //fs.Position++; 70 fs.WriteByte(Convert.ToByte(86)); //fs.Position++; 71 fs.WriteByte(Convert.ToByte(69)); //fs.Position++; 72 73 fs.WriteByte(Convert.ToByte(102)); //fs.Position++; 74 fs.WriteByte(Convert.ToByte(109)); //fs.Position++; 75 fs.WriteByte(Convert.ToByte(116)); //fs.Position++; 76 fs.WriteByte(Convert.ToByte(32)); //fs.Position++; 77 78 //Write playback number 79 switch (Waveformat ) 80 { 81 case WaveBitFormat.Bit8: 82 fs.WriteByte(Convert.ToByte(8)); //fs.Position++; 83 fs.WriteByte(Convert.ToByte(0)); //fs.Position++; 84 fs.WriteByte(Convert.ToByte(0)); //fs.Position++; 85 fs.WriteByte(Convert.ToByte(0)); //fs.Position++; 86 break; 87 case WaveBitFormat.Bit16: 88 fs.WriteByte(Convert.ToByte(16)); //fs.Position++; 89 fs.WriteByte(Convert.ToByte(0)); //fs.Position++; 90 fs.WriteByte(Convert.ToByte(0)); //fs.Position++; 91 fs.WriteByte(Convert.ToByte(0)); //fs.Position++; 92 break; 93 case WaveBitFormat.Bit32: 94 fs.WriteByte(Convert.ToByte(32)); //fs.Position++; 95 fs.WriteByte(Convert.ToByte(0)); //fs.Position++; 96 fs.WriteByte(Convert.ToByte(0)); //fs.Position++; 97 fs.WriteByte(Convert.ToByte(0)); //fs.Position++; 98 break; 99 default: 100 break; 101 } 102 103 //Is it compressed? 104 if(zipped) 105 { 106 fs.WriteByte(Convert.ToByte(zipObject)); //fs.Position++; 107 fs.WriteByte(Convert.ToByte(0)); //fs.Position++; 108 } 109 else 110 { 111 fs.WriteByte(Convert.ToByte(1)); //fs.Position++; 112 fs.WriteByte(Convert.ToByte(0)); //fs.Position++; 113 } 114 115 //Vocal tract 116 if(ChannelCount==1 ) 117 { 118 fs.WriteByte(Convert.ToByte(1)); //fs.Position++; 119 fs.WriteByte(Convert.ToByte(0)); //fs.Position++; 120 } 121 else 122 { 123 fs.WriteByte(Convert.ToByte(2)); //fs.Position++; 124 fs.WriteByte(Convert.ToByte(0)); //fs.Position++; 125 } 126 127 //Sampling frequency default 0000 AC44H (44100) 128 System.Numerics.BigInteger fre = 0; 129 fre = Frequency; 130 byte[] freq = fre.ToByteArray(); 131 if (freq.Count() == 4) 132 { 133 fs.WriteByte(freq[0]); //fs.Position++; 134 fs.WriteByte(freq[1]); //fs.Position++; 135 fs.WriteByte(freq[2]); //fs.Position++; 136 fs.WriteByte(freq[3]); //fs.Position++; 137 } 138 else if (freq.Count() == 3) 139 { 140 fs.WriteByte(freq[0]); //fs.Position++; 141 fs.WriteByte(freq[1]); //fs.Position++; 142 fs.WriteByte(freq[2]); //fs.Position++; 143 fs.WriteByte(Convert.ToByte(0)); //fs.Position++; 144 } 145 else if (freq.Count() == 2) 146 { 147 fs.WriteByte(freq[0]); //fs.Position++; 148 fs.WriteByte(freq[1]); //fs.Position++; 149 fs.WriteByte(Convert.ToByte(0)); //fs.Position++; 150 fs.WriteByte(Convert.ToByte(0)); //fs.Position++; 151 } 152 153 //Freq*Channel*Bit/8 154 System.Numerics.BigInteger res11 = 0; 155 res11 = Frequency*(int)Waveformat*ChannelCount; 156 byte[] res1 = res11.ToByteArray(); 157 if (res1.Count() == 4) 158 { 159 fs.WriteByte(res1[0]); //fs.Position++; 160 fs.WriteByte(res1[1]); //fs.Position++; 161 fs.WriteByte(res1[2]); //fs.Position++; 162 fs.WriteByte(res1[3]); //fs.Position++; 163 } 164 else if (res1.Count() == 3) 165 { 166 fs.WriteByte(res1[0]); //fs.Position++; 167 fs.WriteByte(res1[1]); //fs.Position++; 168 fs.WriteByte(res1[2]); //fs.Position++; 169 fs.WriteByte(Convert.ToByte(0)); //fs.Position++; 170 } 171 else if (res1.Count() == 2) 172 { 173 fs.WriteByte(res1[0]); //fs.Position++; 174 fs.WriteByte(res1[1]); //fs.Position++; 175 fs.WriteByte(Convert.ToByte(0)); //fs.Position++; 176 fs.WriteByte(Convert.ToByte(0)); //fs.Position++; 177 } 178 179 //channel*bit/8 180 System.Numerics.BigInteger res22 = 0; 181 res22 =(int)Waveformat * ChannelCount; 182 byte[] res2 = res22.ToByteArray(); 183 if (res2.Count() == 2) 184 { 185 fs.WriteByte(res2[0]); //fs.Position++; 186 fs.WriteByte(res2[1]); //fs.Position++; 187 } 188 else if (res2.Count() == 1) 189 { 190 fs.WriteByte(res2[0]); //fs.Position++; 191 fs.WriteByte(Convert.ToByte(0)); //fs.Position++; 192 } 193 194 //digit(That's right. Write it twice.) 195 switch (Waveformat) 196 { 197 case WaveBitFormat.Bit8: 198 fs.WriteByte(Convert.ToByte(8)); //fs.Position++; 199 fs.WriteByte(Convert.ToByte(0)); //fs.Position++; 200 break; 201 case WaveBitFormat.Bit16: 202 fs.WriteByte(Convert.ToByte(16)); //fs.Position++; 203 fs.WriteByte(Convert.ToByte(0)); //fs.Position++; 204 break; 205 case WaveBitFormat.Bit32: 206 fs.WriteByte(Convert.ToByte(32));// fs.Position++; 207 fs.WriteByte(Convert.ToByte(0)); //fs.Position++; 208 break; 209 default: 210 break; 211 } 212 213 //data sign 214 fs.WriteByte(Convert.ToByte(100)); //fs.Position++; 215 fs.WriteByte(Convert.ToByte(97)); //fs.Position++; 216 fs.WriteByte(Convert.ToByte(116)); //fs.Position++; 217 fs.WriteByte(Convert.ToByte(97)); //fs.Position++; 218 219 //data size 220 len = (int)Waveformat * Data.Length; 221 byte[] lengthD = len.ToByteArray(); 222 if (lengthD.Count() == 4) 223 { 224 fs.WriteByte(lengthD[0]); //fs.Position++; 225 fs.WriteByte(lengthD[1]); //fs.Position++; 226 fs.WriteByte(lengthD[2]); //fs.Position++; 227 fs.WriteByte(lengthD[3]); //fs.Position++; 228 } 229 else if (lengthD.Count() == 3) 230 { 231 fs.WriteByte(lengthD[0]); //fs.Position++; 232 fs.WriteByte(lengthD[1]); //fs.Position++; 233 fs.WriteByte(lengthD[2]); //fs.Position++; 234 fs.WriteByte(Convert.ToByte(0)); //fs.Position++; 235 } 236 else if (lengthD.Count() == 2) 237 { 238 fs.WriteByte(lengthD[0]); //fs.Position++; 239 fs.WriteByte(lengthD[1]); //fs.Position++; 240 fs.WriteByte(Convert.ToByte(0)); //fs.Position++; 241 fs.WriteByte(Convert.ToByte(0)); //fs.Position++; 242 } 243 244 //data 245 foreach (float dataitem in Data) 246 { 247 byte[] target32; 248 byte[] target16; 249 target32 = BitConverter.GetBytes(dataitem); 250 int i =Convert.ToInt32( dataitem * 32768); 251 //string h16 = i.ToString("X"); 252 //string h161=h16.Substring(4, 4); 253 target16 = BitConverter.GetBytes(i); 254 255 switch (Waveformat) 256 { 257 case WaveBitFormat.Bit8: 258 //fs.WriteByte(Convert.ToByte(8)); fs.Position++; 259 //fs.WriteByte(Convert.ToByte(0)); fs.Position++; 260 break; 261 case WaveBitFormat.Bit16: 262 fs.WriteByte(target16[0]); //fs.Position++; 263 fs.WriteByte(target16[1]); //fs.Position++; 264 break; 265 case WaveBitFormat.Bit32: 266 fs.WriteByte(target32[0]); //fs.Position++; 267 fs.WriteByte(target32[1]); //fs.Position++; 268 fs.WriteByte(target32[2]); //fs.Position++; 269 fs.WriteByte(target32[3]); //fs.Position++; 270 break; 271 default: 272 break; 273 } 274 } 275 276 //Ending 277 fs.Flush(); 278 fs.Close(); 279 } 280 281 #endregion 282 public int ChannelCount { get; set; } 283 public int Frequency { get; set; } 284 } 285 }
Look at the comments in the code and you'll see the usefulness.
Here's how to call:
1 private void saveToolStripMenuItem_Click(object sender, EventArgs e) 2 { 3 SaveFileDialog o = new SaveFileDialog(); 4 o.ShowDialog(); 5 Channel.Core.WriteWAVFile ww = new Core.WriteWAVFile();//New instance 6 ww.ChannelCount = 1;//Channels 7 ww.Data = wavePainterExtended1.DataProperty;//data 8 ww.Frequency = 44100;//sampling frequency 9 ww.Path = o.FileName;//Save position 10 ww.Waveformat = Core.WriteWAVFile.WaveBitFormat.Bit16;//16bit 11 ww.zipObject = 1;//Null value 12 ww.zipped = false;//Uncompressed 13 ww.WriteWave();//implement 14 }
Running picture:
And the files before and after saving (data I do anti-processing)