Audio I';我有音频样本;如何使用SDL正确播放它们?

Audio I';我有音频样本;如何使用SDL正确播放它们?,audio,sdl,libretro,Audio,Sdl,Libretro,我正在为核心编写一个非常简单的前端,我正在攻击音频部分,这是最难的部分(我以前从未处理过任何与声音相关的事情,所以很可能我完全搞错了) 按照它的工作方式,libretro内核定期调用一个函数原型,因为我必须自己实现: typedef size_t (*retro_audio_sample_batch_t)(const int16_t *data, size_t count); data参数是交错立体声数据的数组({Left,Right,Left,…}),而count是采样数(因此数组元素计数实

我正在为核心编写一个非常简单的前端,我正在攻击音频部分,这是最难的部分(我以前从未处理过任何与声音相关的事情,所以很可能我完全搞错了)

按照它的工作方式,libretro内核定期调用一个函数原型,因为我必须自己实现:

typedef size_t (*retro_audio_sample_batch_t)(const int16_t *data, size_t count);
data
参数是交错立体声数据的数组(
{Left,Right,Left,…}
),而
count
是采样数(因此数组元素计数实际上是count*2)

以下是我目前对这些数据所做的操作:

  • 当libretro core向我发送样本时
    • 我只是将它们连接到音频缓冲区
  • 当SDL调用我的音频回调方法时,
    • 我从音频缓冲区向流缓冲区复制所需和可用的数据
    • 如果没有足够的数据可用,我将用0填充流缓冲区的其余部分
    • 如果我的缓冲区有比请求的更多的数据,我只需删除刚才播放的内容并保留其余的内容
然而,我得到的并不正确。尽管有点可识别,但声音杂乱无章,充满了噪音。我不确定我到底遗漏了什么:似乎RetroArch前端(libretro核心的官方前端)正在进行某种重采样,但我不知道它是什么。是否需要重新采样?我能从中得到一些问题吗

以下是我的个人简历,部分转载如下:

static int16_t * g_audio_samples = NULL;
static size_t g_audio_sample_count = 0;

static void audio_write( int16_t const * samples, size_t count )
{
    SDL_LockAudio( );

    int16_t * previous_samples = g_audio_samples;
    size_t previous_count = g_audio_sample_count;

    g_audio_sample_count = previous_count + count;
    g_audio_samples = calloc( g_audio_sample_count * 2, sizeof( int16_t ) );

    for ( size_t index = 0; index < previous_count; ++ index )
        g_audio_samples[ index ] = previous_samples[ index ];

    for ( size_t index = 0; index < count; ++ index )
        g_audio_samples[ previous_count + index ] = samples[ index ];

    free( previous_samples );

    SDL_UnlockAudio( );
}

static void audio_callback( void * userdata, Uint8 * stream, int length )
{
    int16_t * available_samples = g_audio_samples;
    size_t available_sample_count = g_audio_sample_count;

    size_t requested_sample_count = length / 2;
    size_t requested_byte_length = requested_sample_count * 2;

    size_t providen_sample_count = requested_sample_count < available_sample_count ? requested_sample_count : available_sample_count;
    size_t providen_byte_length = providen_sample_count * 2;

    memcpy( stream, available_samples, providen_byte_length );
    memset( stream + providen_byte_length, 0, requested_byte_length - providen_byte_length );

    g_audio_samples = NULL;
    g_audio_sample_count = 0;

    if ( providen_sample_count < available_sample_count )
        audio_write( available_samples + providen_sample_count, available_sample_count - providen_sample_count );

    free( available_samples );
}

size_t bridge_virtjs_audio_push_sample_batch( int16_t const * samples, size_t count )
{
    audio_write( samples, count );

    return count;
}
static int16\u t*g\u audio\u samples=NULL;
静态大小\u t g\u音频\u样本\u计数=0;
静态无效音频写入(int16常量*样本、大小计数)
{
SDL_LockAudio();
int16_t*先前的_样本=g_音频_样本;
大小\u t先前的\u计数=g\u音频\u样本\u计数;
g_音频_样本_计数=上一次_计数+计数;
g_audio_samples=calloc(g_audio_sample_count*2,sizeof(int16_t));
对于(大小索引=0;索引<以前的计数;++索引)
g_音频_样本[索引]=以前的_样本[索引];
用于(大小索引=0;索引<计数;++索引)
g_音频_样本[上一次计数+索引]=样本[索引];
免费(以前的样品);
SDL_解锁音频();
}
静态void audio_回调(void*userdata,Uint8*stream,int-length)
{
int16_t*可用_样本=g_音频_样本;
大小可用样本计数=g音频样本计数;
所需尺寸、样本数量=长度/2;
大小\请求的\字节\长度=请求的\样本\计数*2;
大小\公积金\样本\计数=请求\样本\计数<可用\样本\计数?请求\样本\计数:可用\样本\计数;
大小\u t providen\u字节\u长度=providen\u样本\u计数*2;
memcpy(流、可用样本、providen字节长度);
memset(流+providen字节长度,0,请求的字节长度-providen字节长度);
g_audio_samples=NULL;
g_音频_样本_计数=0;
if(普罗维登斯样本计数<可用样本计数)
音频写入(可用样本+providen样本计数,可用样本计数-providen样本计数);
免费(可提供样品);
}
大小\u t桥接\u virtjs\u音频\u推送\u样本\u批(int16 \u t const*样本,大小\u t计数)
{
音频写入(样本、计数);
返回计数;
}