Wave File Coding: Save Files

Keywords: C#

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)

Posted by jd307 on Fri, 22 Mar 2019 06:30:52 -0700