UWP AudioGraph API - неправильно считаны байты FrameOutputNode - PullRequest
2 голосов
/ 29 апреля 2020

У меня проблема с FrameOutputNode API UWP Audio Graph. У меня есть очень простой график, который читает аудио из файла wav (PCM 16000Hz, 16 bit mono) и отправляет его на узел вывода кадра для обработки. При обработке мне нужно, чтобы звук был в шортах (как они есть в необработанных байтах файла). Но когда я читаю здесь , данные могут быть прочитаны только как числа с плавающей запятой.

Вот мой код:

var encoding = MediaEncodingProfile.CreateWav(AudioEncodingQuality.Low);
encoding.Audio = AudioEncodingProperties.CreatePcm(16000, 1, 16);

AudioGraphSettings settings = new AudioGraphSettings(AudioRenderCategory.Media);
settings.EncodingProperties = encoding.Audio;
CreateAudioGraphResult result = await AudioGraph.CreateAsync(settings);
var graph = result.Graph;

var localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
StorageFile file = await localFolder.GetFileAsync("audio.wav");

var fileInputNodeResult = await graph.CreateFileInputNodeAsync(file);
var fileInputNode = fileInputNodeResult.FileInputNode;

fileInputNode.FileCompleted += async (AudioFileInputNode sender, object args) =>
{
    graph.Stop();
}

frameOutputNode = graph.CreateFrameOutputNode(encoding.Audio);
fileInputNode.AddOutgoingConnection(frameOutputNode);

graph.QuantumStarted+= AudioGraph_QuantumStarted;

со следующим AudioGraph_QuantumStarted обработчиком событий:

private void AudioGraph_QuantumStarted(AudioGraph sender, object args)
{
    AudioFrame frame = frameOutputNode.GetFrame();
    ProcessFrameOutput(frame);
}

unsafe private void ProcessFrameOutput(AudioFrame frame)
{
    AudioBuffer buffer = frame.LockBuffer(AudioBufferAccessMode.Read);
    IMemoryBufferReference reference = buffer.CreateReference();
    ((IMemoryBufferByteAccess)reference).GetBuffer(out byte* dataInBytes, out uint capacityInBytes);

    if (capacityInBytes > 0) {
        // Read the first 20 bytes 
        for (int i = 0; i < 20; i++)
        {
            Debug.WriteLine(dataInBytes[i]);
        }
    }
}

Получены следующие байты на выходе. Так как образцы возвращаются как байты с плавающей точкой, я пометил границу выборки линией.

0 0 0 0 | 0 0 0 184 | 0 0 128 184 | 0 0 0 184 ...

Но когда я читаю фактические байты из файла с помощью устройства чтения байтов:

FileStream fIn = new FileStream(@"/path/to/audio.wav", FileMode.Open);
BinaryReader br = new BinaryReader(fIn);
// Skip the first 44 bytes since they are header stuff
br.ReadBytes(44);
for (int i = 0; i < 20; i++) 
{
    Debug.WriteLine(br.ReadByte());
}

Затем я получаю фактические байты:

0 0 | 255 255 | 254 255 | 255 255 | 255 255 | 254 255 | 253 255 | 252 255 ...

Снова Я пометил отдельные сэмплы (шорты -> два байта) линией.

Как вы видите, короткие байты 255 255 как-то отображаются в плавающие байты 0 0 0 184 по мере их повторения. Так что это за отображение? Как я могу получить сырые шорты с поплавков? Что мне нужно сделать, чтобы фактически прочитать байты wav-файла?

1 Ответ

0 голосов
/ 30 апреля 2020

На мой вопрос ответили здесь . В основном, числа с плавающей запятой - это диапазон шорт от -32768 до 32767, преобразованный в диапазон от -1 до 1 в формате с плавающей запятой.

Таким образом, учитывая число с плавающей запятой в буфере (используйте (float*)dataInFloats = (float*)dataInBytes для преобразования), вы можете вычислить соответствующий короткий с:

f(x) = (65535 * x - 1) / 2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...