从麦克风的数据创建.wav文件

时间:2014-01-23 16:13:57

标签: c# windows-phone-7 windows-phone-8 windows-phone

我只想从麦克风录制音频并将其保存在.wav文件中。 这是我的c#代码:

            IsolatedStorageFileStream fileStream = new IsolatedStorageFileStream(Filename, FileMode.Create, myIsolatedStorage);

            // Add wave header:

            BinaryWriter bw = new BinaryWriter(fileStream);
            bw.Write(new char[4] { 'R', 'I', 'F', 'F' });

            bw.Write((int)fileStream.Length + 36);

            bw.Write(new char[8] { 'W', 'A', 'V', 'E', 'f', 'm', 't', ' ' });

            bw.Write((int)16);

            bw.Write((short)1);
            short channels = 2;
            bw.Write(channels);
            int samplerate = 8000;
            bw.Write(samplerate);
            short BitsPerSample = 8;
            bw.Write((int)(samplerate * ((BitsPerSample * channels) / 8)));

            bw.Write((short)((BitsPerSample * channels) / 8));

            bw.Write(BitsPerSample);

            bw.Write(new char[4] { 'd', 'a', 't', 'a' });
            int DataLength = (int)fileStream.Length;
            bw.Write(DataLength);


            fileStream.Write(stream.GetBuffer(), 44, (int)stream.Position);

            fileStream.Position = 0;

            bw.Close();
            fileStream.Close();

如果我用VLC打开.wav文件,它不会重现任何内容。 如果我以这种方式打开文件(见下文),就在我保存之后,它会正确地重现声音:

 byte[] buffer = new byte[microphone.GetSampleSizeInBytes(duration)];
 using (IsolatedStorageFile userStore = IsolatedStorageFile.GetUserStoreForApplication())
 using (IsolatedStorageFileStream openfilestream = userStore.OpenFile(Filename, FileMode.Open))
            {
                openfilestream.Read(buffer, 0, buffer.Length);
            }

  SoundEffect sound = new SoundEffect(buffer, microphone.SampleRate, AudioChannels.Mono);
  soundInstance = sound.CreateInstance();
  soundIsPlaying = true;
  soundInstance.Play();

已编辑的代码

我只是编辑上面的代码,因为Adriano说(但它不起作用):

            IsolatedStorageFileStream fileStream = new IsolatedStorageFileStream(Filename, FileMode.Create, myIsolatedStorage);
            fileStream.Write(stream.GetBuffer(), 44, (int)stream.Position);


            // Aggiunta wav header:

            BinaryWriter bw = new BinaryWriter(fileStream);
            bw.Write(new char[4] { 'R', 'I', 'F', 'F' });

            bw.Write((int)fileStream.Length - 8);

            bw.Write(new char[8] { 'W', 'A', 'V', 'E', 'f', 'm', 't', ' ' });

            bw.Write((int)16);

            bw.Write((short)1);
            short channels = 1;
            bw.Write(channels);
            int samplerate = 8000;
            bw.Write(samplerate);
            short BitsPerSample = 8;
            bw.Write((int)(samplerate * ((BitsPerSample * channels) / 8)));

            bw.Write((short)((BitsPerSample * channels) / 8));

            bw.Write(BitsPerSample);

            bw.Write(new char[4] { 'd', 'a', 't', 'a' });
            int DataLength = (int)fileStream.Length - 44;
            bw.Write(DataLength);

            fileStream.Position = 0;

            bw.Close();
            fileStream.Close();

1 个答案:

答案 0 :(得分:0)

这些行看起来很可疑:

bw.Write((int)fileStream.Length + 36);
// ...
int DataLength = (int)fileStream.Length;
// ...
short channels = 2;
// ...
int samplerate = 8000;

如果它是单声道,频道应该是1。

看起来像fileStream.length总是0,你刚刚在上面创建它,看起来你打算写的是实际wav数据的长度。 stream.length?

8K的采样率质量很差,但这可能就是你猜的那样。最好使用实际的麦克风属性来确定这一点。

此外,如果将0x52494646和0x57415645设置为几个常量而不是使用char数组,则可能更容易阅读。

The canonical WAVE format starts with the RIFF header:

0         4   ChunkID          Contains the letters "RIFF" in ASCII form
                               (0x52494646 big-endian form).
4         4   ChunkSize        36 + SubChunk2Size, or more precisely:
                               4 + (8 + SubChunk1Size) + (8 + SubChunk2Size)
                               This is the size of the rest of the chunk 
                               following this number.  This is the size of the 
                               entire file in bytes minus 8 bytes for the
                               two fields not included in this count:
                               ChunkID and ChunkSize.
8         4   Format           Contains the letters "WAVE"
                               (0x57415645 big-endian form).

The "WAVE" format consists of two subchunks: "fmt " and "data":
The "fmt " subchunk describes the sound data's format:

12        4   Subchunk1ID      Contains the letters "fmt "
                               (0x666d7420 big-endian form).
16        4   Subchunk1Size    16 for PCM.  This is the size of the
                               rest of the Subchunk which follows this number.
20        2   AudioFormat      PCM = 1 (i.e. Linear quantization)
                               Values other than 1 indicate some 
                               form of compression.
22        2   NumChannels      Mono = 1, Stereo = 2, etc.
24        4   SampleRate       8000, 44100, etc.
28        4   ByteRate         == SampleRate * NumChannels * BitsPerSample/8
32        2   BlockAlign       == NumChannels * BitsPerSample/8
                               The number of bytes for one sample including
                               all channels. I wonder what happens when
                               this number isn't an integer?
34        2   BitsPerSample    8 bits = 8, 16 bits = 16, etc.
          2   ExtraParamSize   if PCM, then doesn't exist
          X   ExtraParams      space for extra parameters

The "data" subchunk contains the size of the data and the actual sound:

36        4   Subchunk2ID      Contains the letters "data"
                               (0x64617461 big-endian form).
40        4   Subchunk2Size    == NumSamples * NumChannels * BitsPerSample/8
                               This is the number of bytes in the data.
                               You can also think of this as the size
                               of the read of the subchunk following this 
                               number.
44        *   Data             The actual sound data.

通过:

https://ccrma.stanford.edu/courses/422/projects/WaveFormat/