Je voudrais obtenir un tampon d'octets à partir d'un support audio à l'aide de la OpenSL ES FileDescriptor objet, afin que je puisse mettre en file d'attente à plusieurs reprises pour un SimpleBufferQueue, au lieu d'utiliser SL interfaces pour lire/arrêter/rechercher le fichier.
Il y a trois principales raisons pour lesquelles je voudrais gérer les octets d'échantillon directement:
- OpenSL utilise un AudioTrack couche play/stop/etc pour le Joueur des Objets. Ce n'est pas seulement introduire des frais généraux, mais il a aussi plusieurs bugs, et rapide démarrages/arrêts du joueur causer beaucoup de problèmes.
- J'ai besoin de manipuler des octets de la mémoire tampon directement pour personnaliser les effets DSP.
- Les clips, je vais jouer sont de petite taille, et peuvent être chargés en mémoire pour éviter d'e/S de fichier de frais généraux. De Plus, enqueueing mes propres tampons va me permettre de réduire la latence en écriture de 0 pour la sortie de l'évier, et simplement en changeant d'octets d'échantillon quand ils jouent, plutôt que de s'ARRÊTER, faire une PAUSE et de JOUER de la AudioTrack.
Ok, donc les justifications complètes - voici ce que j'ai essayé - je avoir un Exemple de structure qui contient, pour l'essentiel, une entrée et une sortie de piste, et un tableau d'octets pour contenir les échantillons. L'entrée est mon FileDescriptor joueur, et la sortie est un SimpleBufferQueue objet. Voici ma structure:
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;
après l'initialisation d'un lecteur de fichiers fdPlayerObject, et le malloc-ing mémoire pour mon tampon d'octets avec
sample->buffer = malloc(sizeof(short)*sample->totalSamples);
Je suis de son BufferQueue interface avec
// get the buffer queue interface
result = (*(sample->fdPlayerObject))->GetInterface(sample->fdPlayerObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &(sample->fdBufferQueue));
Puis j'instancie une sortie de joueur:
// 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);
Quand je veux jouer de l'échantillon, je suis en utilisant:
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));
Toutefois, cela provoque mon application de gel et arrêt. Quelque chose ne va pas ici. Aussi, je préfère ne pas obtenir des échantillons par le Descripteur de Fichier du BufferQueue à chaque fois. Au lieu de cela, je voudrais stocker de façon permanente dans un tableau d'octets, et mettre en File d'attente que pour la sortie à chaque fois que j'aime.