Захват и передача/сохранение звука, получаемого с микрофона

Здравствуйте. Передо мной стоит такая задача: мне нужно брать звук из микрофона и передавать его. На данный момент я могу захватывать звук двумя способами:

С помощью mediacapture;
С помощью AudioGraph.

Рассмотрим второй вариант.

При работе с AudioGraph я создал и соединил такие узлы, как:

узел устройства захвата;
узел устройства вывода;
узел вывода аудиокадра.

Все сделано по вот этому уроку:

Звуковые графики

Вот как у меня выглядит метод вывода аудиокадра:

C#Выделить код

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

private byte[] _audioInBytes;
    unsafe private void ProcessFrameOutput(AudioFrame frame)
    {
        using (AudioBuffer buffer = frame.LockBuffer(AudioBufferAccessMode.Write))
        using (IMemoryBufferReference reference = buffer.CreateReference())
        {
            byte dataInBytes;
            uint capacityInBytes;
            float dataInFloat;
            ((IMemoryBufferByteAccess)reference).GetBuffer(out dataInBytes, out capacityInBytes);
            dataInFloat = (float)dataInBytes;
            _audioInBytes = new byte[capacityInBytes];
            Marshal.Copy((IntPtr)dataInFloat, _audioInBytes, 0, capacityInBytes);
        }
    }

И каждые 480 миллисек. вызывается этот метод и я получаю массив байтов со звуком. Но я думаю, что тут у меня ошибка, потому что я не могу воспроизвести их, если засуну эти байты в InMemoryRandomAccessStream и отправлю этот поток в MediaElement как источник. Ну, или же мне сначала нужно добавить header, но какой именно? Я при настройке AudioGraph задаю лишь то, что сжатие не должно производится, то есть ставлю AudioProccessing.Raw.

По первому варианту:

Я могу или периодически вызывать _mediaCapture.StopRecordAsync(), а затем считывать данные из потока (ранее я вызываю _mediaCapture.StartRecordToStreamAsync()), а затем заново запускать запись. Но я думаю, что это было бы глупо, потому что сильно замедлилась бы работа.

Или же я могу периодически считывать данные из потока, не останавливая запись. Но я так пробовал, но опять таки снова не могу воспроизводить все это.

Так, подскажите пожалуйста, что мне делать?

Добавлено через 16 часов 43 минуты

Вот со вчерашнего дня кое-что сделал по первому варианту. Теперь я могу считывать байты и записывать их в mp3 файл, и все нормально работает.

Только вот почему то не могу записать их wav файл.

Можете сказать, из-за чего это?

Вот код начала записи в поток:

C#Выделить код

1
2
3
4

MediaEncodingProfile encodingProfile = MediaEncodingProfile.CreateMp3(AudioEncodingQuality.Auto);
encodingProfile.Audio.ChannelCount = 1;
stream = new InMemoryRandomAccessStream();
await this.AudioCapture.StartRecordToStreamAsync(encodingProfile, stream);

А вот код, считывающий байты из потока:

C#Выделить код

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

private ulong FirstPos=0;
private async Task GetBytesFromStream()
{
     var reader = new DataReader(stream.GetInputStreamAt(0));
     newBytes = new byte[this.stream.Position-FirstPos];
     try
     {
           Bytes.Text = FirstPos + " " + this.stream.Position;
           ulong pos = this.stream.Position;
           this.stream.Seek(FirstPos);
           await reader.LoadAsync((uint)(this.stream.Size-FirstPos)); reader.ReadBytes(newBytes);
           FirstPos = this.stream.Size;
           this.stream.Seek(FirstPos);
     }
     catch (Exception ex)
     {
           rootPage.NotifyUser(ex.ToString()+ " GetBytesFromStream");
      }
}

И вот код, записывающий байты в файл:

C#Выделить код

1
2
3
4
5
6

if (isPreviewing)
{
      await GetBytesFromStream();
      StorageFile file = await KnownFolders.PicturesLibrary.CreateFileAsync("sound.mp3",                       CreationCollisionOption.GenerateUniqueName);
      await FileIO.WriteBytesAsync(file, newBytes);
}

Добавлено через 12 минут

Как оказалось, байты берутся лишь из начала потока. Так что не работает.

Добавлено через 1 час 11 минут

Я дурак, там я не сменил вот это:

C#Выделить код

| | |
| --- | --- |
| 1 | var reader = new DataReader(stream.GetInputStreamAt(0)); |

На это:

C#Выделить код

| | |
| --- | --- |
| 1 | var reader = new DataReader(stream.GetInputStreamAt(FirstPos)); |