Vorrei ottenere un buffer di byte da una risorsa audio utilizzando l'oggetto FileDescriptor OpenSL ES, quindi posso accodarlo ripetutamente a un SimpleBufferQueue, invece di utilizzare le interfacce SL per riprodurre/arrestare/cercare il file.E 'possibile ottenere un buffer di byte direttamente da una risorsa audio in OpenSL ES (per Android)?
Ci sono tre ragioni principali per cui vorrei gestire direttamente i byte di esempio:
- OpenSL utilizza uno strato AudioTrack per play/stop/etc per il giocatore gli oggetti. Ciò non solo introduce un sovraccarico indesiderato, ma ha anche diversi bug e gli avviamenti/arresti rapidi del lettore causano molti problemi.
- Ho bisogno di manipolare il buffer di byte direttamente per effetti DSP personalizzati.
- Le clip che sto per riprodurre sono piccole e possono essere caricate in memoria per evitare l'overhead di I/O dei file. Inoltre, l'accodamento dei miei buffer personali mi consentirà di ridurre la latenza scrivendo gli 0 nel sink di output e semplicemente passando ai sample byte durante la riproduzione, piuttosto che STOPPING, PAUSING e PLAYing AudioTrack.
Ok, quindi giustificazioni completi - ecco cosa ho provato - Ho una Esempio struct che contiene, in sostanza, una traccia di ingresso e uscita, e una matrice di byte per contenere i campioni. L'input è il mio lettore FileDescriptor e l'output è un oggetto SimpleBufferQueue. Ecco il mio 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;
dopo aver inizializzato un riproduttore di file fdPlayerObject e malloc-zione di memoria per il mio buffer di byte con
sample->buffer = malloc(sizeof(short)*sample->totalSamples);
che sto ricevendo la sua interfaccia BufferQueue con
// get the buffer queue interface
result = (*(sample->fdPlayerObject))->GetInterface(sample->fdPlayerObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &(sample->fdBufferQueue));
Quindi istanziato un lettore di uscita :
// 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);
Quando voglio giocare il campione, io sto usando:
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));
Tuttavia, questo fa sì che la mia app per congelare e si spegnerà. Qualcosa non va, qui. Inoltre,, preferirei non ottenere ogni volta gli esempi dal BufferQueue del File Descriptor. Invece, mi piacerebbe memorizzarlo in modo permanente in un array di byte e accodarlo all'output ogni volta che mi piace.
Ciao khiner, ti aiuterà a leggere i file .wav dalla cartella delle risorse in un byte Java o in un array breve e poi elaborarli ulteriormente? –
Non sono sicuro di quanto posso aiutare, ma solo per il record - stai usando l'NDK? È per questo che il tuo codice è in C++? – Erhannis
Sì, sto usando NDK, e questo in realtà è puro C. Questa domanda sta diventando a lungo nel dente. Ho fatto un sacco di progressi su questo e andrò in giro ad aggiungere una risposta decente. – khiner