如何将 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
)
我的任务的简短描述:
作为函数的参数,我得到了一些缓冲区 (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
)