Chciałbym uzyskać bufor bajtowy z zasobu audio za pomocą obiektu OpenSL ES FileDescriptor, więc mogę go wielokrotnie zamieniać w kolejkę do SimpleBufferQueue, zamiast używać interfejsów SL do odtwarzania/zatrzymywania/wyszukiwania pliku.Czy można uzyskać bufor bajtów bezpośrednio z zasobu audio w OpenSL ES (dla systemu Android)?
Istnieją trzy główne powody, dla których chciałbym bezpośrednio zarządzać bajtów przykładowe:
- OpenSL wykorzystuje warstwę AudioTrack do PLAY/STOP/etc na odtwarzacz obiektów. To nie tylko wprowadza niepożądane obciążenie, ale także ma kilka błędów, a szybkie uruchamianie/zatrzymywanie odtwarzacza powoduje wiele problemów.
- Potrzebuję manipulować bezpośrednio buforem bajtowym dla niestandardowych efektów DSP.
- Klipy, które będę odtwarzać, są małe i wszystkie mogą być załadowane do pamięci, aby uniknąć narzutu we/wy pliku. Dodatkowo, zapisywanie własnych buforów pozwoli mi zmniejszyć opóźnienie, pisząc 0 do wyjściowego zlewu, i po prostu przełączając się na bajty przykładowe podczas odtwarzania, zamiast ZATRZYMYĆ, WSTRZYMAĆ i ODTWARZAĆ ścieżkę dźwiękową.
porządku, więc uzasadnienia Complete - oto co próbowałem - Mam Sample struct, który zawiera w istocie ścieżkę wejścia i wyjścia oraz tablicę bajtów do przechowywania próbek. Wejście to mój odtwarzacz FileDescriptor, a wyjście to obiekt SimpleBufferQueue. Oto mój struct:
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;
po uruchomieniu odtwarzacza plików fdPlayerObject i malloc-ing pamięci dla mojego bufora bajtów z
sample->buffer = malloc(sizeof(short)*sample->totalSamples);
Dostaję jego interfejs BufferQueue z
// get the buffer queue interface
result = (*(sample->fdPlayerObject))->GetInterface(sample->fdPlayerObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &(sample->fdBufferQueue));
Następnie tworzę egzemplarz wyjściowy :
// 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);
Gdy chcę odtworzyć próbkę, używam:
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));
Jednak to powoduje mój app zamrozić i zamknięty. Coś tu nie gra. Również, Wolałbym nie pobierać próbek z bufora bufora deskryptorów plików za każdym razem. Zamiast tego chciałbym na stałe zapisać go w tablicy bajtów i dodać go do wyjścia, kiedy tylko zechcę.
Witaj khiner, czy pomogłoby Ci odczytać pliki .wav z folderu zasobów w bajcie Java lub krótkiej tablicy, a następnie przetworzyć to dalej? –
Nie jestem pewien, ile mogę pomóc, ale tylko dla nagrania - czy używasz NDK? Czy to dlatego Twój kod jest w C++? – Erhannis
Tak, używam NDK, a to jest rzeczywiście czysty C. To pytanie jest coraz dłuższe w ząb. Dokonałem wielu postępów w tej sprawie i otrzymam porządną odpowiedź. – khiner