uwp AudioGraph 音频处理

Posted

技术标签:

【中文标题】uwp AudioGraph 音频处理【英文标题】:uwp AudioGraph audio processing 【发布时间】:2016-04-14 21:17:55 【问题描述】:

我正在开发一个基于音频输入控制 LED 灯条的 winodws IoT 项目。现在我有一些代码可以将音频输入并使用 AudioGraph API 将其写入缓冲区,但我不知道如何将音频处理为一些有用的数据。

到目前为止我的代码:

private async void MainPage_Loaded(object sender, RoutedEventArgs eventArgs)

        try
        
            // Initialize the led strip
            //await this.pixelStrip.Begin();

            sampleAggregator.FftCalculated += new EventHandler<FftEventArgs>(FftCalculated);
            sampleAggregator.PerformFFT = true;

            // Create graph
            AudioGraphSettings settings = new AudioGraphSettings(AudioRenderCategory.Media);
            settings.DesiredSamplesPerQuantum = fftLength;
            settings.DesiredRenderDeviceAudioProcessing = Windows.Media.AudioProcessing.Default;
            settings.QuantumSizeSelectionMode = QuantumSizeSelectionMode.ClosestToDesired;

            CreateAudioGraphResult result = await AudioGraph.CreateAsync(settings);
            if (result.Status != AudioGraphCreationStatus.Success)
            
                // Cannot create graph
                return;
            
            graph = result.Graph;

            // Create a device input node using the default audio input device
            CreateAudioDeviceInputNodeResult deviceInputNodeResult = await graph.CreateDeviceInputNodeAsync(MediaCategory.Other);

            if (deviceInputNodeResult.Status != AudioDeviceNodeCreationStatus.Success)
            
                return;
            

            deviceInputNode = deviceInputNodeResult.DeviceInputNode;

            frameOutputNode = graph.CreateFrameOutputNode();
            frameOutputNode.Start();
            graph.QuantumProcessed += AudioGraph_QuantumProcessed;

            // Because we are using lowest latency setting, we need to handle device disconnection errors
            graph.UnrecoverableErrorOccurred += Graph_UnrecoverableErrorOccurred;

            graph.Start();
        
        catch (Exception e)
        
            Debug.WriteLine(e.ToString());
        
    

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

    unsafe private void ProcessFrameOutput(AudioFrame frame)
    
        using (AudioBuffer buffer = frame.LockBuffer(AudioBufferAccessMode.Write))
        using (IMemoryBufferReference reference = buffer.CreateReference())
        
            byte* dataInBytes;
            uint capacityInBytes;
            float* dataInFloat;

            // Get the buffer from the AudioFrame
            ((IMemoryBufferByteAccess)reference).GetBuffer(out dataInBytes, out capacityInBytes);

            dataInFloat = (float*)dataInBytes;


        
    

所以我以我的缓冲区作为浮点数结束。但是我怎样才能将其更改为有用的数据,从而可以创建像频谱分析仪这样的东西呢?

编辑:

也许我必须让这个问题对听力图不那么具体。我使用 API 来获取我的音频输入。我从 API 获得的数据是一个字节*,我可以将其转换为浮点数* 如何将其从字节*或浮点数*更改为可用于创建一些颜色代码的其他数据。

我想对 float* 进行一些 FFT 分析以获得 164 个 LED*3(rgb) = 492 个 bin。并进一步处理这些数据以获得 0 到 255 之间的一些值。

那么我该如何处理这个 float* 或 byte* 来获取这些有用的数据呢?或者我该如何开始?

【问题讨论】:

你可以看看github.com/filoe/cscore,里面有一个示例(见下图) 【参考方案1】:

该数据是交错的 IEEE 浮点数,因此它会在您逐步通过数组时交替通道数据,并且每个样本的数据范围是从 -1 到 1。 例如,单声道信号只有一个通道,所以它根本不会交错数据;但是立体声信号有两个音频通道,所以:

dataInFloat[0]

是来自左通道的第一个数据样本,并且

dataInFloat[1]

是来自右通道的第一个数据样本。那么,

dataInFloat[2]

是来自左通道的第二个数据样本。他们只是不断地来回走动。您最终会关心的所有其他数据都在 windows.media.mediaproperties.audioencodingproperties 中

因此,只要知道这一点,您(基本上)就可以通过查看每个样本的绝对值直接从该数据中获得信号的整体音量。您肯定希望在一段时间内对其进行平均。您甚至可以将 EQ 效果附加到不同的节点,并制作单独的 Low、Mids 和 High 分析器节点,甚至永远不会进入 FFT 的东西。但那有什么乐趣呢? (其实还是很好玩的)

然后,是的,要获取复杂的谐波数据并制作真正精美的可视化工具,您需要对其进行 FFT。人们喜欢将AForge 用于学习场景,例如您的场景。用法参见 Sources/Imaging/ComplexImage.cs,实现参见 Sources/Math/FourierTransform.cs

然后您可以轻松获取经典 bin 数据并执行经典音乐可视化工具或获取更多 creative 或其他任何内容!技术很棒!

【讨论】:

谢谢!我还有一些问题。我大部分时间在 0.01 秒的帧时间内有 3840 的缓冲区长度,所以这意味着 (3840/sizeof(float))/2 我的左右通道的长度为 480 个浮点数。这是正确的吗?我的图的编码属性是比特率 3072000,比特/样本 32,采样率 48000 你是对的!请注意,数据的范围是 [-1,+1],因此如果您查看该数据的绝对值的平均值,您将获得对音量的粗略估计。 (我也在用这个信息修改我上面的帖子)但实际上你应该把它交给 FFT 以获取真实的数据值,但是幅度技巧(平均绝对浮点值)对于快速 n 脏分析工作正常并且 CPU 密集度要低得多。如果我只想从音乐中触发一件外部事物(一盏灯、一个马达、手机振动等),我会一直这样做 好的,很好!所以现在我创建了一个复数数组,其中实部是左音频的值(需要类似 hammingwindow 的东西吗?),复数部分将是 0(音频总是 0 对吗?)。如果该数组是 2^n 的长度,那么我将其通过 FFT 并返回频率与时间的关系。然后我期望的是后半部分与第一部分相同。但事实并非如此 :( 那么,我的想法和行为是否正确? 抱歉,这超出了我的知识库。当你做这样的音频工作时,我会说要非常注意数据格式。 PCM 与 IEEE 等……请确保您了解函数之间的数据切换点并且符合预期格式 啊,好吧。不管怎么说,还是要谢谢你。你帮我找到了正确的方向:)【参考方案2】:
  dataInFloat = (float*)dataInBytes;
  float max = 0;
   for (int i = 0; i < graph.SamplesPerQuantum; i++)
                
                    max = Math.Max(Math.Abs(dataInFloat[i]), max);

                

                finalLevel = max;
                Debug.WriteLine(max);

【讨论】:

以上是关于uwp AudioGraph 音频处理的主要内容,如果未能解决你的问题,请参考以下文章

UWP AudioGraph API - FrameOutputNode 读取字节错误

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

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

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

当 Superpowered Reverb 与 Audio Graph 一起使用时,处理的音频非常嘈杂

基于音频iOS的动画