yun
yun

Reputation: 1283

Android OpenSL Audio Buffer underrun with native sample rate/buffer size (only some devices)

Looks like I'm getting an issue of crackling/glitchy audio (basically when a buffer doesn't get filled up/callback doesn't finish in time/buffer underrun situation) even after setting the device's preferred sample rate and buffer size while using OpenSL ES.

I've tested on a Nexus 7 (2013 model) and a Moto X Pure Edition and they both work fine (using a sample rate of 48 kHz and buffer size of 240 and 960 respectively). Maybe there's like a glitch every minute or so but it's so few I've come to terms with living with it. However, when I'm using a Samsung Galaxy S7, I'm getting a ton of audio glitches every second (this is also at 48 kHz and 960 frames per buffer). I've checked and the audio callback always finishes within the correct time (20 ms); therefore I can say that there is no buffer underrun.

The weird issue is that if I set the Samsung to use a sample rate of 44.1 kHz and buffer size of 128, there's no audio glitches (except for a small interrupt which I'm guessing deals with the incorrect native sample rate).

Why is this happening and how can I fix it so that the native audio properties work?

Thanks!

EDIT: Maybe I'm mixing the terminology up (buffer underrun and overflow) so if someone wants to come in and correct me on that go ahead!!! learning is power

Upvotes: 3

Views: 1051

Answers (1)

WLGfx
WLGfx

Reputation: 1179

I'm not sure how you'd be able to adapt this to your purpose but here's how I did it:

The SLES callback function:

void AudioManager::sles_callback(SLAndroidSimpleBufferQueueItf itf, void *ptr) {
    AudioManager *manager = (AudioManager*)ptr;
    manager->audio_queue_playing = false;
    manager->check_audio_playback(); // the actual function to queue buffers
}

Checking for another audio buffer availability:

void AudioManager::check_audio_playback() {
    // mutex used to only allow one thread access at a time
    pthread_mutex_lock(&audio_callback_mutex); // block access to renderer or callback

    if (audio_queue_playing || playback_pos == decode_pos) {
        pthread_mutex_unlock(&audio_callback_mutex);
        return;
    }

    double audio_pts = pts_start_time;
    double render_time = Display.get_current_render_time();

    AudioBuffer *buffer = nullptr;

    if (last_played_buffer) {
        last_played_buffer->used = false;
        buffer = &buffers[playback_pos];
        //(*buffer_interface)->Enqueue(buffer_interface, buffer->data, (SLuint32)(buffer->nsamples << 2));
        //audio_queue_playing = true;
        last_played_buffer = buffer;
        playback_pos = (++playback_pos) % MAX_AUD_BUFFERS;
        //return;
    }

    if (audio_pts < 0.0) {
        if (ffmpeg.vid_stream.stream_id == -1) {    // start playback
            pts_start_time = buffers[playback_pos].frame_time;
            audio_pts = pts_start_time;
            sys_start_time = render_time;
        }
    }

    AudioBuffer *temp = nullptr;

    double current_time = render_time - sys_start_time;

    bool bounds = false;
    double temp_time;

    while (!bounds) {
        if (playback_pos == decode_pos) bounds = true;
        else {
            temp = &buffers[playback_pos];
            temp_time = temp->frame_time - audio_pts;

            if (temp_time < current_time) {
                if (buffer) buffer->used = false;
                buffer = temp;
                playback_pos = (++playback_pos) % MAX_AUD_BUFFERS;
            } else {
                bounds = true;
            }
        }
    }

    if (buffer) {
        audio_queue_playing = true;
        (*buffer_interface)->Enqueue(buffer_interface, buffer->data, (SLuint32)(buffer->nsamples << 2));
        last_played_buffer = buffer;
    } else {
        last_played_buffer = nullptr;
    }

    pthread_mutex_unlock(&audio_callback_mutex);
}

And then on every frame update (ie. in my screen renderer 60 times a second) I call the check_audio_playback(). If buffers are playing then the function exits.

Fingers crossed this will help you along.

Upvotes: 1

Related Questions