OpenSL ES FileDescriptor 객체를 사용하여 오디오 자산에서 바이트 버퍼를 가져오고 싶습니다. 따라서 SL 인터페이스를 사용하여 파일 재생/중지/탐색 대신 반복적으로 SimpleBufferQueue에 큐에 넣을 수 있습니다.OpenSL ES (Android 용)의 오디오 자산에서 직접 바이트 버퍼를 가져올 수 있습니까?
내가 직접 샘플 바이트를 관리하려는 이유 세 가지 이유가 있습니다 :
- OpenSL는 플레이어 개체에 대한 등/정지/재생하는 AudioTrack 층을 사용하는가. 이것은 원하지 않는 오버 헤드를 초래할뿐만 아니라 몇 가지 버그가 있으며 플레이어의 빠른 시작/정지로 인해 많은 문제가 발생합니다.
- 사용자 정의 DSP 효과를 위해 직접 바이트 버퍼를 조작해야합니다.
- 재생할 클립이 작아서 파일 I/O 오버 헤드를 피하기 위해 메모리에 모두로드 할 수 있습니다. 또한 내 버퍼를 대기열에 추가하면 출력 싱크에 0을 쓰고 대기 시간을 줄이고 AudioTrack을 중지, 일시 중지 및 재생하는 대신 재생할 때 샘플 바이트로 간단히 전환 할 수 있습니다. 전체
좋아, 정당화는 - 여기에 내가 무엇을 시도했다입니다 - 나는 본질적으로, 입력 및 출력 트랙을 포함하는 샘플 구조체 및 샘플을 보유하는 바이트 배열을 가지고있다. 입력은 My FileDescriptor 플레이어이고 출력은 SimpleBufferQueue 객체입니다. 여기 내 구조체의 : fdPlayerObject 파일 플레이어 를 초기화 한 후
typedef struct Sample_ {
// buffer to hold all samples
short *buffer;
int totalSamples;
SLObjectItf fdPlayerObject;
// file descriptor player interfaces
SLPlayItf fdPlayerPlay;
SLSeekItf fdPlayerSeek;
SLMuteSoloItf fdPlayerMuteSolo;
SLVolumeItf fdPlayerVolume;
SLAndroidSimpleBufferQueueItf fdBufferQueue;
SLObjectItf outputPlayerObject;
SLPlayItf outputPlayerPlay;
// output buffer interfaces
SLAndroidSimpleBufferQueueItf outputBufferQueue;
} Sample;
및 malloc에 - 보내고
sample->buffer = malloc(sizeof(short)*sample->totalSamples);
내가
// get the buffer queue interface
result = (*(sample->fdPlayerObject))->GetInterface(sample->fdPlayerObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &(sample->fdBufferQueue));
와의 BufferQueue 인터페이스를 얻고 내 바이트 버퍼 메모리를 출력 플레이어 :
를 인스턴스화합니다. 내가 샘플을 재생하려면 16,// create audio player for output buffer queue
const SLInterfaceID ids1[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE};
const SLboolean req1[] = {SL_BOOLEAN_TRUE};
result = (*engineEngine)->CreateAudioPlayer(engineEngine, &(sample->outputPlayerObject), &outputAudioSrc, &audioSnk,
1, ids1, req1);
// realize the output player
result = (*(sample->outputPlayerObject))->Realize(sample->outputPlayerObject, SL_BOOLEAN_FALSE);
assert(result == SL_RESULT_SUCCESS);
// get the play interface
result = (*(sample->outputPlayerObject))->GetInterface(sample->outputPlayerObject, SL_IID_PLAY, &(sample->outputPlayerPlay));
assert(result == SL_RESULT_SUCCESS);
// get the buffer queue interface for output
result = (*(sample->outputPlayerObject))->GetInterface(sample->outputPlayerObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
&(sample->outputBufferQueue));
assert(result == SL_RESULT_SUCCESS);
// set the player's state to playing
result = (*(sample->outputPlayerPlay))->SetPlayState(sample->outputPlayerPlay, SL_PLAYSTATE_PLAYING);
assert(result == SL_RESULT_SUCCESS);
, 내가 사용하고 있습니다 :
Sample *sample = &samples[sampleNum];
// THIS WORKS FOR SIMPLY PLAYING THE SAMPLE, BUT I WANT THE BUFFER DIRECTLY
// if (sample->fdPlayerPlay != NULL) {
// // set the player's state to playing
// (*(sample->fdPlayerPlay))->SetPlayState(sample->fdPlayerPlay, SL_PLAYSTATE_PLAYING);
// }
// fill buffer with the samples from the file descriptor
(*(sample->fdBufferQueue))->Enqueue(sample->fdBufferQueue, sample->buffer,sample->totalSamples*sizeof(short));
// write the buffer to the outputBufferQueue, which is already playing
(*(sample->outputBufferQueue))->Enqueue(sample->outputBufferQueue, sample->buffer, sample->totalSamples*sizeof(short));
그러나,이 동결하고 종료하는 내 응용 프로그램을 발생합니다. 뭔가 잘못되었습니다. 또한, 나는 File Descriptor의 BufferQueue에서 매번 샘플을 얻지 않는 것을 선호합니다. 대신, 영구적으로 바이트 배열에 저장하고 원하는 때마다 출력에 큐에 넣고 싶습니다.
안녕하세요 khiner, 자바 바이트 또는 짧은 배열의 자산 폴더에서 .wav 파일을 읽고 더 처리하는 데 도움이 될까요? –
내가 얼마나 도울 수 있는지는 확실하지 않지만 기록만을 위해 - NDK를 사용하고 있습니까? 그게 당신의 코드가 C++에있는 이유입니까? – Erhannis
네, 저는 NDK를 사용하고 있습니다. 이것은 실제로 순수한 C입니다.이 질문은 오랜 시간이 걸리고 있습니다. 나는 이것에 대한 많은 진전을 이뤄 냈으며 괜찮은 대답을 추가하려고 노력할 것입니다. – khiner