slesTestFeedback.cpp revision 58432eb9cea995c69b4f905e68b38c1b8216edeb
1f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten/* 2f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten * Copyright (C) 2010 The Android Open Source Project 3f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten * 4f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten * Licensed under the Apache License, Version 2.0 (the "License"); 5f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten * you may not use this file except in compliance with the License. 6f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten * You may obtain a copy of the License at 7f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten * 8f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten * http://www.apache.org/licenses/LICENSE-2.0 9f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten * 10f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten * Unless required by applicable law or agreed to in writing, software 11f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten * distributed under the License is distributed on an "AS IS" BASIS, 12f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten * See the License for the specific language governing permissions and 14f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten * limitations under the License. 15f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten */ 16f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 177126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten// Test program to record from default audio input and playback to default audio output. 187126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten// It will generate feedback (Larsen effect) if played through on-device speakers, 197126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten// or acts as a delay if played through headset. 205ef8af762b27b4fa45f59d944b11ad00311cb14bGlenn Kasten 21f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten#include "SLES/OpenSLES.h" 2201e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten#include "SLES/OpenSLES_Android.h" 23f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten#include <assert.h> 247126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten#include <pthread.h> 25f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten#include <stdio.h> 26f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten#include <stdlib.h> 27527b7d2e606abdbde0e29fe75f7e9a67285629d2Glenn Kasten#include <string.h> 28f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten#include <unistd.h> 29f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 300ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten#define ASSERT_EQ(x, y) do { if ((x) == (y)) ; else { fprintf(stderr, "0x%x != 0x%x\n", \ 310ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten (unsigned) (x), (unsigned) (y)); assert((x) == (y)); } } while (0) 32f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 330ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten// default values 3458432eb9cea995c69b4f905e68b38c1b8216edebGlenn Kastenstatic SLuint32 rxBufCount = 2; // -r# 350ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kastenstatic SLuint32 txBufCount = 2; // -t# 360ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kastenstatic SLuint32 bufSizeInFrames = 512; // -f# 3758432eb9cea995c69b4f905e68b38c1b8216edebGlenn Kastenstatic SLuint32 channels = 1; // -c# 380ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kastenstatic SLuint32 sampleRate = 44100; // -s# 397126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenstatic SLuint32 exitAfterSeconds = 60; // -e# 407126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenstatic SLuint32 freeBufCount = 0; // calculated 41e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kastenstatic SLuint32 bufSizeInBytes = 0; // calculated 420ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten 437126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten// Storage area for the buffer queues 447126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenstatic char **rxBuffers; 457126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenstatic char **txBuffers; 467126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenstatic char **freeBuffers; 47f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 487126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten// Buffer indices 497126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenstatic SLuint32 rxFront; // oldest recording 507126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenstatic SLuint32 rxRear; // next to be recorded 517126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenstatic SLuint32 txFront; // oldest playing 527126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenstatic SLuint32 txRear; // next to be played 537126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenstatic SLuint32 freeFront; // oldest free 547126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenstatic SLuint32 freeRear; // next to be freed 55f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 567126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenstatic SLAndroidSimpleBufferQueueItf recorderBufferQueue; 577126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenstatic SLBufferQueueItf playerBufferQueue; 58f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 597126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenstatic pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 600ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten 617126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten// Called after audio recorder fills a buffer with data 627126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenstatic void recorderCallback(SLAndroidSimpleBufferQueueItf caller, void *context) 630ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten{ 647126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten SLresult result; 657126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 667126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten pthread_mutex_lock(&mutex); 677126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 687126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // We should only be called when a recording buffer is done 697126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(rxFront <= rxBufCount); 707126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(rxRear <= rxBufCount); 717126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(rxFront != rxRear); 727126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten char *buffer = rxBuffers[rxFront]; 737126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 747126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // Remove buffer from record queue 757126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten if (++rxFront > rxBufCount) { 767126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten rxFront = 0; 777126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } 787126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 797126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // Enqueue the just-filled buffer for the player 807126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten result = (*playerBufferQueue)->Enqueue(playerBufferQueue, buffer, bufSizeInBytes); 817126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten if (SL_RESULT_SUCCESS == result) { 827126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 837126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // There was room in the play queue, update our model of it 847126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(txFront <= txBufCount); 857126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(txRear <= txBufCount); 867126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten SLuint32 txRearNext = txRear+1; 877126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten if (txRearNext > txBufCount) { 887126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten txRearNext = 0; 897126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } 907126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(txRearNext != txFront); 917126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten txBuffers[txRear] = buffer; 927126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten txRear = txRearNext; 937126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 947126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } else { 957126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 967126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // Here if record has a filled buffer to play, but play queue is full. 977126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(SL_RESULT_BUFFER_INSUFFICIENT == result); 987126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten write(1, "?", 1); 997126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 1007126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // We could either try again later, or discard. For now we discard and re-use buffer. 1017126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // Enqueue this same buffer for the recorder to fill again. 1027126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten result = (*recorderBufferQueue)->Enqueue(recorderBufferQueue, buffer, bufSizeInBytes); 1037126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 1047126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 1057126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // Update our model of the record queue 1067126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten SLuint32 rxRearNext = rxRear+1; 1077126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten if (rxRearNext > rxBufCount) { 1087126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten rxRearNext = 0; 1097126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } 1107126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(rxRearNext != rxFront); 1117126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten rxBuffers[rxRear] = buffer; 1127126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten rxRear = rxRearNext; 1137126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 1147126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } 1157126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 1167126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten pthread_mutex_unlock(&mutex); 1170ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten} 1180ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten 1197126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 1207126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten// Called after audio player empties a buffer of data 1217126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenstatic void playerCallback(SLBufferQueueItf caller, void *context) 122f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten{ 123f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLresult result; 1247126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 1257126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten pthread_mutex_lock(&mutex); 1267126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 1277126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // Get the buffer that just finished playing 1287126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(txFront <= txBufCount); 1297126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(txRear <= txBufCount); 1307126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(txFront != txRear); 1317126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten char *buffer = txBuffers[txFront]; 1327126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten if (++txFront > txBufCount) { 1337126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten txFront = 0; 134e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten } 135f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 1367126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // First try to enqueue the free buffer for recording 1370ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten result = (*recorderBufferQueue)->Enqueue(recorderBufferQueue, buffer, bufSizeInBytes); 1385ef8af762b27b4fa45f59d944b11ad00311cb14bGlenn Kasten if (SL_RESULT_SUCCESS == result) { 1397126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 1407126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // There was room in the record queue, update our model of it 1417126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(rxFront <= rxBufCount); 1427126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(rxRear <= rxBufCount); 1437126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten SLuint32 rxRearNext = rxRear+1; 1447126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten if (rxRearNext > rxBufCount) { 1457126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten rxRearNext = 0; 1467126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } 1477126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(rxRearNext != rxFront); 1487126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten rxBuffers[rxRear] = buffer; 1497126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten rxRear = rxRearNext; 1507126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 1510ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten } else { 1527126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 1537126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // Here if record queue is full 1547126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(SL_RESULT_BUFFER_INSUFFICIENT == result); 1557126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 1567126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // Instead enqueue the free buffer on the free queue 1577126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(freeFront <= freeBufCount); 1587126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(freeRear <= freeBufCount); 1597126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten SLuint32 freeRearNext = freeRear+1; 1607126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten if (freeRearNext > freeBufCount) { 1617126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten freeRearNext = 0; 1627126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } 1637126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // There must always be room in the free queue 1647126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(freeRearNext != freeFront); 1657126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten freeBuffers[freeRear] = buffer; 1667126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten freeRear = freeRearNext; 1677126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 1685ef8af762b27b4fa45f59d944b11ad00311cb14bGlenn Kasten } 169f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 1707126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten pthread_mutex_unlock(&mutex); 171f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten} 172f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 1737126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten// Main program 174f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kastenint main(int argc, char **argv) 175f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten{ 1760ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten // process command-line options 1770ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten int i; 1780ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten for (i = 1; i < argc; ++i) { 1790ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten char *arg = argv[i]; 1807126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten if (arg[0] != '-') { 1810ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten break; 1827126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } 1837126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // -r# number of slots in receive buffer queue 1840ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten if (!strncmp(arg, "-r", 2)) { 1850ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten rxBufCount = atoi(&arg[2]); 1867126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten if (rxBufCount < 1 || rxBufCount > 16) { 1877126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten fprintf(stderr, "%s: unusual receive buffer queue size (%u buffers)\n", argv[0], 1880ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten (unsigned) rxBufCount); 1897126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } 1907126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // -t# number of slots in transmit buffer queue 1910ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten } else if (!strncmp(arg, "-t", 2)) { 1920ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten txBufCount = atoi(&arg[2]); 1937126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten if (txBufCount < 1 || txBufCount > 16) { 1947126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten fprintf(stderr, "%s: unusual transmit buffer queue size (%u buffers)\n", argv[0], 1950ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten (unsigned) txBufCount); 1967126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } 1970ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten // -f# size of each buffer in frames 1980ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten } else if (!strncmp(arg, "-f", 2)) { 1990ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten bufSizeInFrames = atoi(&arg[2]); 2000ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten if (bufSizeInFrames == 0) { 2010ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, "%s: unusual buffer size (%u frames)\n", argv[0], 2020ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten (unsigned) bufSizeInFrames); 2030ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten } 2040ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten // -c1 mono or -c2 stereo 2050ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten } else if (!strncmp(arg, "-c", 2)) { 2060ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten channels = atoi(&arg[2]); 2070ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten if (channels < 1 || channels > 2) { 2080ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, "%s: unusual channel count ignored (%u)\n", argv[0], 2090ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten (unsigned) channels); 2100ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten channels = 2; 2110ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten } 2120ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten // -s# sample rate in Hz 2130ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten } else if (!strncmp(arg, "-s", 2)) { 2140ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten sampleRate = atoi(&arg[2]); 2150ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten switch (sampleRate) { 2160ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten case 8000: 2170ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten case 11025: 2187126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten case 12000: 2190ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten case 16000: 2200ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten case 22050: 2217126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten case 24000: 2220ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten case 32000: 2230ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten case 44100: 2247126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten case 48000: 2250ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten break; 2260ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten default: 2270ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, "%s: unusual sample rate (%u Hz)\n", argv[0], 2280ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten (unsigned) sampleRate); 2290ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten break; 2300ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten } 2317126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // -e# exit after this many seconds 2327126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } else if (!strncmp(arg, "-e", 2)) { 2337126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten exitAfterSeconds = atoi(&arg[2]); 2340ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten } else 2350ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, "%s: unknown option %s\n", argv[0], arg); 2360ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten } 2377126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // no other arguments allowed 2380ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten if (i < argc) { 2397126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten fprintf(stderr, "usage: %s -r# -t# -f# -s# -c#\n", argv[0]); 2400ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, " -r# receive buffer queue count for microphone input, default 1\n"); 2410ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, " -t# transmit buffer queue count for speaker output, default 2\n"); 2420ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, " -f# number of frames per buffer, default 512\n"); 2430ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, " -s# sample rate in Hz, default 44100\n"); 2440ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, " -c1 mono\n"); 2450ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, " -c2 stereo, default\n"); 2460ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten } 2477126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // compute total free buffers as -r plus -t 2487126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten freeBufCount = rxBufCount + txBufCount; 2497126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // compute buffer size 2500ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten bufSizeInBytes = channels * bufSizeInFrames * sizeof(short); 2517126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 2527126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // Initialize free buffers 2537126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten freeBuffers = (char **) calloc(freeBufCount+1, sizeof(char *)); 2547126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten unsigned j; 2557126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten for (j = 0; j < freeBufCount; ++j) { 2567126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten freeBuffers[j] = (char *) malloc(bufSizeInBytes); 2577126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } 2587126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten freeFront = 0; 2597126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten freeRear = freeBufCount; 2607126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten freeBuffers[j] = NULL; 2617126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 2627126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // Initialize record queue 2637126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten rxBuffers = (char **) calloc(rxBufCount+1, sizeof(char *)); 2647126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten rxFront = 0; 2657126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten rxRear = 0; 2667126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 2677126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // Initialize play queue 2687126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten txBuffers = (char **) calloc(txBufCount+1, sizeof(char *)); 2697126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten txFront = 0; 2707126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten txRear = 0; 2717126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 272f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLresult result; 273f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 274f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten // create engine 275f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLObjectItf engineObject; 276f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); 277f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 278f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); 279f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 280f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLEngineItf engineEngine; 281f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine); 282f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 283f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 284f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten // create output mix 285f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLObjectItf outputmixObject; 286f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*engineEngine)->CreateOutputMix(engineEngine, &outputmixObject, 0, NULL, NULL); 287f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 288f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*outputmixObject)->Realize(outputmixObject, SL_BOOLEAN_FALSE); 289f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 290f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 291f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten // create an audio player with buffer queue source and output mix sink 292f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLDataSource audiosrc; 293f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLDataSink audiosnk; 294f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLDataFormat_PCM pcm; 295f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLDataLocator_OutputMix locator_outputmix; 29601e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten SLDataLocator_BufferQueue locator_bufferqueue_tx; 29701e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten locator_bufferqueue_tx.locatorType = SL_DATALOCATOR_BUFFERQUEUE; 29801e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten locator_bufferqueue_tx.numBuffers = txBufCount; 299f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX; 300f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten locator_outputmix.outputMix = outputmixObject; 301f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten pcm.formatType = SL_DATAFORMAT_PCM; 3020ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten pcm.numChannels = channels; 3030ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten pcm.samplesPerSec = sampleRate * 1000; 304f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16; 305f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten pcm.containerSize = 16; 3060ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten pcm.channelMask = channels == 1 ? SL_SPEAKER_FRONT_CENTER : 3070ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT); 308f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten pcm.endianness = SL_BYTEORDER_LITTLEENDIAN; 30901e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten audiosrc.pLocator = &locator_bufferqueue_tx; 310f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten audiosrc.pFormat = &pcm; 311f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten audiosnk.pLocator = &locator_outputmix; 312f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten audiosnk.pFormat = NULL; 3137126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten SLObjectItf playerObject = NULL; 3147126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten SLObjectItf recorderObject = NULL; 31501e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten SLInterfaceID ids_tx[1] = {SL_IID_BUFFERQUEUE}; 31601e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten SLboolean flags_tx[1] = {SL_BOOLEAN_TRUE}; 3170ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten result = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, &audiosrc, &audiosnk, 31801e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten 1, ids_tx, flags_tx); 3197126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten if (SL_RESULT_CONTENT_UNSUPPORTED == result) { 32058432eb9cea995c69b4f905e68b38c1b8216edebGlenn Kasten fprintf(stderr, "Could not create audio player (result %x), check sample rate\n", result); 3217126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten goto cleanup; 3227126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } 323f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 324f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*playerObject)->Realize(playerObject, SL_BOOLEAN_FALSE); 325f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 326f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLPlayItf playerPlay; 327f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAY, &playerPlay); 328f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 329f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*playerObject)->GetInterface(playerObject, SL_IID_BUFFERQUEUE, &playerBufferQueue); 330f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 3317126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten result = (*playerBufferQueue)->RegisterCallback(playerBufferQueue, playerCallback, NULL); 3327126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 333f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING); 334f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 335f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 336f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten // Create an audio recorder with microphone device source and buffer queue sink. 337f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten // The buffer queue as sink is an Android-specific extension. 338f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 339f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLDataLocator_IODevice locator_iodevice; 34001e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten SLDataLocator_AndroidSimpleBufferQueue locator_bufferqueue_rx; 341f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten locator_iodevice.locatorType = SL_DATALOCATOR_IODEVICE; 342f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten locator_iodevice.deviceType = SL_IODEVICE_AUDIOINPUT; 343f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten locator_iodevice.deviceID = SL_DEFAULTDEVICEID_AUDIOINPUT; 344f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten locator_iodevice.device = NULL; 345f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten audiosrc.pLocator = &locator_iodevice; 34635c82a8173d1fcc18ae0bc08954a018bfce041deGlenn Kasten audiosrc.pFormat = NULL; 34701e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten locator_bufferqueue_rx.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; 34801e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten locator_bufferqueue_rx.numBuffers = rxBufCount; 34901e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten audiosnk.pLocator = &locator_bufferqueue_rx; 350f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten audiosnk.pFormat = &pcm; 3517126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten { 35201e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten SLInterfaceID ids_rx[1] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE}; 35301e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten SLboolean flags_rx[1] = {SL_BOOLEAN_TRUE}; 3540ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten result = (*engineEngine)->CreateAudioRecorder(engineEngine, &recorderObject, &audiosrc, 35501e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten &audiosnk, 1, ids_rx, flags_rx); 3567126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten if (SL_RESULT_SUCCESS != result) { 35758432eb9cea995c69b4f905e68b38c1b8216edebGlenn Kasten fprintf(stderr, "Could not create audio recorder (result %x), " 3587126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten "check sample rate and channel count\n", result); 3597126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten goto cleanup; 3607126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } 3617126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } 362f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 363f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*recorderObject)->Realize(recorderObject, SL_BOOLEAN_FALSE); 364f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 365f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLRecordItf recorderRecord; 366f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*recorderObject)->GetInterface(recorderObject, SL_IID_RECORD, &recorderRecord); 367f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 36801e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten result = (*recorderObject)->GetInterface(recorderObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, 3690ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten &recorderBufferQueue); 370f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 371f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*recorderBufferQueue)->RegisterCallback(recorderBufferQueue, recorderCallback, NULL); 372f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 373f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 374f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten // Enqueue some empty buffers for the recorder 3757126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten for (j = 0; j < rxBufCount; ++j) { 3767126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 3777126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // allocate a free buffer 3787126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(freeFront != freeRear); 3797126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten char *buffer = freeBuffers[freeFront]; 3807126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten if (++freeFront > freeBufCount) { 3817126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten freeFront = 0; 3827126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } 3837126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 3847126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // put on record queue 3857126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten SLuint32 rxRearNext = rxRear + 1; 3867126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten if (rxRearNext > rxBufCount) { 3877126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten rxRearNext = 0; 3887126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } 3897126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(rxRearNext != rxFront); 3907126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten rxBuffers[rxRear] = buffer; 3917126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten rxRear = rxRearNext; 3920ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten result = (*recorderBufferQueue)->Enqueue(recorderBufferQueue, 3937126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten buffer, bufSizeInBytes); 394f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 395f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten } 396f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 397f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten // Kick off the recorder 398f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_RECORDING); 399f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 400f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 401f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten // Wait patiently 4027126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten do { 403f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten usleep(1000000); 4047126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten write(1, ".", 1); 405f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLBufferQueueState playerBQState; 406f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*playerBufferQueue)->GetState(playerBufferQueue, &playerBQState); 407f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 40801e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten SLAndroidSimpleBufferQueueState recorderBQState; 409f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*recorderBufferQueue)->GetState(recorderBufferQueue, &recorderBQState); 410f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 4117126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } while (--exitAfterSeconds); 4127126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 4137126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // Tear down the objects and exit 4147126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastencleanup: 4157126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten if (NULL != playerObject) { 4167126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten (*playerObject)->Destroy(playerObject); 4177126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } 4187126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten if (NULL != recorderObject) { 4197126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten (*recorderObject)->Destroy(recorderObject); 420f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten } 4217126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten (*outputmixObject)->Destroy(outputmixObject); 4227126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten (*engineObject)->Destroy(engineObject); 423f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 4247126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten return EXIT_SUCCESS; 425f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten} 426