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
slesInit(sles_data ** ppSles,int samplingRate,int frameCount,int micSource,int performanceMode,int testType,double frequency1,char * byteBufferPtr,int byteBufferLength,short * loopbackTone,int maxRecordedLateCallbacks,int ignoreFirstFrames)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 }
slesDestroy(sles_data ** ppSles)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
recorderCallback(SLAndroidSimpleBufferQueueItf caller __unused,void * context)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.
byteBuffer_write(sles_data * pSles,char * buffer,size_t count)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]
diffInNano(struct timespec previousTime,struct timespec currentTime)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
playerCallback(SLBufferQueueItf caller __unused,void * context)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.
initBufferStats(bufferStats * stats)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.
collectBufferPeriod(bufferStats * stats,bufferStats * fdpStats,callbackTimeStamps * timeStamps,short expectedBufferPeriod)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.
recordTimeStamp(callbackTimeStamps * timeStamps,int64_t callbackDuration,int64_t timeStamp)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
atomicSetIfGreater(volatile int32_t * addr,int32_t val)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.
updateBufferStats(bufferStats * stats,int64_t diff_in_nano,int expectedBufferPeriod)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
slesCreateServer(sles_data * pSles,int samplingRate,int frameCount,int micSource,int performanceMode,int testType,double frequency1,char * byteBufferPtr,int byteBufferLength,short * loopbackTone,int maxRecordedLateCallbacks,int ignoreFirstFrames)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.
slesProcessNext(sles_data * pSles,double * pSamples,long maxSamples)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
slesDestroyServer(sles_data * pSles)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
slesGetRecorderBufferPeriod(sles_data * pSles)1017 int* slesGetRecorderBufferPeriod(sles_data *pSles) {
1018 return pSles->recorderBufferStats.buffer_period;
1019 }
1020
slesGetRecorderMaxBufferPeriod(sles_data * pSles)1021 int slesGetRecorderMaxBufferPeriod(sles_data *pSles) {
1022 return pSles->recorderBufferStats.max_buffer_period;
1023 }
1024
slesGetRecorderVarianceBufferPeriod(sles_data * pSles)1025 int64_t slesGetRecorderVarianceBufferPeriod(sles_data *pSles) {
1026 return pSles->recorderBufferStats.var;
1027 }
1028
slesGetPlayerBufferPeriod(sles_data * pSles)1029 int* slesGetPlayerBufferPeriod(sles_data *pSles) {
1030 return pSles->playerBufferStats.buffer_period;
1031 }
1032
slesGetPlayerMaxBufferPeriod(sles_data * pSles)1033 int slesGetPlayerMaxBufferPeriod(sles_data *pSles) {
1034 return pSles->playerBufferStats.max_buffer_period;
1035 }
1036
slesGetPlayerVarianceBufferPeriod(sles_data * pSles)1037 int64_t slesGetPlayerVarianceBufferPeriod(sles_data *pSles) {
1038 return pSles->playerBufferStats.var;
1039 }
1040
slesGetCaptureRank(sles_data * pSles)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