txFront <= pSles->txBufCount);
152 | assert(pSles->txRear <= pSles->txBufCount);
153 | assert(pSles->txFront != pSles->txRear);
154 | char *buffer = pSles->txBuffers[pSles->txFront];
155 | if (++pSles->txFront > pSles->txBufCount) {
156 | pSles->txFront = 0;
157 | }
158 |
159 |
160 | ssize_t actual = audio_utils_fifo_read(&(pSles->fifo), buffer, pSles->bufSizeInFrames);
161 | if (actual != (ssize_t) pSles->bufSizeInFrames) {
162 | write(1, "/", 1);
163 | // on underrun from pipe, substitute silence
164 | memset(buffer, 0, pSles->bufSizeInFrames * pSles->channels * sizeof(short));
165 | }
166 |
167 | if (pSles->injectImpulse == -1) {
168 | // Experimentally, a single frame impulse was insufficient to trigger feedback.
169 | // Also a Nyquist frequency signal was also insufficient, probably because
170 | // the response of output and/or input path was not adequate at high frequencies.
171 | // This short burst of a few cycles of square wave at Nyquist/4 was found to work well.
172 | for (unsigned i = 0; i < pSles->bufSizeInFrames / 8; i += 8) {
173 | for (int j = 0; j < 8; j++) {
174 | for (unsigned k = 0; k < pSles->channels; k++) {
175 | ((short *)buffer)[(i+j)*pSles->channels+k] = j < 4 ? 0x7FFF : 0x8000;
176 | }
177 | }
178 | }
179 | pSles->injectImpulse = 0;
180 | }
181 |
182 | // Enqueue the filled buffer for playing
183 | result = (*(pSles->playerBufferQueue))->Enqueue(pSles->playerBufferQueue, buffer,
184 | pSles->bufSizeInBytes);
185 | ASSERT_EQ(SL_RESULT_SUCCESS, result);
186 |
187 | // Update our model of the player queue
188 | assert(pSles->txFront <= pSles->txBufCount);
189 | assert(pSles->txRear <= pSles->txBufCount);
190 | SLuint32 txRearNext = pSles->txRear+1;
191 | if (txRearNext > pSles->txBufCount) {
192 | txRearNext = 0;
193 | }
194 | assert(txRearNext != pSles->txFront);
195 | pSles->txBuffers[pSles->txRear] = buffer;
196 | pSles->txRear = txRearNext;
197 |
198 |
199 | //ee SLES_PRINTF("p>");
200 | pthread_mutex_unlock(&(pSles->mutex));
201 |
202 | } //pSles not null
203 | }
204 |
205 | int slesCreateServer(sles_data *pSles, int samplingRate, int frameCount, int micSource) {
206 | int status = SLES_FAIL;
207 |
208 | if (pSles != NULL) {
209 |
210 | // adb shell slesTest_feedback -r1 -t1 -s48000 -f240 -i300 -e3 -o/sdcard/log.wav
211 | // r1 and t1 are the receive and transmit buffer counts, typically 1
212 | // s is the sample rate, typically 48000 or 44100
213 | // f is the frame count per buffer, typically 240 or 256
214 | // i is the number of milliseconds before impulse. You may need to adjust this.
215 | // e is number of seconds to record
216 | // o is output .wav file name
217 |
218 |
219 | // // default values
220 | // SLuint32 rxBufCount = 1; // -r#
221 | // SLuint32 txBufCount = 1; // -t#
222 | // SLuint32 bufSizeInFrames = 240; // -f#
223 | // SLuint32 channels = 1; // -c#
224 | // SLuint32 sampleRate = 48000; // -s#
225 | // SLuint32 exitAfterSeconds = 3; // -e#
226 | // SLuint32 freeBufCount = 0; // calculated
227 | // SLuint32 bufSizeInBytes = 0; // calculated
228 | // int injectImpulse = 300; // -i#i
229 | //
230 | // // Storage area for the buffer queues
231 | // char **rxBuffers;
232 | // char **txBuffers;
233 | // char **freeBuffers;
234 | //
235 | // // Buffer indices
236 | // SLuint32 rxFront; // oldest recording
237 | // SLuint32 rxRear; // next to be recorded
238 | // SLuint32 txFront; // oldest playing
239 | // SLuint32 txRear; // next to be played
240 | // SLuint32 freeFront; // oldest free
241 | // SLuint32 freeRear; // next to be freed
242 | //
243 | // audio_utils_fifo fifo; //(*)
244 | // SLAndroidSimpleBufferQueueItf recorderBufferQueue;
245 | // SLBufferQueueItf playerBufferQueue;
246 |
247 | // default values
248 | pSles->rxBufCount = 1; // -r#
249 | pSles->txBufCount = 1; // -t#
250 | pSles->bufSizeInFrames = frameCount;//240; // -f#
251 | pSles->channels = 1; // -c#
252 | pSles->sampleRate = samplingRate;//48000; // -s#
253 | pSles->exitAfterSeconds = 3; // -e#
254 | pSles->freeBufCount = 0; // calculated
255 | pSles->bufSizeInBytes = 0; // calculated
256 | pSles->injectImpulse = 300; // -i#i
257 |
258 | // Storage area for the buffer queues
259 | // char **rxBuffers;
260 | // char **txBuffers;
261 | // char **freeBuffers;
262 |
263 | // Buffer indices
264 | pSles->rxFront; // oldest recording
265 | pSles->rxRear; // next to be recorded
266 | pSles->txFront; // oldest playing
267 | pSles->txRear; // next to be played
268 | pSles->freeFront; // oldest free
269 | pSles->freeRear; // next to be freed
270 |
271 | pSles->fifo; //(*)
272 | pSles->fifo2Buffer = NULL;
273 | pSles->recorderBufferQueue;
274 | pSles->playerBufferQueue;
275 |
276 |
277 |
278 | // compute total free buffers as -r plus -t
279 | pSles->freeBufCount = pSles->rxBufCount + pSles->txBufCount;
280 | // compute buffer size
281 | pSles->bufSizeInBytes = pSles->channels * pSles->bufSizeInFrames * sizeof(short);
282 |
283 | // Initialize free buffers
284 | pSles->freeBuffers = (char **) calloc(pSles->freeBufCount+1, sizeof(char *));
285 | unsigned j;
286 | for (j = 0; j < pSles->freeBufCount; ++j) {
287 | pSles->freeBuffers[j] = (char *) malloc(pSles->bufSizeInBytes);
288 | }
289 | pSles->freeFront = 0;
290 | pSles->freeRear = pSles->freeBufCount;
291 | pSles->freeBuffers[j] = NULL;
292 |
293 | // Initialize record queue
294 | pSles->rxBuffers = (char **) calloc(pSles->rxBufCount+1, sizeof(char *));
295 | pSles->rxFront = 0;
296 | pSles->rxRear = 0;
297 |
298 | // Initialize play queue
299 | pSles->txBuffers = (char **) calloc(pSles->txBufCount+1, sizeof(char *));
300 | pSles->txFront = 0;
301 | pSles->txRear = 0;
302 |
303 | size_t frameSize = pSles->channels * sizeof(short);
304 | #define FIFO_FRAMES 1024
305 | pSles->fifoBuffer = new short[FIFO_FRAMES * pSles->channels];
306 | audio_utils_fifo_init(&(pSles->fifo), FIFO_FRAMES, frameSize, pSles->fifoBuffer);
307 |
308 | // SNDFILE *sndfile;
309 | // if (outFileName != NULL) {
310 | // create .wav writer
311 | // SF_INFO info;
312 | // info.frames = 0;
313 | // info.samplerate = sampleRate;
314 | // info.channels = channels;
315 | // info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
316 | // sndfile = sf_open(outFileName, SFM_WRITE, &info);
317 | // if (sndfile != NULL) {
318 | #define FIFO2_FRAMES 65536
319 | pSles->fifo2Buffer = new short[FIFO2_FRAMES * pSles->channels];
320 | audio_utils_fifo_init(&(pSles->fifo2), FIFO2_FRAMES, frameSize, pSles->fifo2Buffer);
321 | // } else {
322 | // fprintf(stderr, "sf_open failed\n");
323 | // }
324 | // } else {
325 | // sndfile = NULL;
326 | // }
327 |
328 | SLresult result;
329 |
330 | // create engine
331 | pSles->engineObject;
332 | result = slCreateEngine(&(pSles->engineObject), 0, NULL, 0, NULL, NULL);
333 | ASSERT_EQ(SL_RESULT_SUCCESS, result);
334 | result = (*(pSles->engineObject))->Realize(pSles->engineObject, SL_BOOLEAN_FALSE);
335 | ASSERT_EQ(SL_RESULT_SUCCESS, result);
336 | SLEngineItf engineEngine;
337 | result = (*(pSles->engineObject))->GetInterface(pSles->engineObject, SL_IID_ENGINE,
338 | &engineEngine);
339 | ASSERT_EQ(SL_RESULT_SUCCESS, result);
340 |
341 | // create output mix
342 | pSles->outputmixObject;
343 | result = (*engineEngine)->CreateOutputMix(engineEngine, &(pSles->outputmixObject), 0, NULL,
344 | NULL);
345 | ASSERT_EQ(SL_RESULT_SUCCESS, result);
346 | result = (*(pSles->outputmixObject))->Realize(pSles->outputmixObject, SL_BOOLEAN_FALSE);
347 | ASSERT_EQ(SL_RESULT_SUCCESS, result);
348 |
349 | // create an audio player with buffer queue source and output mix sink
350 | SLDataSource audiosrc;
351 | SLDataSink audiosnk;
352 | SLDataFormat_PCM pcm;
353 | SLDataLocator_OutputMix locator_outputmix;
354 | SLDataLocator_BufferQueue locator_bufferqueue_tx;
355 | locator_bufferqueue_tx.locatorType = SL_DATALOCATOR_BUFFERQUEUE;
356 | locator_bufferqueue_tx.numBuffers = pSles->txBufCount;
357 | locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
358 | locator_outputmix.outputMix = pSles->outputmixObject;
359 | pcm.formatType = SL_DATAFORMAT_PCM;
360 | pcm.numChannels = pSles->channels;
361 | pcm.samplesPerSec = pSles->sampleRate * 1000;
362 | pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
363 | pcm.containerSize = 16;
364 | pcm.channelMask = pSles->channels == 1 ? SL_SPEAKER_FRONT_CENTER :
365 | (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT);
366 | pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
367 | audiosrc.pLocator = &locator_bufferqueue_tx;
368 | audiosrc.pFormat = &pcm;
369 | audiosnk.pLocator = &locator_outputmix;
370 | audiosnk.pFormat = NULL;
371 | pSles->playerObject = NULL;
372 | pSles->recorderObject = NULL;
373 | SLInterfaceID ids_tx[1] = {SL_IID_BUFFERQUEUE};
374 | SLboolean flags_tx[1] = {SL_BOOLEAN_TRUE};
375 | result = (*engineEngine)->CreateAudioPlayer(engineEngine, &(pSles->playerObject),
376 | &audiosrc, &audiosnk, 1, ids_tx, flags_tx);
377 | if (SL_RESULT_CONTENT_UNSUPPORTED == result) {
378 | fprintf(stderr, "Could not create audio player (result %x), check sample rate\n",
379 | result);
380 | SLES_PRINTF("ERROR: Could not create audio player (result %x), check sample rate\n",
381 | result);
382 | goto cleanup;
383 | }
384 | ASSERT_EQ(SL_RESULT_SUCCESS, result);
385 | result = (*(pSles->playerObject))->Realize(pSles->playerObject, SL_BOOLEAN_FALSE);
386 | ASSERT_EQ(SL_RESULT_SUCCESS, result);
387 | SLPlayItf playerPlay;
388 | result = (*(pSles->playerObject))->GetInterface(pSles->playerObject, SL_IID_PLAY,
389 | &playerPlay);
390 | ASSERT_EQ(SL_RESULT_SUCCESS, result);
391 | result = (*(pSles->playerObject))->GetInterface(pSles->playerObject, SL_IID_BUFFERQUEUE,
392 | &(pSles->playerBufferQueue));
393 | ASSERT_EQ(SL_RESULT_SUCCESS, result);
394 | result = (*(pSles->playerBufferQueue))->RegisterCallback(pSles->playerBufferQueue,
395 | playerCallback, pSles);
396 | ASSERT_EQ(SL_RESULT_SUCCESS, result);
397 |
398 | // Enqueue some zero buffers for the player
399 | for (j = 0; j < pSles->txBufCount; ++j) {
400 |
401 | // allocate a free buffer
402 | assert(pSles->freeFront != pSles->freeRear);
403 | char *buffer = pSles->freeBuffers[pSles->freeFront];
404 | if (++pSles->freeFront > pSles->freeBufCount) {
405 | pSles->freeFront = 0;
406 | }
407 |
408 | // put on play queue
409 | SLuint32 txRearNext = pSles->txRear + 1;
410 | if (txRearNext > pSles->txBufCount) {
411 | txRearNext = 0;
412 | }
413 | assert(txRearNext != pSles->txFront);
414 | pSles->txBuffers[pSles->txRear] = buffer;
415 | pSles->txRear = txRearNext;
416 | result = (*(pSles->playerBufferQueue))->Enqueue(pSles->playerBufferQueue,
417 | buffer, pSles->bufSizeInBytes);
418 | ASSERT_EQ(SL_RESULT_SUCCESS, result);
419 | }
420 |
421 | result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING);
422 | ASSERT_EQ(SL_RESULT_SUCCESS, result);
423 |
424 | // Create an audio recorder with microphone device source and buffer queue sink.
425 | // The buffer queue as sink is an Android-specific extension.
426 |
427 | SLDataLocator_IODevice locator_iodevice;
428 | SLDataLocator_AndroidSimpleBufferQueue locator_bufferqueue_rx;
429 | locator_iodevice.locatorType = SL_DATALOCATOR_IODEVICE;
430 | locator_iodevice.deviceType = SL_IODEVICE_AUDIOINPUT;
431 | locator_iodevice.deviceID = SL_DEFAULTDEVICEID_AUDIOINPUT;
432 | locator_iodevice.device = NULL;
433 | audiosrc.pLocator = &locator_iodevice;
434 | audiosrc.pFormat = NULL;
435 | locator_bufferqueue_rx.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
436 | locator_bufferqueue_rx.numBuffers = pSles->rxBufCount;
437 | audiosnk.pLocator = &locator_bufferqueue_rx;
438 | audiosnk.pFormat = &pcm;
439 | {
440 | SLInterfaceID ids_rx[2] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_ANDROIDCONFIGURATION};
441 | SLboolean flags_rx[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
442 | result = (*engineEngine)->CreateAudioRecorder(engineEngine, &(pSles->recorderObject),
443 | &audiosrc, &audiosnk, 2, ids_rx, flags_rx);
444 | if (SL_RESULT_SUCCESS != result) {
445 | fprintf(stderr, "Could not create audio recorder (result %x), "
446 | "check sample rate and channel count\n", result);
447 | status = SLES_FAIL;
448 |
449 | SLES_PRINTF("ERROR: Could not create audio recorder (result %x), "
450 | "check sample rate and channel count\n", result);
451 | goto cleanup;
452 | }
453 | }
454 | ASSERT_EQ(SL_RESULT_SUCCESS, result);
455 |
456 | {
457 | /* Get the Android configuration interface which is explicit */
458 | SLAndroidConfigurationItf configItf;
459 | result = (*(pSles->recorderObject))->GetInterface(pSles->recorderObject, SL_IID_ANDROIDCONFIGURATION, (void*)&configItf);
460 | ASSERT_EQ(SL_RESULT_SUCCESS, result);
461 |
462 | SLuint32 presetValue = micSource;//SL_ANDROID_RECORDING_PRESET_CAMCORDER;//SL_ANDROID_RECORDING_PRESET_NONE;
463 |
464 | /* Use the configuration interface to configure the recorder before it's realized */
465 | if (presetValue != SL_ANDROID_RECORDING_PRESET_NONE) {
466 | result = (*configItf)->SetConfiguration(configItf, SL_ANDROID_KEY_RECORDING_PRESET,
467 | &presetValue, sizeof(SLuint32));
468 | ASSERT_EQ(SL_RESULT_SUCCESS, result);
469 | }
470 |
471 | }
472 |
473 | result = (*(pSles->recorderObject))->Realize(pSles->recorderObject, SL_BOOLEAN_FALSE);
474 | ASSERT_EQ(SL_RESULT_SUCCESS, result);
475 | SLRecordItf recorderRecord;
476 | result = (*(pSles->recorderObject))->GetInterface(pSles->recorderObject, SL_IID_RECORD,
477 | &recorderRecord);
478 | ASSERT_EQ(SL_RESULT_SUCCESS, result);
479 | result = (*(pSles->recorderObject))->GetInterface(pSles->recorderObject,
480 | SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &(pSles->recorderBufferQueue));
481 | ASSERT_EQ(SL_RESULT_SUCCESS, result);
482 | result = (*(pSles->recorderBufferQueue))->RegisterCallback(pSles->recorderBufferQueue,
483 | recorderCallback, pSles);
484 | ASSERT_EQ(SL_RESULT_SUCCESS, result);
485 |
486 | // Enqueue some empty buffers for the recorder
487 | for (j = 0; j < pSles->rxBufCount; ++j) {
488 |
489 | // allocate a free buffer
490 | assert(pSles->freeFront != pSles->freeRear);
491 | char *buffer = pSles->freeBuffers[pSles->freeFront];
492 | if (++pSles->freeFront > pSles->freeBufCount) {
493 | pSles->freeFront = 0;
494 | }
495 |
496 | // put on record queue
497 | SLuint32 rxRearNext = pSles->rxRear + 1;
498 | if (rxRearNext > pSles->rxBufCount) {
499 | rxRearNext = 0;
500 | }
501 | assert(rxRearNext != pSles->rxFront);
502 | pSles->rxBuffers[pSles->rxRear] = buffer;
503 | pSles->rxRear = rxRearNext;
504 | result = (*(pSles->recorderBufferQueue))->Enqueue(pSles->recorderBufferQueue,
505 | buffer, pSles->bufSizeInBytes);
506 | ASSERT_EQ(SL_RESULT_SUCCESS, result);
507 | }
508 |
509 | // Kick off the recorder
510 | result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_RECORDING);
511 | ASSERT_EQ(SL_RESULT_SUCCESS, result);
512 |
513 |
514 |
515 | // Tear down the objects and exit
516 | status = SLES_SUCCESS;
517 | cleanup:
518 |
519 | SLES_PRINTF("Finished initialization with status: %d", status);
520 |
521 | int xx =1;
522 |
523 | }
524 | return status;
525 | }
526 |
527 | int slesProcessNext(sles_data *pSles, double *pSamples, long maxSamples) {
528 | //int status = SLES_FAIL;
529 |
530 | SLES_PRINTF("slesProcessNext: pSles = %p, currentSample: %p, maxSamples = %ld", pSles, pSamples, maxSamples);
531 |
532 | int samplesRead = 0;
533 |
534 | int currentSample = 0;
535 | double *pCurrentSample = pSamples;
536 | int maxValue = 32768;
537 |
538 | if (pSles != NULL) {
539 |
540 | SLresult result;
541 | for (int i = 0; i < 10; i++) {
542 | usleep(100000);
543 | if (pSles->fifo2Buffer != NULL) {
544 | for (;;) {
545 | short buffer[pSles->bufSizeInFrames * pSles->channels];
546 | ssize_t actual = audio_utils_fifo_read(&(pSles->fifo2), buffer,
547 | pSles->bufSizeInFrames);
548 | if (actual <= 0)
549 | break;
550 | {
551 | for (int jj =0; jj