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