1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 // FIXME taken from OpenSLES_AndroidConfiguration.h 18 #define SL_ANDROID_KEY_PERFORMANCE_MODE ((const SLchar*) "androidPerformanceMode") 19 20 //////////////////////////////////////////// 21 /// Actual sles functions. 22 23 24 // Test program to record from default audio input and playback to default audio output. 25 // It will generate feedback (Larsen effect) if played through on-device speakers, 26 // or acts as a delay if played through headset. 27 28 #define _USE_MATH_DEFINES 29 #include <cmath> 30 #include "sles.h" 31 #include "audio_utils/atomic.h" 32 #include "byte_buffer.h" 33 #include <unistd.h> 34 #include <string.h> 35 36 static int slesCreateServer(sles_data *pSles, int samplingRate, int frameCount, int micSource, 37 int performanceMode, 38 int testType, double frequency1, char* byteBufferPtr, int byteBufferLength, 39 short* loopbackTone, int maxRecordedLateCallbacks, int ignoreFirstFrames); 40 static int slesDestroyServer(sles_data *pSles); 41 42 static void initBufferStats(bufferStats *stats); 43 static void collectBufferPeriod(bufferStats *stats, bufferStats *fdpStats, 44 callbackTimeStamps *timeStamps, short expectedBufferPeriod); 45 static bool updateBufferStats(bufferStats *stats, int64_t diff_in_nano, int expectedBufferPeriod); 46 static void recordTimeStamp(callbackTimeStamps *timeStamps, 47 int64_t callbackDuration, int64_t timeStamp); 48 49 int slesComputeDefaultSettings(int /*performanceMode*/, int* /*samplingRate*/, 50 int* /*playerBufferFrameCount*/, int* /*recorderBufferFrameCount*/) { 51 // For OpenSL ES, these parameters can be determined by NativeAudioThread itself. 52 return STATUS_FAIL; 53 } 54 55 int slesInit(void ** ppCtx, int samplingRate, int frameCount, int micSource, 56 int performanceMode, 57 int testType, double frequency1, char* byteBufferPtr, int byteBufferLength, 58 short* loopbackTone, int maxRecordedLateCallbacks, int ignoreFirstFrames) { 59 sles_data ** ppSles = (sles_data**) ppCtx; 60 int status = STATUS_FAIL; 61 if (ppSles != NULL) { 62 sles_data * pSles = (sles_data*) calloc(1, sizeof(sles_data)); 63 64 SLES_PRINTF("pSles malloc %zu bytes at %p", sizeof(sles_data), pSles); 65 //__android_log_print(ANDROID_LOG_INFO, "sles_jni", 66 //"malloc %d bytes at %p", sizeof(sles_data), pSles);//Or ANDROID_LOG_INFO, ... 67 *ppSles = pSles; 68 if (pSles != NULL) 69 { 70 SLES_PRINTF("creating server. Sampling rate =%d, frame count = %d", 71 samplingRate, frameCount); 72 status = slesCreateServer(pSles, samplingRate, frameCount, micSource, 73 performanceMode, testType, 74 frequency1, byteBufferPtr, byteBufferLength, loopbackTone, 75 maxRecordedLateCallbacks, ignoreFirstFrames); 76 SLES_PRINTF("slesCreateServer =%d", status); 77 } 78 } 79 80 return status; 81 } 82 int slesDestroy(void ** ppCtx) { 83 sles_data ** ppSles = (sles_data**)ppCtx; 84 int status = STATUS_FAIL; 85 if (ppSles != NULL) { 86 slesDestroyServer(*ppSles); 87 88 if (*ppSles != NULL) 89 { 90 SLES_PRINTF("free memory at %p",*ppSles); 91 free(*ppSles); 92 *ppSles = 0; 93 } 94 status = STATUS_SUCCESS; 95 } 96 return status; 97 } 98 99 #define ASSERT(x) do { if(!(x)) { __android_log_assert("assert", "sles_jni", \ 100 "ASSERTION FAILED: " #x); } } while (0) 101 #define ASSERT_EQ(x, y) do { if ((x) == (y)) ; else __android_log_assert("assert", "sles_jni", \ 102 "ASSERTION FAILED: 0x%x != 0x%x\n", (unsigned) (x), (unsigned) (y)); } while (0) 103 104 // Called after audio recorder fills a buffer with data, then we can read from this filled buffer 105 static void recorderCallback(SLAndroidSimpleBufferQueueItf caller __unused, void *context) { 106 sles_data *pSles = (sles_data*) context; 107 if (pSles != NULL) { 108 collectBufferPeriod(&pSles->recorderBufferStats, NULL /*fdpStats*/, 109 &pSles->recorderTimeStamps, pSles->expectedBufferPeriod); 110 111 //__android_log_print(ANDROID_LOG_INFO, "sles_jni", "in recorderCallback"); 112 SLresult result; 113 114 //ee SLES_PRINTF("<R"); 115 116 // We should only be called when a recording buffer is done 117 ASSERT(pSles->rxFront <= pSles->rxBufCount); 118 ASSERT(pSles->rxRear <= pSles->rxBufCount); 119 ASSERT(pSles->rxFront != pSles->rxRear); 120 char *buffer = pSles->rxBuffers[pSles->rxFront]; //pSles->rxBuffers stores the data recorded 121 122 123 // Remove buffer from record queue 124 if (++pSles->rxFront > pSles->rxBufCount) { 125 pSles->rxFront = 0; 126 } 127 128 if (pSles->testType == TEST_TYPE_LATENCY) { 129 // Throw out first frames 130 if (pSles->ignoreFirstFrames) { 131 int framesToErase = pSles->ignoreFirstFrames; 132 if (framesToErase > (int) pSles->bufSizeInFrames) { 133 framesToErase = pSles->bufSizeInFrames; 134 } 135 pSles->ignoreFirstFrames -= framesToErase; 136 memset(buffer, 0, framesToErase * pSles->channels * sizeof(short)); 137 } 138 139 ssize_t actual = audio_utils_fifo_write(&(pSles->fifo), buffer, 140 (size_t) pSles->bufSizeInFrames); 141 142 if (actual != (ssize_t) pSles->bufSizeInFrames) { 143 write(1, "?", 1); 144 } 145 146 // This is called by a realtime (SCHED_FIFO) thread, 147 // and it is unsafe to do I/O as it could block for unbounded time. 148 // Flash filesystem is especially notorious for blocking. 149 if (pSles->fifo2Buffer != NULL) { 150 actual = audio_utils_fifo_write(&(pSles->fifo2), buffer, 151 (size_t) pSles->bufSizeInFrames); 152 if (actual != (ssize_t) pSles->bufSizeInFrames) { 153 write(1, "?", 1); 154 } 155 } 156 } else if (pSles->testType == TEST_TYPE_BUFFER_PERIOD) { 157 if (pSles->fifo2Buffer != NULL) { 158 ssize_t actual = byteBuffer_write(pSles->byteBufferPtr, pSles->byteBufferLength, 159 buffer, (size_t) pSles->bufSizeInFrames, pSles->channels); 160 161 //FIXME should log errors using other methods instead of printing to terminal 162 if (actual != (ssize_t) pSles->bufSizeInFrames) { 163 write(1, "?", 1); 164 } 165 } 166 } 167 168 169 // Enqueue this same buffer for the recorder to fill again. 170 result = (*(pSles->recorderBufferQueue))->Enqueue(pSles->recorderBufferQueue, buffer, 171 pSles->bufSizeInBytes); 172 //__android_log_print(ANDROID_LOG_INFO, "recorderCallback", "recorder buffer size: %i", 173 // pSles->bufSizeInBytes); 174 ASSERT_EQ(SL_RESULT_SUCCESS, result); 175 176 177 // Update our model of the record queue 178 SLuint32 rxRearNext = pSles->rxRear + 1; 179 if (rxRearNext > pSles->rxBufCount) { 180 rxRearNext = 0; 181 } 182 ASSERT(rxRearNext != pSles->rxFront); 183 pSles->rxBuffers[pSles->rxRear] = buffer; 184 pSles->rxRear = rxRearNext; 185 186 187 188 //ee SLES_PRINTF("r>"); 189 190 } //pSles not null 191 } 192 193 194 // Calculate nanosecond difference between two timespec structs from clock_gettime(CLOCK_MONOTONIC) 195 // tv_sec [0, max time_t] , tv_nsec [0, 999999999] 196 static int64_t diffInNano(struct timespec previousTime, struct timespec currentTime) { 197 return (int64_t) (currentTime.tv_sec - previousTime.tv_sec) * (int64_t) NANOS_PER_SECOND + 198 currentTime.tv_nsec - previousTime.tv_nsec; 199 } 200 201 // Called after audio player empties a buffer of data 202 static void playerCallback(SLBufferQueueItf caller __unused, void *context) { 203 sles_data *pSles = (sles_data*) context; 204 if (pSles != NULL) { 205 collectBufferPeriod(&pSles->playerBufferStats, &pSles->recorderBufferStats /*fdpStats*/, 206 &pSles->playerTimeStamps, pSles->expectedBufferPeriod); 207 SLresult result; 208 209 //ee SLES_PRINTF("<P"); 210 211 // Get the buffer that just finished playing 212 ASSERT(pSles->txFront <= pSles->txBufCount); 213 ASSERT(pSles->txRear <= pSles->txBufCount); 214 ASSERT(pSles->txFront != pSles->txRear); 215 char *buffer = pSles->txBuffers[pSles->txFront]; 216 if (++pSles->txFront > pSles->txBufCount) { 217 pSles->txFront = 0; 218 } 219 220 if (pSles->testType == TEST_TYPE_LATENCY) { 221 // Jitter buffer should have strictly less than 2 buffers worth of data in it. 222 // This is to prevent the test itself from adding too much latency. 223 size_t discardedInputFrames = 0; 224 for (;;) { 225 size_t availToRead = audio_utils_fifo_availToRead(&pSles->fifo); 226 if (availToRead < pSles->bufSizeInFrames * 2) { 227 break; 228 } 229 ssize_t actual = audio_utils_fifo_read(&pSles->fifo, buffer, 230 pSles->bufSizeInFrames); 231 if (actual > 0) { 232 discardedInputFrames += actual; 233 } 234 if (actual != (ssize_t) pSles->bufSizeInFrames) { 235 break; 236 } 237 } 238 if (discardedInputFrames > 0) { 239 if (pSles->totalDiscardedInputFrames > 0) { 240 __android_log_print(ANDROID_LOG_WARN, "sles_jni", 241 "Discarded an additional %zu input frames after a total of %zu input frames" 242 " had previously been discarded", 243 discardedInputFrames, pSles->totalDiscardedInputFrames); 244 } 245 pSles->totalDiscardedInputFrames += discardedInputFrames; 246 } 247 248 ssize_t actual = audio_utils_fifo_read(&(pSles->fifo), buffer, pSles->bufSizeInFrames); 249 if (actual != (ssize_t) pSles->bufSizeInFrames) { 250 write(1, "/", 1); 251 // on underrun from pipe, substitute silence 252 memset(buffer, 0, pSles->bufSizeInFrames * pSles->channels * sizeof(short)); 253 } 254 255 if (pSles->injectImpulse == -1) { // here we inject pulse 256 257 /*// Experimentally, a single frame impulse was insufficient to trigger feedback. 258 // Also a Nyquist frequency signal was also insufficient, probably because 259 // the response of output and/or input path was not adequate at high frequencies. 260 // This short burst of a few cycles of square wave at Nyquist/4 found to work well. 261 for (unsigned i = 0; i < pSles->bufSizeInFrames / 8; i += 8) { 262 for (int j = 0; j < 8; j++) { 263 for (unsigned k = 0; k < pSles->channels; k++) { 264 ((short *) buffer)[(i + j) * pSles->channels + k] = 265 j < 4 ? 0x7FFF : 0x8000; 266 } 267 } 268 }*/ 269 270 //inject java generated tone 271 for (unsigned i = 0; i < pSles->bufSizeInFrames; ++i) { 272 for (unsigned k = 0; k < pSles->channels; ++k) { 273 ((short *) buffer)[i * pSles->channels + k] = pSles->loopbackTone[i]; 274 } 275 } 276 277 pSles->injectImpulse = 0; 278 pSles->totalDiscardedInputFrames = 0; 279 } 280 } else if (pSles->testType == TEST_TYPE_BUFFER_PERIOD) { 281 double twoPi = M_PI * 2; 282 int maxShort = 32767; 283 float amplitude = 0.8; 284 short value; 285 double phaseIncrement = pSles->frequency1 / pSles->sampleRate; 286 bool isGlitchEnabled = false; 287 for (unsigned i = 0; i < pSles->bufSizeInFrames; i++) { 288 value = (short) (sin(pSles->bufferTestPhase1) * maxShort * amplitude); 289 for (unsigned k = 0; k < pSles->channels; ++k) { 290 ((short *) buffer)[i* pSles->channels + k] = value; 291 } 292 293 pSles->bufferTestPhase1 += twoPi * phaseIncrement; 294 // insert glitches if isGlitchEnabled == true, and insert it for every second 295 if (isGlitchEnabled && (pSles->count % pSles->sampleRate == 0)) { 296 pSles->bufferTestPhase1 += twoPi * phaseIncrement; 297 } 298 299 pSles->count++; 300 301 while (pSles->bufferTestPhase1 > twoPi) { 302 pSles->bufferTestPhase1 -= twoPi; 303 } 304 } 305 } 306 307 // Enqueue the filled buffer for playing 308 result = (*(pSles->playerBufferQueue))->Enqueue(pSles->playerBufferQueue, buffer, 309 pSles->bufSizeInBytes); 310 ASSERT_EQ(SL_RESULT_SUCCESS, result); 311 312 // Update our model of the player queue 313 ASSERT(pSles->txFront <= pSles->txBufCount); 314 ASSERT(pSles->txRear <= pSles->txBufCount); 315 SLuint32 txRearNext = pSles->txRear + 1; 316 if (txRearNext > pSles->txBufCount) { 317 txRearNext = 0; 318 } 319 ASSERT(txRearNext != pSles->txFront); 320 pSles->txBuffers[pSles->txRear] = buffer; 321 pSles->txRear = txRearNext; 322 323 } //pSles not null 324 } 325 326 // Used to set initial values for the bufferStats struct before values can be recorded. 327 static void initBufferStats(bufferStats *stats) { 328 stats->buffer_period = new int[RANGE](); // initialized to zeros 329 stats->previous_time = {0,0}; 330 stats->current_time = {0,0}; 331 332 stats->buffer_count = 0; 333 stats->max_buffer_period = 0; 334 335 stats->measurement_count = 0; 336 stats->SDM = 0; 337 stats->var = 0; 338 } 339 340 // Called in the beginning of playerCallback() to collect the interval between each callback. 341 // fdpStats is either NULL or a pointer to the buffer statistics for the full-duplex partner. 342 static void collectBufferPeriod(bufferStats *stats, bufferStats *fdpStats, 343 callbackTimeStamps *timeStamps, short expectedBufferPeriod) { 344 clock_gettime(CLOCK_MONOTONIC, &(stats->current_time)); 345 346 if (timeStamps->startTime.tv_sec == 0 && timeStamps->startTime.tv_nsec == 0) { 347 timeStamps->startTime = stats->current_time; 348 } 349 350 (stats->buffer_count)++; 351 352 if (stats->previous_time.tv_sec != 0 && stats->buffer_count > BUFFER_PERIOD_DISCARD && 353 (fdpStats == NULL || fdpStats->buffer_count > BUFFER_PERIOD_DISCARD_FULL_DUPLEX_PARTNER)) { 354 355 int64_t callbackDuration = diffInNano(stats->previous_time, stats->current_time); 356 357 bool outlier = updateBufferStats(stats, callbackDuration, expectedBufferPeriod); 358 359 //recording timestamps of buffer periods not at expected buffer period 360 if (outlier) { 361 int64_t timeStamp = diffInNano(timeStamps->startTime, stats->current_time); 362 recordTimeStamp(timeStamps, callbackDuration, timeStamp); 363 } 364 } 365 366 stats->previous_time = stats->current_time; 367 } 368 369 // Records an outlier given the duration in nanoseconds and the number of nanoseconds 370 // between it and the start of the test. 371 static void recordTimeStamp(callbackTimeStamps *timeStamps, 372 int64_t callbackDuration, int64_t timeStamp) { 373 if (timeStamps->exceededCapacity) { 374 return; 375 } 376 377 //only marked as exceeded if attempting to record a late callback after arrays full 378 if (timeStamps->index == timeStamps->capacity){ 379 timeStamps->exceededCapacity = true; 380 } else { 381 timeStamps->callbackDurations[timeStamps->index] = 382 (short) ((callbackDuration + NANOS_PER_MILLI - 1) / NANOS_PER_MILLI); 383 timeStamps->timeStampsMs[timeStamps->index] = 384 (int) ((timeStamp + NANOS_PER_MILLI - 1) / NANOS_PER_MILLI); 385 timeStamps->index++; 386 } 387 } 388 389 static void atomicSetIfGreater(volatile int32_t *addr, int32_t val) { 390 // TODO: rewrite this to avoid the need for unbounded spinning 391 int32_t old; 392 do { 393 old = *addr; 394 if (val < old) return; 395 } while(!android_atomic_compare_exchange(&old, val, addr)); 396 } 397 398 // Updates the stats being collected about buffer periods. Returns true if this is an outlier. 399 static bool updateBufferStats(bufferStats *stats, int64_t diff_in_nano, int expectedBufferPeriod) { 400 stats->measurement_count++; 401 402 // round up to nearest millisecond 403 int diff_in_milli = (int) ((diff_in_nano + NANOS_PER_MILLI - 1) / NANOS_PER_MILLI); 404 405 if (diff_in_milli > stats->max_buffer_period) { 406 stats->max_buffer_period = diff_in_milli; 407 } 408 409 // from 0 ms to 1000 ms, plus a sum of all instances > 1000ms 410 if (diff_in_milli >= (RANGE - 1)) { 411 (stats->buffer_period)[RANGE-1]++; 412 } else if (diff_in_milli >= 0) { 413 (stats->buffer_period)[diff_in_milli]++; 414 } else { // for diff_in_milli < 0 415 __android_log_print(ANDROID_LOG_INFO, "sles_player", "Having negative BufferPeriod."); 416 } 417 418 int64_t delta = diff_in_nano - (int64_t) expectedBufferPeriod * NANOS_PER_MILLI; 419 stats->SDM += delta * delta; 420 if (stats->measurement_count > 1) { 421 stats->var = stats->SDM / stats->measurement_count; 422 } 423 424 // check if the lateness is so bad that a systrace should be captured 425 // TODO: replace static threshold of lateness with a dynamic determination 426 if (diff_in_milli > expectedBufferPeriod + LATE_CALLBACK_CAPTURE_THRESHOLD) { 427 // TODO: log in a non-blocking way 428 //__android_log_print(ANDROID_LOG_INFO, "buffer_stats", "Callback late by %d ms", 429 // diff_in_milli - expectedBufferPeriod); 430 atomicSetIfGreater(&(stats->captureRank), diff_in_milli - expectedBufferPeriod); 431 } 432 return diff_in_milli > expectedBufferPeriod + LATE_CALLBACK_OUTLIER_THRESHOLD; 433 } 434 435 static int slesCreateServer(sles_data *pSles, int samplingRate, int frameCount, int micSource, 436 int performanceMode, 437 int testType, double frequency1, char *byteBufferPtr, int byteBufferLength, 438 short *loopbackTone, int maxRecordedLateCallbacks, int ignoreFirstFrames) { 439 int status = STATUS_FAIL; 440 441 if (pSles != NULL) { 442 443 // adb shell slesTest_feedback -r1 -t1 -s48000 -f240 -i300 -e3 -o/sdcard/log.wav 444 // r1 and t1 are the receive and transmit buffer counts, typically 1 445 // s is the sample rate, typically 48000 or 44100 446 // f is the frame count per buffer, typically 240 or 256 447 // i is the number of milliseconds before impulse. You may need to adjust this. 448 // e is number of seconds to record 449 // o is output .wav file name 450 451 452 // // default values 453 // SLuint32 rxBufCount = 1; // -r# 454 // SLuint32 txBufCount = 1; // -t# 455 // SLuint32 bufSizeInFrames = 240; // -f# 456 // SLuint32 channels = 1; // -c# 457 // SLuint32 sampleRate = 48000; // -s# 458 // SLuint32 exitAfterSeconds = 3; // -e# 459 // SLuint32 freeBufCount = 0; // calculated 460 // SLuint32 bufSizeInBytes = 0; // calculated 461 // int injectImpulse = 300; // -i#i 462 // 463 // // Storage area for the buffer queues 464 // char **rxBuffers; 465 // char **txBuffers; 466 // char **freeBuffers; 467 // 468 // // Buffer indices 469 // SLuint32 rxFront; // oldest recording 470 // SLuint32 rxRear; // next to be recorded 471 // SLuint32 txFront; // oldest playing 472 // SLuint32 txRear; // next to be played 473 // SLuint32 freeFront; // oldest free 474 // SLuint32 freeRear; // next to be freed 475 // 476 // audio_utils_fifo fifo; //(*) 477 // SLAndroidSimpleBufferQueueItf recorderBufferQueue; 478 // SLBufferQueueItf playerBufferQueue; 479 480 // default values 481 pSles->rxBufCount = 1; // -r# 482 pSles->txBufCount = 1; // -t# 483 pSles->bufSizeInFrames = frameCount;//240; // -f# 484 pSles->channels = 1; // -c# 485 pSles->sampleRate = samplingRate;//48000; // -s# 486 pSles->exitAfterSeconds = 3; // -e# 487 pSles->freeBufCount = 0; // calculated 488 pSles->bufSizeInBytes = 0; // calculated 489 pSles->injectImpulse = 300; // -i#i 490 pSles->totalDiscardedInputFrames = 0; 491 pSles->ignoreFirstFrames = ignoreFirstFrames; 492 493 // Storage area for the buffer queues 494 // char **rxBuffers; 495 // char **txBuffers; 496 // char **freeBuffers; 497 498 // Buffer indices 499 #if 0 500 pSles->rxFront; // oldest recording 501 pSles->rxRear; // next to be recorded 502 pSles->txFront; // oldest playing 503 pSles->txRear; // next to be played 504 pSles->freeFront; // oldest free 505 pSles->freeRear; // next to be freed 506 507 pSles->fifo; //(*) 508 #endif 509 pSles->fifo2Buffer = NULL; //this fifo is for sending data to java code (to plot it) 510 #if 0 511 pSles->recorderBufferQueue; 512 pSles->playerBufferQueue; 513 #endif 514 515 516 517 // compute total free buffers as -r plus -t 518 pSles->freeBufCount = pSles->rxBufCount + pSles->txBufCount; 519 // compute buffer size 520 pSles->bufSizeInBytes = pSles->channels * pSles->bufSizeInFrames * sizeof(short); 521 522 // Initialize free buffers 523 pSles->freeBuffers = (char **) calloc(pSles->freeBufCount + 1, sizeof(char *)); 524 SLES_PRINTF(" calloc freeBuffers %llu bytes at %p", (long long)pSles->freeBufCount + 1, 525 pSles->freeBuffers); 526 unsigned j; 527 for (j = 0; j < pSles->freeBufCount; ++j) { 528 pSles->freeBuffers[j] = (char *) malloc(pSles->bufSizeInBytes); 529 SLES_PRINTF(" buff%d malloc %llu bytes at %p",j, (long long)pSles->bufSizeInBytes, 530 pSles->freeBuffers[j]); 531 } 532 pSles->freeFront = 0; 533 pSles->freeRear = pSles->freeBufCount; 534 pSles->freeBuffers[j] = NULL; 535 536 // Initialize record queue 537 pSles->rxBuffers = (char **) calloc(pSles->rxBufCount + 1, sizeof(char *)); 538 SLES_PRINTF(" calloc rxBuffers %llu bytes at %p", (long long)pSles->rxBufCount + 1, 539 pSles->rxBuffers); 540 pSles->rxFront = 0; 541 pSles->rxRear = 0; 542 543 // Initialize play queue 544 pSles->txBuffers = (char **) calloc(pSles->txBufCount + 1, sizeof(char *)); 545 SLES_PRINTF(" calloc txBuffers %llu bytes at %p", (long long)pSles->txBufCount + 1, 546 pSles->txBuffers); 547 pSles->txFront = 0; 548 pSles->txRear = 0; 549 550 size_t frameSize = pSles->channels * sizeof(short); 551 #define FIFO_FRAMES 1024 552 pSles->fifoBuffer = new short[FIFO_FRAMES * pSles->channels]; 553 audio_utils_fifo_init(&(pSles->fifo), FIFO_FRAMES, frameSize, pSles->fifoBuffer); 554 555 // SNDFILE *sndfile; 556 // if (outFileName != NULL) { 557 // create .wav writer 558 // SF_INFO info; 559 // info.frames = 0; 560 // info.samplerate = sampleRate; 561 // info.channels = channels; 562 // info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16; 563 // sndfile = sf_open(outFileName, SFM_WRITE, &info); 564 // if (sndfile != NULL) { 565 #define FIFO2_FRAMES 65536 566 pSles->fifo2Buffer = new short[FIFO2_FRAMES * pSles->channels]; 567 audio_utils_fifo_init(&(pSles->fifo2), FIFO2_FRAMES, frameSize, pSles->fifo2Buffer); 568 // } else { 569 // fprintf(stderr, "sf_open failed\n"); 570 // } 571 // } else { 572 // sndfile = NULL; 573 // } 574 575 initBufferStats(&pSles->recorderBufferStats); 576 initBufferStats(&pSles->playerBufferStats); 577 578 // init other variables needed for buffer test 579 pSles->testType = testType; 580 pSles->frequency1 = frequency1; 581 pSles->bufferTestPhase1 = 0; 582 pSles->count = 0; 583 pSles->byteBufferPtr = byteBufferPtr; 584 pSles->byteBufferLength = byteBufferLength; 585 586 //init loopback tone 587 pSles->loopbackTone = loopbackTone; 588 589 pSles->recorderTimeStamps = { 590 new int[maxRecordedLateCallbacks], //int* timeStampsMs 591 new short[maxRecordedLateCallbacks], //short* callbackDurations 592 0, //short index 593 {0,0}, //struct timespec startTime; 594 maxRecordedLateCallbacks, //int capacity 595 false //bool exceededCapacity 596 }; 597 598 pSles->playerTimeStamps = { 599 new int[maxRecordedLateCallbacks], //int* timeStampsMs 600 new short[maxRecordedLateCallbacks], //short* callbackDurations; 601 0, //short index 602 {0,0}, //struct timespec startTime; 603 maxRecordedLateCallbacks, //int capacity 604 false //bool exceededCapacity 605 }; 606 607 pSles->expectedBufferPeriod = (short) ( 608 round(pSles->bufSizeInFrames * MILLIS_PER_SECOND / (float) pSles->sampleRate)); 609 610 SLresult result; 611 612 // create engine 613 #if 0 614 pSles->engineObject; 615 #endif 616 result = slCreateEngine(&(pSles->engineObject), 0, NULL, 0, NULL, NULL); 617 ASSERT_EQ(SL_RESULT_SUCCESS, result); 618 result = (*(pSles->engineObject))->Realize(pSles->engineObject, SL_BOOLEAN_FALSE); 619 ASSERT_EQ(SL_RESULT_SUCCESS, result); 620 SLEngineItf engineEngine; 621 result = (*(pSles->engineObject))->GetInterface(pSles->engineObject, SL_IID_ENGINE, 622 &engineEngine); 623 ASSERT_EQ(SL_RESULT_SUCCESS, result); 624 625 // create output mix 626 #if 0 627 pSles->outputmixObject; 628 #endif 629 result = (*engineEngine)->CreateOutputMix(engineEngine, &(pSles->outputmixObject), 0, NULL, 630 NULL); 631 ASSERT_EQ(SL_RESULT_SUCCESS, result); 632 result = (*(pSles->outputmixObject))->Realize(pSles->outputmixObject, SL_BOOLEAN_FALSE); 633 ASSERT_EQ(SL_RESULT_SUCCESS, result); 634 635 // create an audio player with buffer queue source and output mix sink 636 SLDataSource audiosrc; 637 SLDataSink audiosnk; 638 SLDataFormat_PCM pcm; 639 SLDataLocator_OutputMix locator_outputmix; 640 SLDataLocator_BufferQueue locator_bufferqueue_tx; 641 locator_bufferqueue_tx.locatorType = SL_DATALOCATOR_BUFFERQUEUE; 642 locator_bufferqueue_tx.numBuffers = pSles->txBufCount; 643 locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX; 644 locator_outputmix.outputMix = pSles->outputmixObject; 645 pcm.formatType = SL_DATAFORMAT_PCM; 646 pcm.numChannels = pSles->channels; 647 pcm.samplesPerSec = pSles->sampleRate * 1000; 648 pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16; 649 pcm.containerSize = 16; 650 pcm.channelMask = pSles->channels == 1 ? SL_SPEAKER_FRONT_CENTER : 651 (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT); 652 pcm.endianness = SL_BYTEORDER_LITTLEENDIAN; 653 audiosrc.pLocator = &locator_bufferqueue_tx; 654 audiosrc.pFormat = &pcm; 655 audiosnk.pLocator = &locator_outputmix; 656 audiosnk.pFormat = NULL; 657 pSles->playerObject = NULL; 658 pSles->recorderObject = NULL; 659 SLInterfaceID ids_tx[2] = {SL_IID_BUFFERQUEUE, SL_IID_ANDROIDCONFIGURATION}; 660 SLboolean flags_tx[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; 661 result = (*engineEngine)->CreateAudioPlayer(engineEngine, &(pSles->playerObject), 662 &audiosrc, &audiosnk, 2, ids_tx, flags_tx); 663 if (SL_RESULT_CONTENT_UNSUPPORTED == result) { 664 SLES_PRINTF("ERROR: Could not create audio player (result %x), check sample rate\n", 665 result); 666 goto cleanup; 667 } 668 ASSERT_EQ(SL_RESULT_SUCCESS, result); 669 670 { 671 /* Get the Android configuration interface which is explicit */ 672 SLAndroidConfigurationItf configItf; 673 result = (*(pSles->playerObject))->GetInterface(pSles->playerObject, 674 SL_IID_ANDROIDCONFIGURATION, (void*)&configItf); 675 ASSERT_EQ(SL_RESULT_SUCCESS, result); 676 677 /* Use the configuration interface to configure the player before it's realized */ 678 if (performanceMode != -1) { 679 SLuint32 performanceMode32 = performanceMode; 680 result = (*configItf)->SetConfiguration(configItf, SL_ANDROID_KEY_PERFORMANCE_MODE, 681 &performanceMode32, sizeof(SLuint32)); 682 ASSERT_EQ(SL_RESULT_SUCCESS, result); 683 } 684 685 } 686 687 result = (*(pSles->playerObject))->Realize(pSles->playerObject, SL_BOOLEAN_FALSE); 688 ASSERT_EQ(SL_RESULT_SUCCESS, result); 689 SLPlayItf playerPlay; 690 result = (*(pSles->playerObject))->GetInterface(pSles->playerObject, SL_IID_PLAY, 691 &playerPlay); 692 ASSERT_EQ(SL_RESULT_SUCCESS, result); 693 result = (*(pSles->playerObject))->GetInterface(pSles->playerObject, SL_IID_BUFFERQUEUE, 694 &(pSles->playerBufferQueue)); 695 ASSERT_EQ(SL_RESULT_SUCCESS, result); 696 result = (*(pSles->playerBufferQueue))->RegisterCallback(pSles->playerBufferQueue, 697 playerCallback, pSles); //playerCallback is the name of callback function 698 ASSERT_EQ(SL_RESULT_SUCCESS, result); 699 700 // Enqueue some zero buffers for the player 701 for (j = 0; j < pSles->txBufCount; ++j) { 702 703 // allocate a free buffer 704 ASSERT(pSles->freeFront != pSles->freeRear); 705 char *buffer = pSles->freeBuffers[pSles->freeFront]; 706 if (++pSles->freeFront > pSles->freeBufCount) { 707 pSles->freeFront = 0; 708 } 709 710 // put on play queue 711 SLuint32 txRearNext = pSles->txRear + 1; 712 if (txRearNext > pSles->txBufCount) { 713 txRearNext = 0; 714 } 715 ASSERT(txRearNext != pSles->txFront); 716 pSles->txBuffers[pSles->txRear] = buffer; 717 pSles->txRear = txRearNext; 718 result = (*(pSles->playerBufferQueue))->Enqueue(pSles->playerBufferQueue, 719 buffer, pSles->bufSizeInBytes); 720 ASSERT_EQ(SL_RESULT_SUCCESS, result); 721 } 722 723 result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING); 724 ASSERT_EQ(SL_RESULT_SUCCESS, result); 725 726 // Create an audio recorder with microphone device source and buffer queue sink. 727 // The buffer queue as sink is an Android-specific extension. 728 SLDataLocator_IODevice locator_iodevice; 729 SLDataLocator_AndroidSimpleBufferQueue locator_bufferqueue_rx; 730 731 locator_iodevice.locatorType = SL_DATALOCATOR_IODEVICE; 732 locator_iodevice.deviceType = SL_IODEVICE_AUDIOINPUT; 733 locator_iodevice.deviceID = SL_DEFAULTDEVICEID_AUDIOINPUT; 734 locator_iodevice.device = NULL; 735 736 audiosrc.pLocator = &locator_iodevice; 737 audiosrc.pFormat = NULL; 738 739 locator_bufferqueue_rx.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; 740 locator_bufferqueue_rx.numBuffers = pSles->rxBufCount; 741 742 audiosnk.pLocator = &locator_bufferqueue_rx; 743 audiosnk.pFormat = &pcm; 744 745 { //why brackets here? 746 SLInterfaceID ids_rx[2] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE, 747 SL_IID_ANDROIDCONFIGURATION}; 748 SLboolean flags_rx[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; 749 result = (*engineEngine)->CreateAudioRecorder(engineEngine, &(pSles->recorderObject), 750 &audiosrc, &audiosnk, 2, ids_rx, flags_rx); 751 if (SL_RESULT_SUCCESS != result) { 752 status = STATUS_FAIL; 753 754 SLES_PRINTF("ERROR: Could not create audio recorder (result %x), " 755 "check sample rate and channel count\n", result); 756 goto cleanup; 757 } 758 } 759 ASSERT_EQ(SL_RESULT_SUCCESS, result); 760 761 { 762 /* Get the Android configuration interface which is explicit */ 763 SLAndroidConfigurationItf configItf; 764 result = (*(pSles->recorderObject))->GetInterface(pSles->recorderObject, 765 SL_IID_ANDROIDCONFIGURATION, (void*)&configItf); 766 ASSERT_EQ(SL_RESULT_SUCCESS, result); 767 768 SLuint32 presetValue = micSource; 769 //SL_ANDROID_RECORDING_PRESET_CAMCORDER;//SL_ANDROID_RECORDING_PRESET_NONE; 770 771 /* Use the configuration interface to configure the recorder before it's realized */ 772 if (presetValue != SL_ANDROID_RECORDING_PRESET_NONE) { 773 result = (*configItf)->SetConfiguration(configItf, SL_ANDROID_KEY_RECORDING_PRESET, 774 &presetValue, sizeof(SLuint32)); 775 ASSERT_EQ(SL_RESULT_SUCCESS, result); 776 } 777 if (performanceMode != -1) { 778 SLuint32 performanceMode32 = performanceMode; 779 result = (*configItf)->SetConfiguration(configItf, SL_ANDROID_KEY_PERFORMANCE_MODE, 780 &performanceMode32, sizeof(SLuint32)); 781 ASSERT_EQ(SL_RESULT_SUCCESS, result); 782 } 783 784 } 785 786 result = (*(pSles->recorderObject))->Realize(pSles->recorderObject, SL_BOOLEAN_FALSE); 787 ASSERT_EQ(SL_RESULT_SUCCESS, result); 788 789 SLRecordItf recorderRecord; 790 result = (*(pSles->recorderObject))->GetInterface(pSles->recorderObject, SL_IID_RECORD, 791 &recorderRecord); 792 ASSERT_EQ(SL_RESULT_SUCCESS, result); 793 794 result = (*(pSles->recorderObject))->GetInterface(pSles->recorderObject, 795 SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &(pSles->recorderBufferQueue)); 796 ASSERT_EQ(SL_RESULT_SUCCESS, result); 797 798 result = (*(pSles->recorderBufferQueue))->RegisterCallback(pSles->recorderBufferQueue, 799 recorderCallback, pSles); 800 ASSERT_EQ(SL_RESULT_SUCCESS, result); 801 802 // Enqueue some empty buffers for the recorder 803 for (j = 0; j < pSles->rxBufCount; ++j) { 804 805 // allocate a free buffer 806 ASSERT(pSles->freeFront != pSles->freeRear); 807 char *buffer = pSles->freeBuffers[pSles->freeFront]; 808 if (++pSles->freeFront > pSles->freeBufCount) { 809 pSles->freeFront = 0; 810 } 811 812 // put on record queue 813 SLuint32 rxRearNext = pSles->rxRear + 1; 814 if (rxRearNext > pSles->rxBufCount) { 815 rxRearNext = 0; 816 } 817 ASSERT(rxRearNext != pSles->rxFront); 818 pSles->rxBuffers[pSles->rxRear] = buffer; 819 pSles->rxRear = rxRearNext; 820 result = (*(pSles->recorderBufferQueue))->Enqueue(pSles->recorderBufferQueue, 821 buffer, pSles->bufSizeInBytes); 822 ASSERT_EQ(SL_RESULT_SUCCESS, result); 823 } 824 825 // Kick off the recorder 826 result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_RECORDING); 827 ASSERT_EQ(SL_RESULT_SUCCESS, result); 828 829 830 831 // Tear down the objects and exit 832 status = STATUS_SUCCESS; 833 cleanup: 834 835 SLES_PRINTF("Finished initialization with status: %d", status); 836 837 } 838 return status; 839 } 840 841 // Read data from fifo2Buffer and store into pSamples. 842 int slesProcessNext(void *pCtx, double *pSamples, long maxSamples) { 843 //int status = STATUS_FAIL; 844 sles_data *pSles = (sles_data*)pCtx; 845 846 SLES_PRINTF("slesProcessNext: pSles = %p, currentSample: %p, maxSamples = %ld", 847 pSles, pSamples, maxSamples); 848 849 int samplesRead = 0; 850 851 int currentSample = 0; 852 double *pCurrentSample = pSamples; 853 int maxValue = 32768; 854 855 if (pSles != NULL) { 856 857 SLresult result; 858 for (int i = 0; i < 10; i++) { 859 usleep(100000); // sleep for 0.1s 860 if (pSles->fifo2Buffer != NULL) { 861 for (;;) { 862 short buffer[pSles->bufSizeInFrames * pSles->channels]; 863 ssize_t actual = audio_utils_fifo_read(&(pSles->fifo2), buffer, 864 pSles->bufSizeInFrames); 865 if (actual <= 0) 866 break; 867 { 868 for (int jj = 0; jj < actual && currentSample < maxSamples; jj++) { 869 *(pCurrentSample++) = ((double) buffer[jj]) / maxValue; 870 currentSample++; 871 } 872 } 873 samplesRead += actual; 874 } 875 } 876 if (pSles->injectImpulse > 0) { 877 if (pSles->injectImpulse <= 100) { 878 pSles->injectImpulse = -1; 879 write(1, "I", 1); 880 } else { 881 if ((pSles->injectImpulse % 1000) < 100) { 882 write(1, "i", 1); 883 } 884 pSles->injectImpulse -= 100; 885 } 886 } else if (i == 9) { 887 write(1, ".", 1); 888 } 889 } 890 SLBufferQueueState playerBQState; 891 result = (*(pSles->playerBufferQueue))->GetState(pSles->playerBufferQueue, 892 &playerBQState); 893 ASSERT_EQ(SL_RESULT_SUCCESS, result); 894 SLAndroidSimpleBufferQueueState recorderBQState; 895 result = (*(pSles->recorderBufferQueue))->GetState(pSles->recorderBufferQueue, 896 &recorderBQState); 897 ASSERT_EQ(SL_RESULT_SUCCESS, result); 898 899 SLES_PRINTF("End of slesProcessNext: pSles = %p, samplesRead = %d, maxSamples = %ld", 900 pSles, samplesRead, maxSamples); 901 } 902 return samplesRead; 903 } 904 905 906 static int slesDestroyServer(sles_data *pSles) { 907 int status = STATUS_FAIL; 908 909 SLES_PRINTF("Start slesDestroyServer: pSles = %p", pSles); 910 911 if (pSles != NULL) { 912 if (NULL != pSles->playerObject) { 913 SLES_PRINTF("stopping player..."); 914 SLPlayItf playerPlay; 915 SLresult result = (*(pSles->playerObject))->GetInterface(pSles->playerObject, 916 SL_IID_PLAY, &playerPlay); 917 918 ASSERT_EQ(SL_RESULT_SUCCESS, result); 919 920 //stop player and recorder if they exist 921 result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_STOPPED); 922 ASSERT_EQ(SL_RESULT_SUCCESS, result); 923 } 924 925 if (NULL != pSles->recorderObject) { 926 SLES_PRINTF("stopping recorder..."); 927 SLRecordItf recorderRecord; 928 SLresult result = (*(pSles->recorderObject))->GetInterface(pSles->recorderObject, 929 SL_IID_RECORD, &recorderRecord); 930 ASSERT_EQ(SL_RESULT_SUCCESS, result); 931 932 result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_STOPPED); 933 ASSERT_EQ(SL_RESULT_SUCCESS, result); 934 } 935 936 usleep(1000); 937 938 audio_utils_fifo_deinit(&(pSles->fifo)); 939 delete[] pSles->fifoBuffer; 940 941 SLES_PRINTF("slesDestroyServer 2"); 942 943 // if (sndfile != NULL) { 944 audio_utils_fifo_deinit(&(pSles->fifo2)); 945 delete[] pSles->fifo2Buffer; 946 947 SLES_PRINTF("slesDestroyServer 3"); 948 949 // sf_close(sndfile); 950 // } 951 if (NULL != pSles->playerObject) { 952 (*(pSles->playerObject))->Destroy(pSles->playerObject); 953 } 954 955 SLES_PRINTF("slesDestroyServer 4"); 956 957 if (NULL != pSles->recorderObject) { 958 (*(pSles->recorderObject))->Destroy(pSles->recorderObject); 959 } 960 961 SLES_PRINTF("slesDestroyServer 5"); 962 963 (*(pSles->outputmixObject))->Destroy(pSles->outputmixObject); 964 SLES_PRINTF("slesDestroyServer 6"); 965 (*(pSles->engineObject))->Destroy(pSles->engineObject); 966 SLES_PRINTF("slesDestroyServer 7"); 967 968 //free buffers 969 if (NULL != pSles->freeBuffers) { 970 for (unsigned j = 0; j < pSles->freeBufCount; ++j) { 971 if (NULL != pSles->freeBuffers[j]) { 972 SLES_PRINTF(" free buff%d at %p",j, pSles->freeBuffers[j]); 973 free (pSles->freeBuffers[j]); 974 } 975 } 976 SLES_PRINTF(" free freeBuffers at %p", pSles->freeBuffers); 977 free(pSles->freeBuffers); 978 } else { 979 SLES_PRINTF(" freeBuffers NULL, no need to free"); 980 } 981 982 983 if (NULL != pSles->rxBuffers) { 984 SLES_PRINTF(" free rxBuffers at %p", pSles->rxBuffers); 985 free(pSles->rxBuffers); 986 } else { 987 SLES_PRINTF(" rxBuffers NULL, no need to free"); 988 } 989 990 if (NULL != pSles->txBuffers) { 991 SLES_PRINTF(" free txBuffers at %p", pSles->txBuffers); 992 free(pSles->txBuffers); 993 } else { 994 SLES_PRINTF(" txBuffers NULL, no need to free"); 995 } 996 997 998 status = STATUS_SUCCESS; 999 } 1000 SLES_PRINTF("End slesDestroyServer: status = %d", status); 1001 return status; 1002 } 1003 1004 1005 int* slesGetRecorderBufferPeriod(void *pCtx) { 1006 sles_data *pSles = (sles_data*)pCtx; 1007 return pSles->recorderBufferStats.buffer_period; 1008 } 1009 1010 int slesGetRecorderMaxBufferPeriod(void *pCtx) { 1011 sles_data *pSles = (sles_data*)pCtx; 1012 return pSles->recorderBufferStats.max_buffer_period; 1013 } 1014 1015 int64_t slesGetRecorderVarianceBufferPeriod(void *pCtx) { 1016 sles_data *pSles = (sles_data*)pCtx; 1017 return pSles->recorderBufferStats.var; 1018 } 1019 1020 int* slesGetPlayerBufferPeriod(void *pCtx) { 1021 sles_data *pSles = (sles_data*)pCtx; 1022 return pSles->playerBufferStats.buffer_period; 1023 } 1024 1025 int slesGetPlayerMaxBufferPeriod(void *pCtx) { 1026 sles_data *pSles = (sles_data*)pCtx; 1027 return pSles->playerBufferStats.max_buffer_period; 1028 } 1029 1030 int64_t slesGetPlayerVarianceBufferPeriod(void *pCtx) { 1031 sles_data *pSles = (sles_data*)pCtx; 1032 return pSles->playerBufferStats.var; 1033 } 1034 1035 int slesGetCaptureRank(void *pCtx) { 1036 sles_data *pSles = (sles_data*)pCtx; 1037 // clear the capture flags since they're being handled now 1038 int recorderRank = android_atomic_exchange(0, &pSles->recorderBufferStats.captureRank); 1039 int playerRank = android_atomic_exchange(0, &pSles->playerBufferStats.captureRank); 1040 1041 if (recorderRank > playerRank) { 1042 return recorderRank; 1043 } else { 1044 return playerRank; 1045 } 1046 } 1047 1048 int slesGetPlayerTimeStampsAndExpectedBufferPeriod(void *pCtx, callbackTimeStamps **ppTSs) { 1049 sles_data *pSles = (sles_data*)pCtx; 1050 *ppTSs = &pSles->playerTimeStamps; 1051 return pSles->expectedBufferPeriod; 1052 } 1053 1054 int slesGetRecorderTimeStampsAndExpectedBufferPeriod(void *pCtx, callbackTimeStamps **ppTSs) { 1055 sles_data *pSles = (sles_data*)pCtx; 1056 *ppTSs = &pSles->recorderTimeStamps; 1057 return pSles->expectedBufferPeriod; 1058 } 1059