Wave文件编码:保存文件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Wave文件编码:保存文件相关的知识,希望对你有一定的参考价值。

Channel的音频引擎是我自己写的,保存文件一直想找开源库但就是找不着。。

于是就有了以下简单粗暴打点办法:

首先是WAV的文件格式

起始地址

占用空间

本地址数字的含义

00H

4byte

RIFF,资源交换文件标志。

04H

4byte

从下一个地址开始到文件尾的总字节数。高位字节在后面,这里就是001437ECH,换成十进制是1325036byte,算上这之前的8byte就正好1325044byte了。

08H

4byte

WAVE,代表wav文件格式。

0CH

4byte

FMT ,波形格式标志

10H

4byte

00000010H,16PCM,用16bit的数据表示一个量化结果。

14H

2byte

为1时表示线性PCM编码,大于1时表示有压缩的编码。这里是0001H。

16H

2byte

1为单声道,2为双声道,这里是0001H。

18H

4byte

采样频率,这里是00002B11H,也就是11025Hz。

1CH

4byte

Byte率=采样频率*音频通道数*每次采样得到的样本位数/8,00005622H,也就是22050Byte/s=11025*1*16/2。

20H

2byte

块对齐=通道数*每次采样得到的样本位数/8,0002H,也就是2=1*16/8。

22H

2byte

样本数据位数,0010H即16,一个量化样本占2byte。

24H

4byte

data,一个标志而已。

28H

4byte

Wav文件实际音频数据所占的大小,这里是001437C8H即1325000,再加上2CH就正好是1325044,整个文件的大小。

2CH

不定

量化数据。

于是我们可以反着来,做一个写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             //写入‘riff’文件标记
 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             //写入文件长度
 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             //写入“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             //写入播放位数
 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             //是否压缩
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             //声道
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             //采样频率  默认 0000AC44H (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             //位数(没错要写两遍)
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标记
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             //数据大小
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             //数据
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 }

看代码中的注释就知道用处了

下面是如何调用

 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();//新建实例
 6             ww.ChannelCount = 1;//声道数
 7             ww.Data = wavePainterExtended1.DataProperty;//数据
 8             ww.Frequency = 44100;//采样频率
 9             ww.Path = o.FileName;//保存位置
10             ww.Waveformat = Core.WriteWAVFile.WaveBitFormat.Bit16;//16bit
11             ww.zipObject = 1;//空值
12             ww.zipped = false;//不压缩
13             ww.WriteWave();//执行
14         }

运行图片:

技术分享

以及保存前后的文件(数据我做了反相处理)

技术分享

技术分享

 

以上是关于Wave文件编码:保存文件的主要内容,如果未能解决你的问题,请参考以下文章

使用 AudioToolBox 将 Wave 文件保存到 NSFileWrapper

使用 acm 进行 Ogg 到 Riff/Wave 编码

多媒体:WAVE文件格式分析

加载和保存 WAV 文件

WAV 文件 (.wav) 和 WAVE 音频文件 (.wave) 有啥区别?

Python 从零开始制作自己的声音 - wave模块读写wav文件详解