I've got audio samples; how to play them correctly with the SDL?

I'm in the process of writing a very simple frontend for the libretro cores, and I'm attacking the audio part, the hardest (I never ever dealt with anything sound-related before, so it's very possible that I got it totally wrong).

The way it works, the libretro cores regularly call a function prototyped as such, as I have to implement myself:

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

The data parameter is an array of interlaced stereo data ( { Left, Right, Left, ...} ), and count is the number of samples (so the array element count is actually count * 2).

Here is what I currently do with these data:

  • When the libretro core is sending me samples
  • I just concatenate them to an audio buffer
  • When the SDL is calling my audio callback method,
  • I copy as much as requested and available from the audio buffer to the stream buffer
  • If not enough data are available, I fill the rest of the stream buffer with 0's
  • If my buffer has more data than requested, I just remove what I just played and keep the rest
  • However, what I get isn't right. Despite being somewhat recognizable, the sound is garbled and full of noise. I'm not sure exactly about what I might be missing : it seems that the RetroArch frontend (the official frontend for the libretro cores) is doing some sort of resampling, but I have no idea what it is. Is resampling required? Can me issues come from that?

    Here is my full code, partly reproduced below:

    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;
    }
    
    链接地址: http://www.djcxy.com/p/33826.html

    上一篇: 如何对SDL2音频流数据执行实时FFT?

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