2016-10-18 9 views
0

기본적으로 버퍼가 채워지지 않을 때/콜백이 완료되지 않는 것처럼 보이는 문제가 발생합니다. in-time/buffer underrun 상황)에 대해서도 OpenSL ES를 사용하는 동안 장치의 선호 샘플링 속도와 버퍼 크기를 설정 한 후에도 가능합니다.네이티브 샘플 속도/버퍼 크기 (일부 장치 만 해당)가있는 OpenSL 오디오 버퍼 언더런

Nexus 7 (2013 모델) 및 Moto X Pure Edition에서 테스트했으며 두 샘플 모두 48kHz의 샘플 속도와 각각 240 및 960의 버퍼 크기를 사용하여 정상적으로 작동합니다. 어쩌면 매 순간마다 결함이 생길 수도 있지만 너무 적 으면서도 그걸로 살아가는 용어를 찾지 못했습니다. 그러나 삼성 갤럭시 S7을 사용할 때 매초마다 1 초당 오디오 결함이 발생합니다 (이 또한 48kHz와 960 프레임/버퍼). 내가 확인한 오디오 콜백은 항상 올바른 시간 (20 ms) 내에 완료됩니다. 따라서 버퍼 언더런이 없다고 말할 수 있습니다.

이상한 문제는 삼성이 44.1kHz의 샘플링 속도와 128의 버퍼 크기를 사용하도록 설정하면 음성 오류가 발생하지 않는다는 것입니다 (잘못된 기본 샘플 속도를 처리하는 작은 인터럽트 제외).).

왜 이런 일이 발생하며 어떻게 수정하여 기본 오디오 속성이 작동 할 수 있습니까?

감사합니다.

EDIT : 어쩌면 나는 버퍼 언더런 (buffer underrun)과 오버플로 (overflow)라는 용어를 섞어서 누군가가 들어 와서 교정 해 주길 원한다. 학습은 당신이 당신의 목적이 적응할 수있을 거라고 확실하지 않아요 전원

+0

콜백을 사용하여 새 버퍼를 큐에 넣고 있습니까? – WLGfx

+0

@WLGfx 나는 내가 그 일을하고 있음을 확신한다. (잘못 일 수있다, 나는 모든 것이 어떻게 작동하는지에 대한 나의 이해를 인정한다.) 이 클래스를 사용하여 콜백 및 오디오 스트림을 설정했습니다. https://github.com/superpoweredSDK/audioIO/blob/master/SuperpoweredAndroidAudioIO.cpp –

+0

버퍼가 완료된 후 콜백이 호출되지 않습니다. 버퍼가 완성되어 여러분에게 다른 큐를 대기시킬 수 있습니다. 다른 대기열을 수동으로 추가 한 다음 콜백을 다시 시작해야합니다. 버퍼를 큐에 넣을 때 콜백이 호출 되더라도 다른 버퍼를 준비 할 충분한 시간이 없을 수 있습니다. 내 프로젝트에서, 모든 스크린 업데이트는 슬레 스가 재생 중인지를 확인하고 그렇지 않으면 수동으로 다른 버퍼를 큐에 추가합니다. – WLGfx

답변

0

하지만 여기에 내가했던 방법 : 서로에 대한 확인

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 
} 

:

SLES 콜백 함수를 오디오 버퍼 가용성 :

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

그리고 모든 프레임 업데이트에 (. 즉, 내 스크린 렌더러에서 1 초에 60 번) 나는 check_audio_playback()를 호출한다. 버퍼가 재생 중이면 함수가 종료됩니다.

손가락을 건 드리면 도움이됩니다.

+0

고마워요! 나는 일단 모든 것을 이해하면 다시보고 할 것입니다! –