首页 > 代码库 > Wave文件编码:保存文件
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 = http://www.mamicode.com/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文件编码:保存文件