Похоже, у меня проблема с потрескивающим / сбойным звуком (в основном, когда буфер не заполняется / обратный вызов не завершается во время / переполнение буфера) даже после установки предпочтительной частоты дискретизации устройства и размера буфера при использовании OpenSL ES.
Я тестировал Nexus 7 (модель 2013 года) и Moto X Pure Edition, и они оба работают нормально (с частотой дискретизации 48 кГц и размером буфера 240 и 960 соответственно). Может быть, что-то вроде сбоя каждую минуту или около того, но так мало, что я смирился с этим жить. Однако, когда я использую Samsung Galaxy S7, я получаю тонну глюков звука каждую секунду (это также при 48 кГц и 960 кадрах на буфер). Я проверил, и аудио обратный вызов всегда завершается в течение правильного времени (20 мс); поэтому могу сказать, что нет опустошения буфера.
Странная проблема заключается в том, что, если я настрою Samsung на использование частоты дискретизации 44,1 кГц и размера буфера 128, то нет никаких глюков звука (за исключением небольшого прерывания, которое, как я предполагаю, связано с неправильной собственной частотой дискретизации).
Почему это происходит и как я могу это исправить, чтобы нативные свойства звука работали?
Спасибо!
РЕДАКТИРОВАТЬ: Возможно, я смешиваю терминологию (переполнение буфера и переполнение), так что если кто-то захочет войти и исправить меня, продолжайте !!! обучение это сила
Я не уверен, как вы сможете адаптировать это к вашей цели, но вот как я это сделал:
Функция обратного вызова SLES:
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
}
Проверка наличия другого аудио буфера:
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);
}
И затем при каждом обновлении кадра (т.е. в моем рендерере экрана 60 раз в секунду) я вызываю check_audio_playback (). Если воспроизводятся буферы, то функция завершается.
Скрещенные пальцы это поможет вам в этом.
Других решений пока нет …