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 21c6853892c94800e72c0bd676d5d2136d48cea76eGlenn Kasten#include <SLES/OpenSLES.h> 22c6853892c94800e72c0bd676d5d2136d48cea76eGlenn 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 30fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten#include <media/nbaio/MonoPipe.h> 31fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten#include <media/nbaio/MonoPipeReader.h> 32fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten 330ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten#define ASSERT_EQ(x, y) do { if ((x) == (y)) ; else { fprintf(stderr, "0x%x != 0x%x\n", \ 340ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten (unsigned) (x), (unsigned) (y)); assert((x) == (y)); } } while (0) 35f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 360ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten// default values 3758432eb9cea995c69b4f905e68b38c1b8216edebGlenn Kastenstatic SLuint32 rxBufCount = 2; // -r# 380ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kastenstatic SLuint32 txBufCount = 2; // -t# 39fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kastenstatic SLuint32 bufSizeInFrames = 240; // -f# 4058432eb9cea995c69b4f905e68b38c1b8216edebGlenn Kastenstatic SLuint32 channels = 1; // -c# 41fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kastenstatic SLuint32 sampleRate = 48000; // -s# 427126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenstatic SLuint32 exitAfterSeconds = 60; // -e# 437126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenstatic SLuint32 freeBufCount = 0; // calculated 44e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kastenstatic SLuint32 bufSizeInBytes = 0; // calculated 450ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten 467126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten// Storage area for the buffer queues 477126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenstatic char **rxBuffers; 487126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenstatic char **txBuffers; 497126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenstatic char **freeBuffers; 50f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 517126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten// Buffer indices 527126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenstatic SLuint32 rxFront; // oldest recording 537126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenstatic SLuint32 rxRear; // next to be recorded 547126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenstatic SLuint32 txFront; // oldest playing 557126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenstatic SLuint32 txRear; // next to be played 567126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenstatic SLuint32 freeFront; // oldest free 577126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenstatic SLuint32 freeRear; // next to be freed 58f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 597126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenstatic SLAndroidSimpleBufferQueueItf recorderBufferQueue; 607126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenstatic SLBufferQueueItf playerBufferQueue; 61f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 627126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenstatic pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 630ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten 64fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kastenstatic android::MonoPipeReader *pipeReader; 65fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kastenstatic android::MonoPipe *pipeWriter; 66fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten 677126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten// Called after audio recorder fills a buffer with data 687126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenstatic void recorderCallback(SLAndroidSimpleBufferQueueItf caller, void *context) 690ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten{ 707126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten SLresult result; 717126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 727126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten pthread_mutex_lock(&mutex); 737126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 747126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // We should only be called when a recording buffer is done 757126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(rxFront <= rxBufCount); 767126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(rxRear <= rxBufCount); 777126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(rxFront != rxRear); 787126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten char *buffer = rxBuffers[rxFront]; 797126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 807126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // Remove buffer from record queue 817126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten if (++rxFront > rxBufCount) { 827126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten rxFront = 0; 837126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } 847126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 85fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten#if 1 86fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten ssize_t actual = pipeWriter->write(buffer, (size_t) bufSizeInFrames); 87fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten if (actual != (ssize_t) bufSizeInFrames) { 88fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten write(1, "?", 1); 89fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten } 90fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten 91fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten // Enqueue this same buffer for the recorder to fill again. 92fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten result = (*recorderBufferQueue)->Enqueue(recorderBufferQueue, buffer, bufSizeInBytes); 93fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 94fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten 95fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten // Update our model of the record queue 96fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten SLuint32 rxRearNext = rxRear+1; 97fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten if (rxRearNext > rxBufCount) { 98fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten rxRearNext = 0; 99fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten } 100fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten assert(rxRearNext != rxFront); 101fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten rxBuffers[rxRear] = buffer; 102fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten rxRear = rxRearNext; 103fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten 104fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten#else 1057126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // Enqueue the just-filled buffer for the player 1067126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten result = (*playerBufferQueue)->Enqueue(playerBufferQueue, buffer, bufSizeInBytes); 1077126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten if (SL_RESULT_SUCCESS == result) { 1087126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 1097126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // There was room in the play queue, update our model of it 1107126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(txFront <= txBufCount); 1117126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(txRear <= txBufCount); 1127126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten SLuint32 txRearNext = txRear+1; 1137126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten if (txRearNext > txBufCount) { 1147126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten txRearNext = 0; 1157126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } 1167126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(txRearNext != txFront); 1177126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten txBuffers[txRear] = buffer; 1187126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten txRear = txRearNext; 1197126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 1207126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } else { 1217126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 1227126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // Here if record has a filled buffer to play, but play queue is full. 1237126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(SL_RESULT_BUFFER_INSUFFICIENT == result); 1247126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten write(1, "?", 1); 1257126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 1267126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // We could either try again later, or discard. For now we discard and re-use buffer. 1277126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // Enqueue this same buffer for the recorder to fill again. 1287126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten result = (*recorderBufferQueue)->Enqueue(recorderBufferQueue, buffer, bufSizeInBytes); 1297126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 1307126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 1317126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // Update our model of the record queue 1327126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten SLuint32 rxRearNext = rxRear+1; 1337126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten if (rxRearNext > rxBufCount) { 1347126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten rxRearNext = 0; 1357126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } 1367126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(rxRearNext != rxFront); 1377126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten rxBuffers[rxRear] = buffer; 1387126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten rxRear = rxRearNext; 1397126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 1407126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } 141fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten#endif 1427126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 1437126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten pthread_mutex_unlock(&mutex); 1440ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten} 1450ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten 1467126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 1477126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten// Called after audio player empties a buffer of data 1487126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenstatic void playerCallback(SLBufferQueueItf caller, void *context) 149f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten{ 150f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLresult result; 1517126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 1527126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten pthread_mutex_lock(&mutex); 1537126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 1547126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // Get the buffer that just finished playing 1557126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(txFront <= txBufCount); 1567126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(txRear <= txBufCount); 1577126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(txFront != txRear); 1587126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten char *buffer = txBuffers[txFront]; 1597126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten if (++txFront > txBufCount) { 1607126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten txFront = 0; 161e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten } 162f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 163fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten#if 1 164fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten ssize_t actual = pipeReader->read(buffer, bufSizeInFrames, (int64_t) -1); 165fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten if (actual != (ssize_t) bufSizeInFrames) { 166fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten write(1, "/", 1); 167fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten // on underrun from pipe, substitute silence 168fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten memset(buffer, 0, bufSizeInFrames * channels * sizeof(short)); 169fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten } 170fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten 171fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten // Enqueue the filled buffer for playing 172fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten result = (*playerBufferQueue)->Enqueue(playerBufferQueue, buffer, bufSizeInBytes); 173fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 174fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten 175fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten // Update our model of the player queue 176fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten assert(txFront <= txBufCount); 177fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten assert(txRear <= txBufCount); 178fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten SLuint32 txRearNext = txRear+1; 179fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten if (txRearNext > txBufCount) { 180fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten txRearNext = 0; 181fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten } 182fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten assert(txRearNext != txFront); 183fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten txBuffers[txRear] = buffer; 184fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten txRear = txRearNext; 185fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten 186fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten#else 1877126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // First try to enqueue the free buffer for recording 1880ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten result = (*recorderBufferQueue)->Enqueue(recorderBufferQueue, buffer, bufSizeInBytes); 1895ef8af762b27b4fa45f59d944b11ad00311cb14bGlenn Kasten if (SL_RESULT_SUCCESS == result) { 1907126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 1917126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // There was room in the record queue, update our model of it 1927126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(rxFront <= rxBufCount); 1937126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(rxRear <= rxBufCount); 1947126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten SLuint32 rxRearNext = rxRear+1; 1957126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten if (rxRearNext > rxBufCount) { 1967126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten rxRearNext = 0; 1977126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } 1987126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(rxRearNext != rxFront); 1997126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten rxBuffers[rxRear] = buffer; 2007126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten rxRear = rxRearNext; 2017126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 2020ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten } else { 2037126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 2047126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // Here if record queue is full 2057126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(SL_RESULT_BUFFER_INSUFFICIENT == result); 2067126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 2077126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // Instead enqueue the free buffer on the free queue 2087126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(freeFront <= freeBufCount); 2097126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(freeRear <= freeBufCount); 2107126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten SLuint32 freeRearNext = freeRear+1; 2117126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten if (freeRearNext > freeBufCount) { 2127126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten freeRearNext = 0; 2137126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } 2147126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // There must always be room in the free queue 2157126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(freeRearNext != freeFront); 2167126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten freeBuffers[freeRear] = buffer; 2177126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten freeRear = freeRearNext; 2187126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 2195ef8af762b27b4fa45f59d944b11ad00311cb14bGlenn Kasten } 220fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten#endif 221f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 2227126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten pthread_mutex_unlock(&mutex); 223f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten} 224f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 2257126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten// Main program 226f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kastenint main(int argc, char **argv) 227f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten{ 2280ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten // process command-line options 2290ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten int i; 2300ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten for (i = 1; i < argc; ++i) { 2310ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten char *arg = argv[i]; 2327126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten if (arg[0] != '-') { 2330ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten break; 2347126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } 2357126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // -r# number of slots in receive buffer queue 2360ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten if (!strncmp(arg, "-r", 2)) { 2370ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten rxBufCount = atoi(&arg[2]); 2387126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten if (rxBufCount < 1 || rxBufCount > 16) { 2397126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten fprintf(stderr, "%s: unusual receive buffer queue size (%u buffers)\n", argv[0], 2400ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten (unsigned) rxBufCount); 2417126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } 2427126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // -t# number of slots in transmit buffer queue 2430ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten } else if (!strncmp(arg, "-t", 2)) { 2440ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten txBufCount = atoi(&arg[2]); 2457126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten if (txBufCount < 1 || txBufCount > 16) { 2467126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten fprintf(stderr, "%s: unusual transmit buffer queue size (%u buffers)\n", argv[0], 2470ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten (unsigned) txBufCount); 2487126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } 2490ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten // -f# size of each buffer in frames 2500ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten } else if (!strncmp(arg, "-f", 2)) { 2510ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten bufSizeInFrames = atoi(&arg[2]); 2520ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten if (bufSizeInFrames == 0) { 2530ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, "%s: unusual buffer size (%u frames)\n", argv[0], 2540ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten (unsigned) bufSizeInFrames); 2550ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten } 2560ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten // -c1 mono or -c2 stereo 2570ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten } else if (!strncmp(arg, "-c", 2)) { 2580ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten channels = atoi(&arg[2]); 2590ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten if (channels < 1 || channels > 2) { 2600ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, "%s: unusual channel count ignored (%u)\n", argv[0], 2610ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten (unsigned) channels); 2620ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten channels = 2; 2630ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten } 2640ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten // -s# sample rate in Hz 2650ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten } else if (!strncmp(arg, "-s", 2)) { 2660ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten sampleRate = atoi(&arg[2]); 2670ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten switch (sampleRate) { 2680ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten case 8000: 2690ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten case 11025: 2707126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten case 12000: 2710ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten case 16000: 2720ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten case 22050: 2737126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten case 24000: 2740ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten case 32000: 2750ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten case 44100: 2767126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten case 48000: 2770ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten break; 2780ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten default: 2790ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, "%s: unusual sample rate (%u Hz)\n", argv[0], 2800ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten (unsigned) sampleRate); 2810ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten break; 2820ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten } 2837126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // -e# exit after this many seconds 2847126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } else if (!strncmp(arg, "-e", 2)) { 2857126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten exitAfterSeconds = atoi(&arg[2]); 2860ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten } else 2870ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, "%s: unknown option %s\n", argv[0], arg); 2880ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten } 2897126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // no other arguments allowed 2900ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten if (i < argc) { 2917126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten fprintf(stderr, "usage: %s -r# -t# -f# -s# -c#\n", argv[0]); 2920ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, " -r# receive buffer queue count for microphone input, default 1\n"); 2930ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, " -t# transmit buffer queue count for speaker output, default 2\n"); 2940ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, " -f# number of frames per buffer, default 512\n"); 2950ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, " -s# sample rate in Hz, default 44100\n"); 2960ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, " -c1 mono\n"); 2970ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, " -c2 stereo, default\n"); 2980ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten } 2997126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // compute total free buffers as -r plus -t 3007126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten freeBufCount = rxBufCount + txBufCount; 3017126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // compute buffer size 3020ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten bufSizeInBytes = channels * bufSizeInFrames * sizeof(short); 3037126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 3047126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // Initialize free buffers 3057126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten freeBuffers = (char **) calloc(freeBufCount+1, sizeof(char *)); 3067126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten unsigned j; 3077126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten for (j = 0; j < freeBufCount; ++j) { 3087126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten freeBuffers[j] = (char *) malloc(bufSizeInBytes); 3097126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } 3107126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten freeFront = 0; 3117126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten freeRear = freeBufCount; 3127126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten freeBuffers[j] = NULL; 3137126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 3147126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // Initialize record queue 3157126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten rxBuffers = (char **) calloc(rxBufCount+1, sizeof(char *)); 3167126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten rxFront = 0; 3177126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten rxRear = 0; 3187126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 3197126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // Initialize play queue 3207126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten txBuffers = (char **) calloc(txBufCount+1, sizeof(char *)); 3217126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten txFront = 0; 3227126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten txRear = 0; 3237126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 324fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten const android::NBAIO_Format nbaio_format = android::Format_from_SR_C(sampleRate, channels, 325fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten AUDIO_FORMAT_PCM_16_BIT); 326fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten pipeWriter = new android::MonoPipe(1024, nbaio_format, false /*writeCanBlock*/); 327fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten android::NBAIO_Format offer = nbaio_format; 328fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten size_t numCounterOffers = 0; 329fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten ssize_t neg = pipeWriter->negotiate(&offer, 1, NULL, numCounterOffers); 330fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten assert(0 == neg); 331fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten pipeReader = new android::MonoPipeReader(pipeWriter); 332fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten numCounterOffers = 0; 333fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten neg = pipeReader->negotiate(&offer, 1, NULL, numCounterOffers); 334fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten assert(0 == neg); 335fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten 336f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLresult result; 337f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 338f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten // create engine 339f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLObjectItf engineObject; 340f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); 341f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 342f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); 343f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 344f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLEngineItf engineEngine; 345f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine); 346f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 347f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 348f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten // create output mix 349f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLObjectItf outputmixObject; 350f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*engineEngine)->CreateOutputMix(engineEngine, &outputmixObject, 0, NULL, NULL); 351f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 352f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*outputmixObject)->Realize(outputmixObject, SL_BOOLEAN_FALSE); 353f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 354f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 355f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten // create an audio player with buffer queue source and output mix sink 356f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLDataSource audiosrc; 357f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLDataSink audiosnk; 358f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLDataFormat_PCM pcm; 359f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLDataLocator_OutputMix locator_outputmix; 36001e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten SLDataLocator_BufferQueue locator_bufferqueue_tx; 36101e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten locator_bufferqueue_tx.locatorType = SL_DATALOCATOR_BUFFERQUEUE; 36201e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten locator_bufferqueue_tx.numBuffers = txBufCount; 363f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX; 364f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten locator_outputmix.outputMix = outputmixObject; 365f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten pcm.formatType = SL_DATAFORMAT_PCM; 3660ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten pcm.numChannels = channels; 3670ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten pcm.samplesPerSec = sampleRate * 1000; 368f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16; 369f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten pcm.containerSize = 16; 3700ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten pcm.channelMask = channels == 1 ? SL_SPEAKER_FRONT_CENTER : 3710ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT); 372f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten pcm.endianness = SL_BYTEORDER_LITTLEENDIAN; 37301e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten audiosrc.pLocator = &locator_bufferqueue_tx; 374f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten audiosrc.pFormat = &pcm; 375f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten audiosnk.pLocator = &locator_outputmix; 376f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten audiosnk.pFormat = NULL; 3777126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten SLObjectItf playerObject = NULL; 3787126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten SLObjectItf recorderObject = NULL; 37901e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten SLInterfaceID ids_tx[1] = {SL_IID_BUFFERQUEUE}; 38001e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten SLboolean flags_tx[1] = {SL_BOOLEAN_TRUE}; 3810ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten result = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, &audiosrc, &audiosnk, 38201e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten 1, ids_tx, flags_tx); 3837126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten if (SL_RESULT_CONTENT_UNSUPPORTED == result) { 38458432eb9cea995c69b4f905e68b38c1b8216edebGlenn Kasten fprintf(stderr, "Could not create audio player (result %x), check sample rate\n", result); 3857126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten goto cleanup; 3867126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } 387f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 388f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*playerObject)->Realize(playerObject, SL_BOOLEAN_FALSE); 389f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 390f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLPlayItf playerPlay; 391f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAY, &playerPlay); 392f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 393f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*playerObject)->GetInterface(playerObject, SL_IID_BUFFERQUEUE, &playerBufferQueue); 394f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 3957126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten result = (*playerBufferQueue)->RegisterCallback(playerBufferQueue, playerCallback, NULL); 3967126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 397fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten 398fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten // Enqueue some zero buffers for the player 399fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten for (j = 0; j < txBufCount; ++j) { 400fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten 401fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten // allocate a free buffer 402fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten assert(freeFront != freeRear); 403fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten char *buffer = freeBuffers[freeFront]; 404fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten if (++freeFront > freeBufCount) { 405fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten freeFront = 0; 406fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten } 407fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten 408fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten // put on play queue 409fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten SLuint32 txRearNext = txRear + 1; 410fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten if (txRearNext > txBufCount) { 411fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten txRearNext = 0; 412fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten } 413fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten assert(txRearNext != txFront); 414fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten txBuffers[txRear] = buffer; 415fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten txRear = txRearNext; 416fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten result = (*playerBufferQueue)->Enqueue(playerBufferQueue, 417fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten buffer, bufSizeInBytes); 418fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 419fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten } 420fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten 421f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING); 422f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 423f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 424f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten // Create an audio recorder with microphone device source and buffer queue sink. 425f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten // The buffer queue as sink is an Android-specific extension. 426f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 427f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLDataLocator_IODevice locator_iodevice; 42801e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten SLDataLocator_AndroidSimpleBufferQueue locator_bufferqueue_rx; 429f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten locator_iodevice.locatorType = SL_DATALOCATOR_IODEVICE; 430f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten locator_iodevice.deviceType = SL_IODEVICE_AUDIOINPUT; 431f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten locator_iodevice.deviceID = SL_DEFAULTDEVICEID_AUDIOINPUT; 432f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten locator_iodevice.device = NULL; 433f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten audiosrc.pLocator = &locator_iodevice; 43435c82a8173d1fcc18ae0bc08954a018bfce041deGlenn Kasten audiosrc.pFormat = NULL; 43501e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten locator_bufferqueue_rx.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; 43601e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten locator_bufferqueue_rx.numBuffers = rxBufCount; 43701e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten audiosnk.pLocator = &locator_bufferqueue_rx; 438f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten audiosnk.pFormat = &pcm; 4397126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten { 44001e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten SLInterfaceID ids_rx[1] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE}; 44101e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten SLboolean flags_rx[1] = {SL_BOOLEAN_TRUE}; 4420ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten result = (*engineEngine)->CreateAudioRecorder(engineEngine, &recorderObject, &audiosrc, 44301e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten &audiosnk, 1, ids_rx, flags_rx); 4447126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten if (SL_RESULT_SUCCESS != result) { 44558432eb9cea995c69b4f905e68b38c1b8216edebGlenn Kasten fprintf(stderr, "Could not create audio recorder (result %x), " 4467126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten "check sample rate and channel count\n", result); 4477126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten goto cleanup; 4487126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } 4497126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } 450f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 451f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*recorderObject)->Realize(recorderObject, SL_BOOLEAN_FALSE); 452f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 453f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLRecordItf recorderRecord; 454f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*recorderObject)->GetInterface(recorderObject, SL_IID_RECORD, &recorderRecord); 455f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 45601e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten result = (*recorderObject)->GetInterface(recorderObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, 4570ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten &recorderBufferQueue); 458f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 459f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*recorderBufferQueue)->RegisterCallback(recorderBufferQueue, recorderCallback, NULL); 460f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 461f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 462f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten // Enqueue some empty buffers for the recorder 4637126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten for (j = 0; j < rxBufCount; ++j) { 4647126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 4657126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // allocate a free buffer 4667126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(freeFront != freeRear); 4677126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten char *buffer = freeBuffers[freeFront]; 4687126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten if (++freeFront > freeBufCount) { 4697126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten freeFront = 0; 4707126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } 4717126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 4727126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // put on record queue 4737126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten SLuint32 rxRearNext = rxRear + 1; 4747126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten if (rxRearNext > rxBufCount) { 4757126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten rxRearNext = 0; 4767126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } 4777126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten assert(rxRearNext != rxFront); 4787126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten rxBuffers[rxRear] = buffer; 4797126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten rxRear = rxRearNext; 4800ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten result = (*recorderBufferQueue)->Enqueue(recorderBufferQueue, 4817126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten buffer, bufSizeInBytes); 482f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 483f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten } 484f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 485f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten // Kick off the recorder 486f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_RECORDING); 487f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 488f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 489fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten#if 0 490fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten // give recorder a head start so that the pipe is initially filled 491fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten sleep(1); 492fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten#endif 493fdef5de17abc6c30b293861ca276259a7dd93837Glenn Kasten 494f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten // Wait patiently 4957126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten do { 496f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten usleep(1000000); 4977126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten write(1, ".", 1); 498f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLBufferQueueState playerBQState; 499f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*playerBufferQueue)->GetState(playerBufferQueue, &playerBQState); 500f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 50101e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten SLAndroidSimpleBufferQueueState recorderBQState; 502f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*recorderBufferQueue)->GetState(recorderBufferQueue, &recorderBQState); 503f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 5047126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } while (--exitAfterSeconds); 5057126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten 5067126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten // Tear down the objects and exit 5077126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastencleanup: 5087126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten if (NULL != playerObject) { 5097126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten (*playerObject)->Destroy(playerObject); 5107126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten } 5117126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten if (NULL != recorderObject) { 5127126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten (*recorderObject)->Destroy(recorderObject); 513f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten } 5147126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten (*outputmixObject)->Destroy(outputmixObject); 5157126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten (*engineObject)->Destroy(engineObject); 516f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 5177126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten return EXIT_SUCCESS; 518f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten} 519