slesTestFeedback.cpp revision f460ec604707d0bdaf8124d84c5f8595cba9c804
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
19f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten#include "SLES/OpenSLES.h"
20f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten#include <assert.h>
21f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten#include <stdio.h>
22f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten#include <stdlib.h>
23f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten#include <unistd.h>
24f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten
25f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten#define ASSERT_EQ(x, y) assert((x) == (y))
26f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten
27f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kastentypedef struct {
28f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    short left;
29f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    short right;
30f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten} stereo;
31f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten
32f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten// These ping-pong buffers hold 1 second of audio at 44.1 kHz
33f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten#define SR 8000 //44100
34f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten#define N 3
35f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kastenstatic stereo buffers[SR*N];
36f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten
37f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten// Index of which buffer to enqueue next
38f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kastenstatic SLuint32 whichRecord;
39f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kastenstatic SLuint32 whichPlay;
40f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten
41f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn KastenSLBufferQueueItf recorderBufferQueue;
42f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn KastenSLBufferQueueItf playerBufferQueue;
43f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten
44f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten// Called after audio recorder fills a buffer with data
45f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kastenstatic void recorderCallback(SLBufferQueueItf caller, void *context)
46f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten{
47f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    SLresult result;
48f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    putchar('*');
49f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    fflush(stdout);
50f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten
51f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    // Enqueue the next empty buffer for the recorder to fill
52f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    assert(whichRecord < N);
53f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    void *buffer = &buffers[SR*whichRecord];
54f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    SLuint32 size = SR*sizeof(stereo);
55f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    result = (*recorderBufferQueue)->Enqueue(recorderBufferQueue, buffer, size);
56f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    ASSERT_EQ(SL_RESULT_SUCCESS, result);
57f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    if (++whichRecord >= N)
58f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten        whichRecord = 0;
59f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten
60f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    // Enqueue the just-filled buffer for the player to empty
61f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    assert(whichPlay < N);
62f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    buffer = &buffers[SR*whichPlay];
63f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    result = (*playerBufferQueue)->Enqueue(playerBufferQueue, buffer, size);
64f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    ASSERT_EQ(SL_RESULT_SUCCESS, result);
65f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    if (++whichPlay >= N)
66f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten        whichPlay = 0;
67f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten
68f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten}
69f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten
70f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kastenint main(int argc, char **argv)
71f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten{
72f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    SLresult result;
73f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten
74f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    // create engine
75f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    SLObjectItf engineObject;
76f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
77f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    ASSERT_EQ(SL_RESULT_SUCCESS, result);
78f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
79f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    ASSERT_EQ(SL_RESULT_SUCCESS, result);
80f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    SLEngineItf engineEngine;
81f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
82f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    ASSERT_EQ(SL_RESULT_SUCCESS, result);
83f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten
84f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    // create output mix
85f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    SLObjectItf outputmixObject;
86f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    result = (*engineEngine)->CreateOutputMix(engineEngine, &outputmixObject, 0, NULL, NULL);
87f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    ASSERT_EQ(SL_RESULT_SUCCESS, result);
88f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    result = (*outputmixObject)->Realize(outputmixObject, SL_BOOLEAN_FALSE);
89f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    ASSERT_EQ(SL_RESULT_SUCCESS, result);
90f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten
91f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    // create an audio player with buffer queue source and output mix sink
92f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    SLDataSource audiosrc;
93f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    SLDataSink audiosnk;
94f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    SLDataFormat_PCM pcm;
95f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    SLDataLocator_OutputMix locator_outputmix;
96f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    SLDataLocator_BufferQueue locator_bufferqueue;
97f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    locator_bufferqueue.locatorType = SL_DATALOCATOR_BUFFERQUEUE;
98f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    locator_bufferqueue.numBuffers = 2;
99f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
100f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    locator_outputmix.outputMix = outputmixObject;
101f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    pcm.formatType = SL_DATAFORMAT_PCM;
102f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    pcm.numChannels = 1; //2;
103f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    pcm.samplesPerSec = SL_SAMPLINGRATE_8; //44_1;
104f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
105f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    pcm.containerSize = 16;
106f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    pcm.channelMask = SL_SPEAKER_FRONT_CENTER; //SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
107f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
108f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    audiosrc.pLocator = &locator_bufferqueue;
109f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    audiosrc.pFormat = &pcm;
110f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    audiosnk.pLocator = &locator_outputmix;
111f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    audiosnk.pFormat = NULL;
112f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    SLObjectItf playerObject;
113f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    SLInterfaceID ids[1] = {SL_IID_BUFFERQUEUE};
114f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    SLboolean flags[1] = {SL_BOOLEAN_TRUE};
115f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    result = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, &audiosrc, &audiosnk, 1, ids, flags);
116f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    ASSERT_EQ(SL_RESULT_SUCCESS, result);
117f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    result = (*playerObject)->Realize(playerObject, SL_BOOLEAN_FALSE);
118f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    ASSERT_EQ(SL_RESULT_SUCCESS, result);
119f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    SLPlayItf playerPlay;
120f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAY, &playerPlay);
121f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    ASSERT_EQ(SL_RESULT_SUCCESS, result);
122f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    result = (*playerObject)->GetInterface(playerObject, SL_IID_BUFFERQUEUE, &playerBufferQueue);
123f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    ASSERT_EQ(SL_RESULT_SUCCESS, result);
124f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING);
125f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    ASSERT_EQ(SL_RESULT_SUCCESS, result);
126f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten
127f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    // Create an audio recorder with microphone device source and buffer queue sink.
128f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    // The buffer queue as sink is an Android-specific extension.
129f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten
130f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    SLDataLocator_IODevice locator_iodevice;
131f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    locator_iodevice.locatorType = SL_DATALOCATOR_IODEVICE;
132f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    locator_iodevice.deviceType = SL_IODEVICE_AUDIOINPUT;
133f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    locator_iodevice.deviceID = SL_DEFAULTDEVICEID_AUDIOINPUT;
134f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    locator_iodevice.device = NULL;
135f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    audiosrc.pLocator = &locator_iodevice;
136f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    audiosrc.pFormat = &pcm;
137f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    audiosnk.pLocator = &locator_bufferqueue;
138f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    audiosnk.pFormat = &pcm;
139f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    SLObjectItf recorderObject;
140f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    result = (*engineEngine)->CreateAudioRecorder(engineEngine, &recorderObject, &audiosrc, &audiosnk, 1, ids, flags);
141f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    ASSERT_EQ(SL_RESULT_SUCCESS, result);
142f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    result = (*recorderObject)->Realize(recorderObject, SL_BOOLEAN_FALSE);
143f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    ASSERT_EQ(SL_RESULT_SUCCESS, result);
144f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    SLRecordItf recorderRecord;
145f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    result = (*recorderObject)->GetInterface(recorderObject, SL_IID_RECORD, &recorderRecord);
146f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    ASSERT_EQ(SL_RESULT_SUCCESS, result);
147f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    result = (*recorderObject)->GetInterface(recorderObject, SL_IID_BUFFERQUEUE, &recorderBufferQueue);
148f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    ASSERT_EQ(SL_RESULT_SUCCESS, result);
149f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    result = (*recorderBufferQueue)->RegisterCallback(recorderBufferQueue, recorderCallback, NULL);
150f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    ASSERT_EQ(SL_RESULT_SUCCESS, result);
151f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten
152f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    // Enqueue some empty buffers for the recorder
153f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    for (whichRecord = 0; whichRecord < N-1; ++whichRecord) {
154f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten        result = (*recorderBufferQueue)->Enqueue(recorderBufferQueue, &buffers[SR*whichRecord], SR*sizeof(stereo));
155f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten        ASSERT_EQ(SL_RESULT_SUCCESS, result);
156f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    }
157f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten
158f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    // Kick off the recorder
159f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    whichPlay = 0;
160f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_RECORDING);
161f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    ASSERT_EQ(SL_RESULT_SUCCESS, result);
162f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten
163f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    // Wait patiently
164f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    for (;;) {
165f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten        usleep(1000000);
166f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten        putchar('.');
167f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten        SLBufferQueueState playerBQState;
168f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten        result = (*playerBufferQueue)->GetState(playerBufferQueue, &playerBQState);
169f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten        ASSERT_EQ(SL_RESULT_SUCCESS, result);
170f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten        SLBufferQueueState recorderBQState;
171f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten        result = (*recorderBufferQueue)->GetState(recorderBufferQueue, &recorderBQState);
172f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten        ASSERT_EQ(SL_RESULT_SUCCESS, result);
173f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten        printf("pC%u pI%u rC%u rI%u\n", (unsigned) playerBQState.count, (unsigned) playerBQState.playIndex, (unsigned) recorderBQState.count, (unsigned) recorderBQState.playIndex);
174f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten        fflush(stdout);
175f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    }
176f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten
177f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten    //return EXIT_SUCCESS;
178f460ec604707d0bdaf8124d84c5f8595cba9c804Glenn Kasten}
179