如何将 float* 复制到 IntPtr?

How to copy float* to IntPtr?

我的任务的简短描述:

作为函数的参数,我得到了一些缓冲区 (IntPtr)。

我需要从此缓冲区中提取一些信息并将信息复制到 audioFrame.AudioBuffer 缓冲区 (IntPtr)。

问题:

需要的信息放在channelData[c](float*)中,我需要把这些信息复制到destStart(IntPtr)中。

代码:

private void SomeFunc(IntPtr buffer)
{

...
AudioFrame audioFrame; // audioFrame.AudioBuffer is IntPtr
...

unsafe
{
    float** channelData = (float**)buffer.ToPointer();
    for (int c = 0; c < 2; c++)
    {
        IntPtr destStart = new IntPtr(audioFrame.AudioBuffer.ToInt64() + (c * audioFrame.ChannelStride));
        Marshal.Copy(channelData[c], 0, destStart, audioFrame.NumSamples); ///< problem in this line, channelData[c] is float*
    }
}

...

}

编辑 更多上下文:我从 CEF (https://github.com/cefsharp/CefSharp). In fact this function work as callback. When I got new audio data I need to send this data throught NDI (https://www.ndi.tv/)

获得了这个缓冲区

AudioFrame 是 NDI 结构的包装器

public struct audio_frame_v2_t
    {
    // The sample-rate of this buffer
    public int  sample_rate;

    // The number of audio channels
    public int  no_channels;

    // The number of audio samples per channel
    public int  no_samples;

    // The timecode of this frame in 100ns intervals
    public Int64    timecode;

    // The audio data
    public IntPtr   p_data;

    // The inter channel stride of the audio channels, in bytes
    public int  channel_stride_in_bytes;

    // Per frame metadata for this frame. This is a NULL terminated UTF8 string that should be
    // in XML format. If you do not want any metadata then you may specify NULL here.
    public IntPtr   p_metadata;

    // This is only valid when receiving a frame and is specified as a 100ns time that was the exact
    // moment that the frame was submitted by the sending side and is generated by the SDK. If this
    // value is NDIlib_recv_timestamp_undefined then this value is not available and is NDIlib_recv_timestamp_undefined.
    public Int64    timestamp;
}

也许在这里考虑跨度:

var fromSpan = new Span<float>(channelData[c], audioFrame.NumSamples);
var toSpan = new Span<float>(destStart.ToPointer(), audioFrame.NumSamples);
fromSpan.CopyTo(toSpan);

Buffer.MemoryCopy:

var size = sizeof(float) * audioFrame.NumSamples;
Buffer.MemoryCopy(channelData[c], destStart.ToPointer(), size, size);

(请注意,在这两种情况下,最好包括 实际 缓冲区大小的知识,以避免缓冲区溢出情况;我只是假设为简单起见,大小是有效的;还有 Unsafe.CopyBlock,它的工作方式很像 Buffer.MemoryCopy)