UWP AudioGraph API - FrameOutputNode 读取字节错误

Posted

技术标签:

【中文标题】UWP AudioGraph API - FrameOutputNode 读取字节错误【英文标题】:UWP AudioGraph API - FrameOutputNode read bytes wrong 【发布时间】:2020-08-13 20:58:31 【问题描述】:

我对 UWP Audio Graph API 的 FrameOutputNode 有疑问。我有一个非常简单的图表,它从 wav(PCM 16000Hz,16 位单声道)文件中读取音频并将其发送到帧输出节点进行处理。处理时,我需要音频短(因为它们在文件的原始字节中)。但是当我阅读here 时,数据只能作为浮点数读取。

这是我的代码:

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 文件字节?

【问题讨论】:

您的代码 sn-p 中的 SpeechRecognitionNode 是什么?你能提供一个简单的样本,可以复制给我们测试吗? 抱歉是我上面创建的frameoutput节点,只是代码中的一个错误。 是的,我会准备一个演示并给你链接。 gist.github.com/erksch/662772d6a90d6605c0368b964f937b5c 这是 MainPage.xaml.cs 的要点,您可以将其复制到新的 C# UWP 项目中。您必须将音频文件复制到应用程序的 LocalState 文件夹。您可以在此处github.com/mozilla/DeepSpeech/raw/master/data/smoke_test/… 下载 16000Hz 16 位单声道示例音频。文件的实际字节和帧输出节点读取的字节被打印到输出。 【参考方案1】:

我的问题得到了回答here。基本上,浮点数是短裤 -32768 到 32767 的范围转换为浮点数 -1 到 1 的范围。

因此,给定缓冲区中的浮点 x(使用(float*)dataInFloats = (float*)dataInBytes 转换),您可以计算相应的短:

f(x) = (65535 * x - 1) / 2

【讨论】:

以上是关于UWP AudioGraph API - FrameOutputNode 读取字节错误的主要内容,如果未能解决你的问题,请参考以下文章

uwp AudioGraph 音频处理

在 UWP 应用中使用 AudioGraph 将音频输出发送到两台设备

最小化或锁定时继续播放 Audiograph UWP 输出

AudioGraph 可以播放流吗?

AudioGraph DesiredSamplesPerQuantum 属性被忽略

如何使用默认输出设备作为使用 AudioGraph 录制音频的源?