slesTestFeedback.cpp revision 01e9f5fa4698856f92bcfd88188ee4c8397b22db
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 17f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten// Test program to record from default audio input and playback to default audio output 18f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 195ef8af762b27b4fa45f59d944b11ad00311cb14bGlenn Kasten#undef NDEBUG 205ef8af762b27b4fa45f59d944b11ad00311cb14bGlenn Kasten 21f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten#include "SLES/OpenSLES.h" 2201e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten#include "SLES/OpenSLES_Android.h" 23f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten#include <assert.h> 24f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten#include <stdio.h> 25f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten#include <stdlib.h> 26527b7d2e606abdbde0e29fe75f7e9a67285629d2Glenn Kasten#include <string.h> 27f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten#include <unistd.h> 28f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 290ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten#define ASSERT_EQ(x, y) do { if ((x) == (y)) ; else { fprintf(stderr, "0x%x != 0x%x\n", \ 300ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten (unsigned) (x), (unsigned) (y)); assert((x) == (y)); } } while (0) 31f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 320ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten// default values 330ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kastenstatic SLuint32 rxBufCount = 1; // -r# 340ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kastenstatic SLuint32 txBufCount = 2; // -t# 350ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kastenstatic SLuint32 bufSizeInFrames = 512; // -f# 360ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kastenstatic SLuint32 channels = 2; // -c# 370ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kastenstatic SLuint32 sampleRate = 44100; // -s# 380ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kastenstatic SLuint32 appBufCount = 0; // -n# 39e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kastenstatic SLuint32 bufSizeInBytes = 0; // calculated 40e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kastenstatic SLboolean verbose = SL_BOOLEAN_FALSE; 410ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten 420ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten// Storage area for the buffers 430ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kastenstatic char *buffers = NULL; 44f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 45f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten// Index of which buffer to enqueue next 46f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kastenstatic SLuint32 whichRecord; 47f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kastenstatic SLuint32 whichPlay; 48f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 4901e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn KastenSLAndroidSimpleBufferQueueItf recorderBufferQueue; 50f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn KastenSLBufferQueueItf playerBufferQueue; 51f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 520ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten// Compute maximum of two values 530ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kastenstatic SLuint32 max(SLuint32 a, SLuint32 b) 540ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten{ 550ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten return a >= b ? a : b; 560ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten} 570ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten 580ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten// Compute minimum of two values 590ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kastenstatic SLuint32 min(SLuint32 a, SLuint32 b) 600ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten{ 610ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten return a <= b ? a : b; 620ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten} 630ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten 64f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten// Called after audio recorder fills a buffer with data 6501e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kastenstatic void recorderCallback(SLAndroidSimpleBufferQueueItf caller, void *context) 66f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten{ 67f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLresult result; 68e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten if (verbose) { 69e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten putchar('*'); 70e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten fflush(stdout); 71e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten } 72f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 73f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten // Enqueue the next empty buffer for the recorder to fill 740ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten assert(whichRecord < appBufCount); 750ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten void *buffer = &buffers[bufSizeInBytes * whichRecord]; 760ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten result = (*recorderBufferQueue)->Enqueue(recorderBufferQueue, buffer, bufSizeInBytes); 77f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 780ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten if (++whichRecord >= appBufCount) 79f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten whichRecord = 0; 80f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 81f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten // Enqueue the just-filled buffer for the player to empty 820ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten assert(whichPlay < appBufCount); // sic not tx 830ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten buffer = &buffers[bufSizeInBytes * whichPlay]; 840ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten result = (*playerBufferQueue)->Enqueue(playerBufferQueue, buffer, bufSizeInBytes); 855ef8af762b27b4fa45f59d944b11ad00311cb14bGlenn Kasten // FIXME not sure yet why this is overflowing 865ef8af762b27b4fa45f59d944b11ad00311cb14bGlenn Kasten if (SL_RESULT_SUCCESS == result) { 870ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten if (++whichPlay >= appBufCount) 880ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten whichPlay = 0; 890ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten } else { 900ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten ASSERT_EQ(SL_RESULT_BUFFER_INSUFFICIENT, result); 915ef8af762b27b4fa45f59d944b11ad00311cb14bGlenn Kasten } 92f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 93f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten} 94f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 95f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kastenint main(int argc, char **argv) 96f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten{ 970ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten // process command-line options 980ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten int i; 990ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten for (i = 1; i < argc; ++i) { 1000ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten char *arg = argv[i]; 1010ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten if (arg[0] != '-') 1020ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten break; 1030ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten // -r# number of receive buffers 1040ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten if (!strncmp(arg, "-r", 2)) { 1050ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten rxBufCount = atoi(&arg[2]); 1060ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten if (rxBufCount < 1 || rxBufCount > 8) 1070ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, "%s: unusual receive buffer queue size (%u buffers)", argv[0], 1080ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten (unsigned) rxBufCount); 1090ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten // -t# number of receive buffers 1100ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten } else if (!strncmp(arg, "-t", 2)) { 1110ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten txBufCount = atoi(&arg[2]); 1120ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten if (txBufCount < 1 || txBufCount > 8) 1130ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, "%s: unusual transmit buffer queue size (%u buffers)", argv[0], 1140ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten (unsigned) txBufCount); 1150ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten // -n# number of application buffers 1160ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten } else if (!strncmp(arg, "-n", 2)) { 1170ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten appBufCount = atoi(&arg[2]); 1180ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten // -f# size of each buffer in frames 1190ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten } else if (!strncmp(arg, "-f", 2)) { 1200ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten bufSizeInFrames = atoi(&arg[2]); 1210ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten if (bufSizeInFrames == 0) { 1220ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, "%s: unusual buffer size (%u frames)\n", argv[0], 1230ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten (unsigned) bufSizeInFrames); 1240ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten } 1250ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten // -c1 mono or -c2 stereo 1260ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten } else if (!strncmp(arg, "-c", 2)) { 1270ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten channels = atoi(&arg[2]); 1280ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten if (channels < 1 || channels > 2) { 1290ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, "%s: unusual channel count ignored (%u)\n", argv[0], 1300ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten (unsigned) channels); 1310ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten channels = 2; 1320ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten } 1330ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten // -s# sample rate in Hz 1340ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten } else if (!strncmp(arg, "-s", 2)) { 1350ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten sampleRate = atoi(&arg[2]); 1360ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten switch (sampleRate) { 1370ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten case 8000: 1380ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten case 11025: 1390ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten case 16000: 1400ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten case 22050: 1410ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten case 32000: 1420ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten case 44100: 1430ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten break; 1440ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten default: 1450ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, "%s: unusual sample rate (%u Hz)\n", argv[0], 1460ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten (unsigned) sampleRate); 1470ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten break; 1480ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten } 149e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten // -v verbose 150e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten } else if (!strcmp(arg, "-v")) { 151e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten verbose = SL_BOOLEAN_TRUE; 1520ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten } else 1530ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, "%s: unknown option %s\n", argv[0], arg); 1540ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten } 1550ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten if (i < argc) { 1560ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, "usage: %s -r# -t# -f# -r# -m/-s\n", argv[0]); 1570ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, " -r# receive buffer queue count for microphone input, default 1\n"); 1580ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, " -t# transmit buffer queue count for speaker output, default 2\n"); 1590ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, " -f# number of frames per buffer, default 512\n"); 1600ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, " -s# sample rate in Hz, default 44100\n"); 1610ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, " -n# number of application-allocated buffers, default max(-r#,-t#)\n"); 1620ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, " -c1 mono\n"); 1630ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, " -c2 stereo, default\n"); 1640ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten } 1650ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten if (appBufCount == 0) 1660ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten appBufCount = max(rxBufCount, txBufCount); 1670ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten if (appBufCount == 0) 1680ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten appBufCount = 1; 1690ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten if (appBufCount < max(rxBufCount, txBufCount)) 1700ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten fprintf(stderr, "%s: unusual application buffer count (%u buffers)", argv[0], 1710ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten (unsigned) appBufCount); 1720ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten bufSizeInBytes = channels * bufSizeInFrames * sizeof(short); 1730ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten buffers = (char *) malloc(bufSizeInBytes * appBufCount); 174f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLresult result; 175f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 176f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten // create engine 177f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLObjectItf engineObject; 178f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); 179f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 180f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); 181f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 182f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLEngineItf engineEngine; 183f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine); 184f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 185f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 186f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten // create output mix 187f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLObjectItf outputmixObject; 188f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*engineEngine)->CreateOutputMix(engineEngine, &outputmixObject, 0, NULL, NULL); 189f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 190f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*outputmixObject)->Realize(outputmixObject, SL_BOOLEAN_FALSE); 191f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 192f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 193f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten // create an audio player with buffer queue source and output mix sink 194f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLDataSource audiosrc; 195f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLDataSink audiosnk; 196f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLDataFormat_PCM pcm; 197f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLDataLocator_OutputMix locator_outputmix; 19801e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten SLDataLocator_BufferQueue locator_bufferqueue_tx; 19901e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten locator_bufferqueue_tx.locatorType = SL_DATALOCATOR_BUFFERQUEUE; 20001e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten locator_bufferqueue_tx.numBuffers = txBufCount; 201f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX; 202f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten locator_outputmix.outputMix = outputmixObject; 203f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten pcm.formatType = SL_DATAFORMAT_PCM; 2040ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten pcm.numChannels = channels; 2050ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten pcm.samplesPerSec = sampleRate * 1000; 206f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16; 207f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten pcm.containerSize = 16; 2080ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten pcm.channelMask = channels == 1 ? SL_SPEAKER_FRONT_CENTER : 2090ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT); 210f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten pcm.endianness = SL_BYTEORDER_LITTLEENDIAN; 21101e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten audiosrc.pLocator = &locator_bufferqueue_tx; 212f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten audiosrc.pFormat = &pcm; 213f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten audiosnk.pLocator = &locator_outputmix; 214f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten audiosnk.pFormat = NULL; 215f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLObjectItf playerObject; 21601e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten SLInterfaceID ids_tx[1] = {SL_IID_BUFFERQUEUE}; 21701e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten SLboolean flags_tx[1] = {SL_BOOLEAN_TRUE}; 2180ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten result = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, &audiosrc, &audiosnk, 21901e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten 1, ids_tx, flags_tx); 220f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 221f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*playerObject)->Realize(playerObject, SL_BOOLEAN_FALSE); 222f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 223f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLPlayItf playerPlay; 224f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAY, &playerPlay); 225f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 226f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*playerObject)->GetInterface(playerObject, SL_IID_BUFFERQUEUE, &playerBufferQueue); 227f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 228f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING); 229f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 230f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 231f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten // Create an audio recorder with microphone device source and buffer queue sink. 232f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten // The buffer queue as sink is an Android-specific extension. 233f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 234f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLDataLocator_IODevice locator_iodevice; 23501e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten SLDataLocator_AndroidSimpleBufferQueue locator_bufferqueue_rx; 236f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten locator_iodevice.locatorType = SL_DATALOCATOR_IODEVICE; 237f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten locator_iodevice.deviceType = SL_IODEVICE_AUDIOINPUT; 238f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten locator_iodevice.deviceID = SL_DEFAULTDEVICEID_AUDIOINPUT; 239f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten locator_iodevice.device = NULL; 240f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten audiosrc.pLocator = &locator_iodevice; 241f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten audiosrc.pFormat = &pcm; 24201e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten locator_bufferqueue_rx.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; 24301e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten locator_bufferqueue_rx.numBuffers = rxBufCount; 24401e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten audiosnk.pLocator = &locator_bufferqueue_rx; 245f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten audiosnk.pFormat = &pcm; 246f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLObjectItf recorderObject; 24701e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten SLInterfaceID ids_rx[1] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE}; 24801e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten SLboolean flags_rx[1] = {SL_BOOLEAN_TRUE}; 2490ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten result = (*engineEngine)->CreateAudioRecorder(engineEngine, &recorderObject, &audiosrc, 25001e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten &audiosnk, 1, ids_rx, flags_rx); 251f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 252f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*recorderObject)->Realize(recorderObject, SL_BOOLEAN_FALSE); 253f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 254f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLRecordItf recorderRecord; 255f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*recorderObject)->GetInterface(recorderObject, SL_IID_RECORD, &recorderRecord); 256f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 25701e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten result = (*recorderObject)->GetInterface(recorderObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, 2580ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten &recorderBufferQueue); 259f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 260f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*recorderBufferQueue)->RegisterCallback(recorderBufferQueue, recorderCallback, NULL); 261f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 262f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 263f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten // Enqueue some empty buffers for the recorder 2640ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten SLuint32 temp = min(rxBufCount, appBufCount); 2650ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten for (whichRecord = 0; whichRecord < (temp <= 1 ? 1 : temp - 1); ++whichRecord) { 2660ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten result = (*recorderBufferQueue)->Enqueue(recorderBufferQueue, 2670ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten &buffers[bufSizeInBytes * whichRecord], bufSizeInBytes); 268f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 269f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten } 2700ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten if (whichRecord >= appBufCount) 2710ac2a7d4343d98e3cb02180e548a5a4737ba0df1Glenn Kasten whichRecord = 0; 272f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 273f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten // Kick off the recorder 274f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten whichPlay = 0; 275f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_RECORDING); 276f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 277f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 278f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten // Wait patiently 279f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten for (;;) { 280f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten usleep(1000000); 281f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten putchar('.'); 282f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten SLBufferQueueState playerBQState; 283f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*playerBufferQueue)->GetState(playerBufferQueue, &playerBQState); 284f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 28501e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten SLAndroidSimpleBufferQueueState recorderBQState; 286f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten result = (*recorderBufferQueue)->GetState(recorderBufferQueue, &recorderBQState); 287f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten ASSERT_EQ(SL_RESULT_SUCCESS, result); 288e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten if (verbose) { 289e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten printf("pC%u pI%u rC%u rI%u\n", (unsigned) playerBQState.count, 290e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten (unsigned) playerBQState.playIndex, (unsigned) recorderBQState.count, 29101e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten (unsigned) recorderBQState.index); 292e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten fflush(stdout); 293e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten } 294f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten } 295f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten 296f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten //return EXIT_SUCCESS; 297f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten} 298