为内存中的流创建有效的wav文件头

Hip*_*nor 4 c# audio wav pcm

我有raw-headerless wav音频数据作为MemoryStreams.

Stream rawAudioStream = Producer.GetRawAudioFileStream(...);
Run Code Online (Sandbox Code Playgroud)

我知道那些流数据格式:

// WaveFormat(int rate, int bits, int channels);
WaveFormat waveformat = new WaveFormat(8000, 16, 1);
Run Code Online (Sandbox Code Playgroud)

我想要的是以编程方式为这些内存流添加正确的头信息,而无需将它们写入物理文件.

我怎样才能做到这一点?

PS:我检查了NAudio库,但只找到了一种通过将流写入真实物理文件来创建标头的方法,这种方式不适合我的情况.

var waveformat = new WaveFormat(8000,16,1);

var reader = new RawSourceWaveStream(rawAudioMemStream, waveformat);

using (var convertedStream = WaveFormatConversionStream.CreatePcmStream(reader))    
{
    WaveFileWriter.CreateWaveFile(fileName, convertedStream);     
}

rawAudioMemStream.Close();
Run Code Online (Sandbox Code Playgroud)

Sam*_*Sam 12

下面的代码会将一个Wav标题写入a的开头MemoryStream.这意味着你需要写标题,你流第一,然后你可以写你的样品.否则,您的流开头的样本将被元数据覆盖,

// totalSampleCount needs to be the combined count of samples of all channels. So if the left and right channels contain 1000 samples each, then totalSampleCount should be 2000.
// isFloatingPoint should only be true if the audio data is in 32-bit floating-point format.

private void WriteWavHeader(MemoryStream stream, bool isFloatingPoint, ushort channelCount, ushort bitDepth, int sampleRate, int totalSampleCount)
{
    stream.Position = 0;

    // RIFF header.
    // Chunk ID.
    stream.Write(Encoding.ASCII.GetBytes("RIFF"), 0, 4);

    // Chunk size.
    stream.Write(BitConverter.GetBytes(((bitDepth / 8) * totalSampleCount) + 36), 0, 4);

    // Format.
    stream.Write(Encoding.ASCII.GetBytes("WAVE"), 0, 4);



    // Sub-chunk 1.
    // Sub-chunk 1 ID.
    stream.Write(Encoding.ASCII.GetBytes("fmt "), 0, 4);

    // Sub-chunk 1 size.
    stream.Write(BitConverter.GetBytes(16), 0, 4);

    // Audio format (floating point (3) or PCM (1)). Any other format indicates compression.
    stream.Write(BitConverter.GetBytes((ushort)(isFloatingPoint ? 3 : 1)), 0, 2);

    // Channels.
    stream.Write(BitConverter.GetBytes(channelCount), 0, 2);

    // Sample rate.
    stream.Write(BitConverter.GetBytes(sampleRate), 0, 4);

    // Bytes rate.
    stream.Write(BitConverter.GetBytes(sampleRate * channelCount * (bitDepth / 8)), 0, 4);

    // Block align.
    stream.Write(BitConverter.GetBytes((ushort)channelCount * (bitDepth / 8)), 0, 2);

    // Bits per sample.
    stream.Write(BitConverter.GetBytes(bitDepth), 0, 2);



    // Sub-chunk 2.
    // Sub-chunk 2 ID.
    stream.Write(Encoding.ASCII.GetBytes("data"), 0, 4);

    // Sub-chunk 2 size.
    stream.Write(BitConverter.GetBytes((bitDepth / 8) * totalSampleCount), 0, 4);
}
Run Code Online (Sandbox Code Playgroud)