使用NAudio混合原始音频流生成的WAV文件损坏问题排查
问题分析:混合音频流生成损坏WAV文件的原因
代码片段
string path = string.Empty; private void SaveAudioRecording() { timer.Dispose(); if (string.IsNullOrEmpty(path)) { path = Directory.GetCurrentDirectory() + "\\AudioRecordings_"+clientSession.clientInfo[0]; Directory.CreateDirectory(path); } WaveMixerStream32 mix= new WaveMixerStream32(); foreach (var stream in new MemoryStream[] { audioOutputMemoryStream, audioInputMemoryStream }) { stream.Position = 0; if (stream != null && stream.Length > 0 && stream.Position < stream.Length) { RawSourceWaveStream reader = new RawSourceWaveStream(stream,new WaveFormat(41100,1)); WaveChannel32 chanel = new WaveChannel32(reader); mix.AddInputStream(chanel); } } using (FileStream stream = File.Create(System.IO.Path.Combine(path, "Audio_recording_" + Directory.EnumerateFiles(path).Count().ToString() + ".wav"))) { byte[] buffer = new byte[mix.Length]; mix.Read(buffer, 0, buffer.Length); stream.Write(buffer, 0, buffer.Length); WriteWavHeader(stream,Convert.ToInt32(stream.Length)); stream.Flush(); } recordButton.IsEnabled = true; } private void WriteWavHeader(Stream stream, int audioDataSize) { using (var writer = new BinaryWriter(stream, Encoding.UTF8, true)) { writer.Write(Encoding.ASCII.GetBytes("RIFF")); writer.Write(audioDataSize + 36); // Total file size - 8 bytes writer.Write(Encoding.ASCII.GetBytes("WAVE")); writer.Write(Encoding.ASCII.GetBytes("fmt ")); writer.Write(16); // Length of format data writer.Write((ushort)1); // PCM format writer.Write((ushort)1); // Not Stereo writer.Write(41100); // Sample rate writer.Write(82200); // Byte rate (Sample rate * Channels * BitsPerSample / 8) writer.Write((ushort)4); // Block align (Channels * BitsPerSample / 8) writer.Write((ushort)16); // Bits per sample writer.Write(Encoding.ASCII.GetBytes("data")); writer.Write(audioDataSize); // Size of audio data } }
问题描述
生成的文件已损坏,无法播放,但文件有一定大小,说明字节已写入。我尝试将两个原始音频流混合为完整的WAV文件,因此为其写入WAV头。此前单独测试WAV头功能正常,但修改代码后生成的文件出现损坏。可能的问题原因是什么?
可能的原因分析
- WAV头写入顺序错误:标准WAV文件结构是先头后数据,你现在先写音频数据再写头,播放器读取时会先找开头的RIFF标识,头在文件末尾导致播放器无法识别,直接判定文件损坏。
- 音频数据读取不完整:
WaveMixerStream32的Length属性可能无法准确返回混合后音频的实际长度,一次性读取mix.Length字节可能导致数据读取不全,或者包含无效内容。建议用循环调用Read方法直到返回0,确保读取所有有效数据。 - 原始流格式与指定格式不匹配:创建
RawSourceWaveStream时指定了WaveFormat(41100,1),但如果audioOutputMemoryStream和audioInputMemoryStream实际不是41100采样率、单声道、16位PCM格式,混合后的音频数据会错乱,即使头正确也无法正常播放。 - 音频数据大小计算错误:调用
WriteWavHeader时传入的stream.Length是已写入的字节数,但如果mix.Read没读满buffer,这个值就不准确。正确的做法是用mix.Read的返回值作为实际音频数据大小,而不是stream.Length。 - 流指针位置错误:写完音频数据后,文件流指针在末尾,此时写入头会把头放在数据后面。正确流程应该是先写头(或占位头),再写数据,最后回到开头更新头的正确数值;或者先准备好头,按头→数据的顺序写入。
- 混合流格式与手动写头不匹配:
WaveMixerStream32混合后的流格式可能和你手动写的头参数不一致,比如混合后变成了立体声或者采样率改变。可以检查mix.WaveFormat的参数,确保和写头时用的参数完全一致。
内容的提问来源于stack exchange,提问作者Alexander Jansson
相关产品推荐
相关产品推荐

