Запись с микрофона и воспроизведение в Windows Phone - PullRequest
1 голос
/ 07 января 2012

Часть приложения, которое я разрабатываю, позволяет пользователю записывать что угодно, используя микрофон.Для записи с микрофона я использовал код, указанный в Пример кода микрофона от Microsoft .Я просто внес несколько изменений в код, чтобы записать заголовок wav в поток, чтобы я мог сохранить запись в виде волнового файла в изолированном хранилище.

private void recordButton_Click(object sender, EventArgs e)
        {
            // Get audio data in 1/2 second chunks
            microphone.BufferDuration = TimeSpan.FromMilliseconds(500);

            // Allocate memory to hold the audio data
            buffer = new byte[microphone.GetSampleSizeInBytes(microphone.BufferDuration)];

            // Set the stream back to zero in case there is already something in it
            stream.SetLength(0);

            //Write wav header
            WriteWavHeader(microphone.SampleRate);

            // Start recording
            microphone.Start();

            SetButtonStates(false, false, true,false);
            UserHelp.Text = "record";
            StatusImage.Source = microphoneImage;
            StatusImage.Visibility = System.Windows.Visibility.Visible;
        }

        public void WriteWavHeader(int sampleRate)
        {
            const int bitsPerSample = 16;
            const int bytesPerSample = bitsPerSample / 8;
            var encoding = System.Text.Encoding.UTF8;
            // ChunkID Contains the letters "RIFF" in ASCII form (0x52494646 big-endian form).
            stream.Write(encoding.GetBytes("RIFF"), 0, 4);

            // NOTE this will be filled in later
            stream.Write(BitConverter.GetBytes(0), 0, 4);

            // Format Contains the letters "WAVE"(0x57415645 big-endian form).
            stream.Write(encoding.GetBytes("WAVE"), 0, 4);

            // Subchunk1ID Contains the letters "fmt " (0x666d7420 big-endian form).
            stream.Write(encoding.GetBytes("fmt "), 0, 4);

            // Subchunk1Size 16 for PCM.  This is the size of therest of the Subchunk which follows this number.
            stream.Write(BitConverter.GetBytes(16), 0, 4);

            // AudioFormat PCM = 1 (i.e. Linear quantization) Values other than 1 indicate some form of compression.
            stream.Write(BitConverter.GetBytes((short)1), 0, 2);

            // NumChannels Mono = 1, Stereo = 2, etc.
            stream.Write(BitConverter.GetBytes((short)1), 0, 2);

            // SampleRate 8000, 44100, etc.
            stream.Write(BitConverter.GetBytes(sampleRate), 0, 4);

            // ByteRate =  SampleRate * NumChannels * BitsPerSample/8
            stream.Write(BitConverter.GetBytes(sampleRate * bytesPerSample), 0, 4);

            // BlockAlign NumChannels * BitsPerSample/8 The number of bytes for one sample including all channels.
            stream.Write(BitConverter.GetBytes((short)(bytesPerSample)), 0, 2);

            // BitsPerSample    8 bits = 8, 16 bits = 16, etc.
            stream.Write(BitConverter.GetBytes((short)(bitsPerSample)), 0, 2);

            // Subchunk2ID Contains the letters "data" (0x64617461 big-endian form).
            stream.Write(encoding.GetBytes("data"), 0, 4);

            // NOTE to be filled in later
            stream.Write(BitConverter.GetBytes(0), 0, 4);
        }

        public void UpdateWavHeader()
        {
            //if (!stream.CanSeek) throw new Exception("Can't seek stream to update wav header");

            var oldPos = stream.Position;

            // ChunkSize  36 + SubChunk2Size
            stream.Seek(4, SeekOrigin.Begin);
            stream.Write(BitConverter.GetBytes((int)stream.Length - 8), 0, 4);

            // Subchunk2Size == NumSamples * NumChannels * BitsPerSample/8 This is the number of bytes in the data.
            stream.Seek(40, SeekOrigin.Begin);
            stream.Write(BitConverter.GetBytes((int)stream.Length - 44), 0, 4);

            stream.Seek(oldPos, SeekOrigin.Begin);
        }

        private void stopButton_Click(object sender, EventArgs e)
        {
            if (microphone.State == MicrophoneState.Started)
            {
                // In RECORD mode, user clicked the 
                // stop button to end recording
                microphone.Stop();
                UpdateWavHeader();
            }
            else if (soundInstance.State == SoundState.Playing)
            {
                // In PLAY mode, user clicked the 
                // stop button to end playing back
                soundInstance.Stop();
            }

            SetButtonStates(true, true, false,true);
            UserHelp.Text = "ready";
            StatusImage.Source = blankImage;
        }

После этого, если пользователь решит сохранитьзапись Я сохраняю ее в изолированном хранилище.

В приложении есть различные страницы, и одна из них - страница с микрофоном.Переход к этой странице осуществляется с другой страницы:

NavigationService.Navigate(new Uri("/Mic.xaml", UriKind.Relative));

Теперь, когда на странице Mic.xaml записывается или не записывается что-либо, если пользователь нажимает кнопку возврата оборудования, он возвращается на старую страницу.,С этой страницы, если он снова переходит на страницу Mic.xaml и затем пытается что-то записать, записанный файл, похоже, не записывается должным образом.Кажется, что в записи есть проблемы.

Следовательно, когда мы впервые переходим на страницу, запись успешна, но когда мы переходим во второй раз или далее, это не так.

Я выполняю тестирование на эмуляторе

1 Ответ

4 голосов
/ 07 января 2012

Образец Microsoft не адаптирован для сценария с несколькими страницами, поскольку он не очищает ресурсы при выходе из страницы.

Сначала поместите DispatcherTimer в поле:

    private DispatcherTimer dt;

Затем измените конструктор, чтобы использовать это поле вместо инициализации нового dt:

    this.dt = new DispatcherTimer();

Наконец, переопределите метод OnNavigateFrom, чтобы определить, когда пользователь покидает страницу, и очистите ресурсы:

    protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
    {
        base.OnNavigatedFrom(e);

        dt.Stop();

        microphone.BufferReady -= this.microphone_BufferReady;
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...