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

时间:2015-06-13 10:09:00

标签: audio sdl libretro

我正在为libretro内核编写一个非常简单的前端,我正在攻击音频部分,这是最难的(我之前从未处理过任何声音相关的内容,所以它非常可能我完全错了。)

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

typedef size_t (*retro_audio_sample_batch_t)(const int16_t *data, size_t count);

data参数是隔行立体声数据({ Left, Right, Left, ...})的数组,count是样本数(因此数组元素数实际上是计数* 2)。 / p>

以下是我目前对这些数据的处理方式:

  • 当libretro核心向我发送样品时
    • 我只是将它们连接到音频缓冲区
  • 当SDL调用我的音频回调方法时,
    • 我尽可能多地复制请求并从音频缓冲区复制到流缓冲区
    • 如果没有足够的数据可用,我用0的
    • 填充流缓冲区的其余部分
    • 如果我的缓冲区有超过请求的数据,我只删除我刚刚播放的内容并保留其余内容

然而,我得到的是不对的。虽然有点识别,声音是乱码和充满噪音。我不确定我可能会遗漏什么:似乎RetroArch前端(libretro核心的官方前端)正在进行某种重新采样,但我不知道它是什么。需要重新取样吗?我可以提出问题吗?

这是我的full code,部分转载如下:

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;
}

0 个答案:

没有答案