[UWP] [C#]使用AudioBuffer清理非托管内存。

问题描述:

& https:// docs上的AudioGraph文档.microsoft.com / zh-CN / windows / uwp / audio-video-camera / audio-graphs 表示访问音频数据不安全,
需要非托管内存访问,如下面的示例代码所示: / p>

The AudioGraph documentation at https://docs.microsoft.com/en-us/windows/uwp/audio-video-camera/audio-graphs indicates that accessing audio data is unsafe and requires unmanaged memory access as with the following sample code:

[ComImport]
[Guid("5B0D3235-4DBA-4D44-865E-8F1D0E4FD04D")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
unsafe interface IMemoryBufferByteAccess
{
    void GetBuffer(out byte* buffer, out uint capacity);
}

private double audioWaveTheta = 0;

unsafe private AudioFrame GenerateAudioData(uint samples)
{
    // Buffer size is (number of samples) * (size of each sample)
    // We choose to generate single channel (mono) audio. For multi-channel, multiply by number of channels
    uint bufferSize = samples * sizeof(float);
    AudioFrame frame = new Windows.Media.AudioFrame(bufferSize);

    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);

        // Cast to float since the data we are generating is float
        dataInFloat = (float*)dataInBytes;

        float freq = 1000; // choosing to generate frequency of 1kHz
        float amplitude = 0.3f;
        int sampleRate = (int)audioGraph.EncodingProperties.SampleRate;
        double sampleIncrement = (freq * (Math.PI * 2)) / sampleRate;

        // Generate a 1kHz sine wave and populate the values in the memory buffer
        for (int i = 0; i < samples; i++)
        {
            double sinValue = amplitude * Math.Sin(audioWaveTheta);
            dataInFloat[i] = (float)sinValue;
            audioWaveTheta += sampleIncrement;
        }
    }

    return frame;
}

虽然看起来很清楚对象因为实现了Dispose方法而被清理了,但是不清楚如何处理由GetBuffer方法。 具体来说,dataInBytes和dataInFloat指针。

While it seems clear that the objects get cleaned up since they implement the Dispose method, it is not clear how to handle the memory that is allocated by the GetBuffer method.  Specifically, the dataInBytes, and dataInFloat pointers.

调用以下内容会引发异常:

Calling the following throws an exception:

System.Runtime.InteropServices.Marshal.FreeHGlobal((IntPtr)dataInBytes);

那么,我们如何释放非托管内存? 并且,在释放之后我们如何强制进行垃圾收集? 换句话说,WinRT中Free()和GC.Collect()的等价物是什么?

So, how do we free up the unmanaged memory?  And, after freeing it how do we force a garbage collection?  In other words what is the equivalent of Free() and GC.Collect() in WinRT?

Steven Edward Wood计算机工程师

Steven Edward Wood Computer Engineer



你不应该,在这个例子中,他们只是引用框架中的数据

You should not, in this exaple they are just references to data in frame

AudioFrame frame = new Windows.Media.AudioFrame(bufferSize);


Windows.Media .AudioFrame实现了IDisposable,你可以调用frame.Dispose()来释放内存。

Windows.Media.AudioFrame implements IDisposable and you can just call frame.Dispose() to free memory.