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