将IntPtr转换为音频数据数组

时间:2018-07-24 19:04:47

标签: c# pointers unity3d audio webrtc

我一直在尝试在Unity上实现WebRTC音频/视频通信。到目前为止,借助this blog post(和Google翻译)以及互联网上的极少数示例,我已经成功地使用WebRTC Unity Plugin在Unity上做了很多工作

但是现在我被卡住了。令人遗憾的是, mhama 编写的出色的Unity示例项目没有一个示例,该示例如何将我从本机代码获得的数据转换为可用作Unity中的音频数据的内容。


我从回调中获得的信息是

(IntPtr data, int bitsPerSample, int sampleRate, int numberOfChannels, int numberOfFrames)

将本机代码中的数据声明为

const void* audio_data

我知道要创建一个Unity可以用来播放声音的音频剪辑,我需要一个float数组,其中包含-1 to 1中的示例值。我不知道该如何做,如何从这些IntPtr数据和所有这些额外的信息到该float数组。

Here's the sample I'm using as a base

1 个答案:

答案 0 :(得分:0)

I'm not sure you can do this without unsafe code. You'll need to make sure your project has unsafe code allowed.

// allocate the float arrays for the output. 
// numberOfChannels x numberOfFrames
float[][] output = new float[numberOfChannels][];
for (int ch = 0 ; ch < numberOfChannels; ++ch)
    output[ch] = new float[numberOfFrames];

// scaling factor for converting signed PCM into float (-1.0 to 1.0)
const double scaleIntToFloat = 1.0/0x7fffffff;

unsafe 
{ 
    // obtain a pointer to the raw PCM audio data.
    byte *ptr = (byte *)data.ToPointer();

    for (int frame = 0 ; frame < numberOfFrames; ++frame)
    {
        for (int ch = 0 ; ch < numberOfChannels; ++ch)
        {
            switch (bitsPerSample)
            {
                case 32:
                   // shift 4 bytes into the integer value
                   int intValue = *ptr++ << 24 & *ptr++ << 16 &
                                  *ptr++ << 8 & *ptr++;
                   // scale the int to float and store.
                   output[ch][frame] = scaleIntToFloat * intValue;
                   break;
                case 16: 
                   // shift 2 bytes into the integer value. Note:
                   // shifting into the upper 16 bits to simplify things,
                   // e.g. multiply by the same scaling factor.
                   int intValue = *ptr++ << 24 & *ptr++ << 16; 
                   output[ch][frame] = scaleIntToFloat * intValue;
                   break;
                case 24:
                   ...
                case 8:
                   // not 8-bit is typically unsigned. Google it if
                   // you need to.
            }
        }
    }
}

You can find the other conversions by searching this site for conversion of PCM to float. Also, depending on your circumstances, you might need a different endianness. If so, shift into the intValue in a different byte order.