Short description of my task:
As parameter of my function I got some buffer (IntPtr).
I need to extract some information from this buffer and copy information to audioFrame.AudioBuffer buffer (IntPtr).
Problem:
Needed information placed in channelData[c] (float*), I need to copy this information to destStart (IntPtr).
Code:
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*
}
}
...
}
Edit Little more context: I got this buffer from 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 is wrapper over the NDI structure
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;
}
Perhaps consider spans here:
var fromSpan = new Span<float>(channelData[c], audioFrame.NumSamples);
var toSpan = new Span<float>(destStart.ToPointer(), audioFrame.NumSamples);
fromSpan.CopyTo(toSpan);
Or Buffer.MemoryCopy
:
var size = sizeof(float) * audioFrame.NumSamples;
Buffer.MemoryCopy(channelData[c], destStart.ToPointer(), size, size);
(note that in both cases it would be better to include knowledge of the actual buffer sizes if you have it, to avoid buffer overflow scenarios; I've just assumed the sizes are valid, for simplicity; there's also Unsafe.CopyBlock
which works a lot like Buffer.MemoryCopy
)