Audio I';我有音频样本;如何使用SDL正确播放它们?
我正在为核心编写一个非常简单的前端,我正在攻击音频部分,这是最难的部分(我以前从未处理过任何与声音相关的事情,所以很可能我完全搞错了) 按照它的工作方式,libretro内核定期调用一个函数原型,因为我必须自己实现: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是采样数(因此数组元素计数实
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填充流缓冲区的其余部分
- 如果我的缓冲区有比请求的更多的数据,我只需删除刚才播放的内容并保留其余的内容
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计数)
{
音频写入(样本、计数);
返回计数;
}