首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将int16声音示例数组转换为用于单游戏/XNA的字节数组

如何将int16声音示例数组转换为用于单游戏/XNA的字节数组
EN

Stack Overflow用户
提问于 2015-08-12 06:08:05
回答 2查看 1.5K关注 0票数 2

我在C#/MonoGame中写了一个libretro前端,我成功地获得了一个粗糙的(但正在工作的)视频闪光灯,但现在我在与声音作斗争。

来自API:

代码语言:javascript
复制
/* Renders multiple audio frames in one go.
 *
 * One frame is defined as a sample of left and right channels, interleaved.
 * I.e. int16_t buf[4] = { l, r, l, r }; would be 2 frames.
 * Only one of the audio callbacks must ever be used.
 */
typedef size_t (*retro_audio_sample_batch_t)(const int16_t *data,
      size_t frames);

因此,样本是有符号16位整数。我试图像这样使用流中的SoundEffect:

代码语言:javascript
复制
        int size = SoundEffect.GetSampleSizeInBytes(TimeSpan.FromMilliseconds((float)1000/(int)_libretro.GetAVInfo().timing.fps), (int)_libretro.GetAVInfo().timing.sample_rate, AudioChannels.Mono);           
        data = _libretro.GetSoundBuffer().data;

        byte[] buffer = new byte[size];
        for (int i = 0; i < size -1 ; i+=2)
        {
            Int16 chunk = Marshal.ReadInt16(data);

            byte b1 = (byte)(chunk);
            byte b2 = (byte)(chunk >> 8);
            buffer[i+1] = b1;
            buffer[i] = b2;

            //move ahead 4 bytes skipping the second sound channel for now
            data = data + (sizeof(byte)*4);
        }

        SoundEffect sound_left = new SoundEffect(buffer, (int)_libretro.GetAVInfo().timing.sample_rate, AudioChannels.Mono);
        sound_left.Play();

而且我的声音越来越好,声音模式很明显是可分辨的,但是它被混淆了,你看到我的实现有什么问题了吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-02-10 05:13:59

此方法将将样本数据转换为字节数组。它适用于任何频道计数(测试单声道和立体声)。

代码语言:javascript
复制
    public static byte[] GetSamplesWaveData(float[] samples, int samplesCount)
    {
        var pcm = new byte[samplesCount * 2];
        int sampleIndex = 0,
            pcmIndex = 0;

        while (sampleIndex < samplesCount)
        {
            var outsample = (short)(samples[sampleIndex] * short.MaxValue);
            pcm[pcmIndex] = (byte)(outsample & 0xff);
            pcm[pcmIndex + 1] = (byte)((outsample >> 8) & 0xff);

            sampleIndex++;
            pcmIndex += 2;
        }

        return pcm;
    }

请注意,float[] samples值应该在[-1;1]范围内。

票数 3
EN

Stack Overflow用户

发布于 2015-08-12 06:16:29

实际上,我并不确定,但既然您获得了b1 a b2,并且您使用了b1两次,也许您只是错误地写了b1而不是b2:

代码语言:javascript
复制
byte b1 =(byte)(chunk);
byte b2 = (byte)(chunk << 8);
buffer[i] = b1;//thats b1
buffer[i+1] = b1;//thats b1 again

也许你需要这样的东西:

代码语言:javascript
复制
buffer[i+1] = b2;

但我不确定你想做什么,所以我不知道我的答案是否有任何关联。

UPDATE现在我确实理解了,您正在将16位int转换成两个字节。所以正确的语法是:

代码语言:javascript
复制
byte b1 =(byte)(chunk);
byte b2 = (byte)(chunk >> 8); 

因为谈话总是最不重要的部分,所以你需要避开它。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31957211

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档