configbq.c revision c2303eb5497c488db786dcb2b8514db229452536
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17// Test various buffer queue configurations
18
19#include <assert.h>
20#include <math.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <unistd.h>
24
25#include "SLES/OpenSLES.h"
26
27typedef struct {
28    SLuint8 numChannels;
29    SLuint32 milliHz;
30    SLuint8 bitsPerSample;
31} PCM;
32
33PCM formats[] = {
34    {1, SL_SAMPLINGRATE_8,      8},
35    {2, SL_SAMPLINGRATE_8,      8},
36    {1, SL_SAMPLINGRATE_8,      16},
37    {2, SL_SAMPLINGRATE_8,      16},
38    {1, SL_SAMPLINGRATE_11_025, 8},
39    {2, SL_SAMPLINGRATE_11_025, 8},
40    {1, SL_SAMPLINGRATE_11_025, 16},
41    {2, SL_SAMPLINGRATE_11_025, 16},
42    {1, SL_SAMPLINGRATE_12,     8},
43    {2, SL_SAMPLINGRATE_12,     8},
44    {1, SL_SAMPLINGRATE_12,     16},
45    {2, SL_SAMPLINGRATE_12,     16},
46    {1, SL_SAMPLINGRATE_16,     8},
47    {2, SL_SAMPLINGRATE_16,     8},
48    {1, SL_SAMPLINGRATE_16,     16},
49    {2, SL_SAMPLINGRATE_16,     16},
50    {1, SL_SAMPLINGRATE_22_05,  8},
51    {2, SL_SAMPLINGRATE_22_05,  8},
52    {1, SL_SAMPLINGRATE_22_05,  16},
53    {2, SL_SAMPLINGRATE_22_05,  16},
54    {1, SL_SAMPLINGRATE_24,     8},
55    {2, SL_SAMPLINGRATE_24,     8},
56    {1, SL_SAMPLINGRATE_24,     16},
57    {2, SL_SAMPLINGRATE_24,     16},
58    {1, SL_SAMPLINGRATE_32,     8},
59    {2, SL_SAMPLINGRATE_32,     8},
60    {1, SL_SAMPLINGRATE_32,     16},
61    {2, SL_SAMPLINGRATE_32,     16},
62    {1, SL_SAMPLINGRATE_44_1,   8},
63    {2, SL_SAMPLINGRATE_44_1,   8},
64    {1, SL_SAMPLINGRATE_44_1,   16},
65    {2, SL_SAMPLINGRATE_44_1,   16},
66    {1, SL_SAMPLINGRATE_48,     8},
67    {2, SL_SAMPLINGRATE_48,     8},
68    {1, SL_SAMPLINGRATE_48,     16},
69    {2, SL_SAMPLINGRATE_48,     16},
70    {0, 0,                      0}
71};
72
73int main(int argc, char **argv)
74{
75    SLresult result;
76    SLObjectItf engineObject;
77
78    // create engine
79    result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
80    assert(SL_RESULT_SUCCESS == result);
81    SLEngineItf engineEngine;
82    result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
83    assert(SL_RESULT_SUCCESS == result);
84    result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
85    assert(SL_RESULT_SUCCESS == result);
86
87    // create output mix
88    SLObjectItf outputMixObject;
89    result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, NULL, NULL);
90    assert(SL_RESULT_SUCCESS == result);
91    result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
92    assert(SL_RESULT_SUCCESS == result);
93
94    // loop over all formats
95    PCM *format;
96    float hzLeft = 440.0;   // A440 (Concert A)
97    float hzRight = 440.0;
98    for (format = formats; format->numChannels; ++format) {
99
100        printf("Channels: %d, sample rate: %lu, bits: %u\n", format->numChannels,
101                format->milliHz / 1000, format->bitsPerSample);
102
103        // configure audio source
104        SLDataLocator_BufferQueue loc_bufq;
105        loc_bufq.locatorType = SL_DATALOCATOR_BUFFERQUEUE;
106        loc_bufq.numBuffers = 1;
107        SLDataFormat_PCM format_pcm;
108        format_pcm.formatType = SL_DATAFORMAT_PCM;
109        format_pcm.numChannels = format->numChannels;
110        format_pcm.samplesPerSec = format->milliHz;
111        format_pcm.bitsPerSample = format->bitsPerSample;
112        format_pcm.containerSize = format->bitsPerSample;
113        format_pcm.channelMask = 0;
114        format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
115        SLDataSource audioSrc;
116        audioSrc.pLocator = &loc_bufq;
117        audioSrc.pFormat = &format_pcm;
118
119        // configure audio sink
120        SLDataLocator_OutputMix loc_outmix;
121        loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
122        loc_outmix.outputMix = outputMixObject;
123        SLDataSink audioSnk;
124        audioSnk.pLocator = &loc_outmix;
125        audioSnk.pFormat = NULL;
126
127        // create audio player
128        SLuint32 numInterfaces = 1;
129        SLInterfaceID ids[1];
130        SLboolean req[1];
131        ids[0] = SL_IID_BUFFERQUEUE;
132        req[0] = SL_BOOLEAN_TRUE;
133        SLObjectItf playerObject;
134        result = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, &audioSrc,
135                &audioSnk, numInterfaces, ids, req);
136        if (SL_RESULT_SUCCESS != result) {
137            printf("failed %lu\n", result);
138            continue;
139        }
140
141        // realize the player
142        result = (*playerObject)->Realize(playerObject, SL_BOOLEAN_FALSE);
143        assert(SL_RESULT_SUCCESS == result);
144
145        // generate a sine wave buffer, ascending in half-steps for each format
146#define N (44100*4)
147        static unsigned char buffer[N];
148        unsigned i;
149        for (i = 0; i < N; ) {
150            float seconds = (((i * 8) / (format->bitsPerSample * format->numChannels)) * 1000.0) /
151                    format->milliHz;
152            short sampleLeft = sin(seconds * M_PI_2 * hzLeft) * 32767.0;
153            short sampleRight = sin(seconds * M_PI_2 * hzRight) * 32767.0;
154            if (2 == format->numChannels) {
155                if (8 == format->bitsPerSample) {
156                    buffer[i++] = (sampleLeft + 32768) >> 8;
157                    buffer[i++] = (sampleRight + 32768) >> 8;
158                } else {
159                    assert(16 == format->bitsPerSample);
160                    buffer[i++] = sampleLeft & 0xFF;
161                    buffer[i++] = sampleLeft >> 8;
162                    buffer[i++] = sampleRight & 0xFF;
163                    buffer[i++] = sampleRight >> 8;
164                }
165            } else {
166                assert(1 == format->numChannels);
167                // cast to int and divide by 2 are needed to prevent overflow
168                short sampleMono = ((int) sampleLeft + (int) sampleRight) / 2;
169                if (8 == format->bitsPerSample) {
170                    buffer[i++] = (sampleMono + 32768) >> 8;
171                } else {
172                    assert(16 == format->bitsPerSample);
173                    buffer[i++] = sampleMono & 0xFF;
174                    buffer[i++] = sampleMono >> 8;
175                }
176            }
177            if (seconds >= 1.0f)
178                break;
179        }
180
181        // get the buffer queue interface and enqueue a buffer
182        SLBufferQueueItf playerBufferQueue;
183        result = (*playerObject)->GetInterface(playerObject, SL_IID_BUFFERQUEUE,
184                &playerBufferQueue);
185        assert(SL_RESULT_SUCCESS == result);
186        result = (*playerBufferQueue)->Enqueue(playerBufferQueue, buffer, i);
187        assert(SL_RESULT_SUCCESS == result);
188
189        // get the play interface
190        SLPlayItf playerPlay;
191        result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAY, &playerPlay);
192        assert(SL_RESULT_SUCCESS == result);
193
194        // set the player's state to playing
195        result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING);
196        assert(SL_RESULT_SUCCESS == result);
197
198        // wait for the buffer to be played
199        for (;;) {
200            SLBufferQueueState state;
201            result = (*playerBufferQueue)->GetState(playerBufferQueue, &state);
202            assert(SL_RESULT_SUCCESS == result);
203            if (state.count == 0)
204                break;
205            usleep(20000);
206        }
207
208        // destroy audio player
209        (*playerObject)->Destroy(playerObject);
210
211        //usleep(1000000);
212        hzLeft *= 1.05946309; // twelfth root of 2
213        hzRight /= 1.05946309;
214    }
215
216    // destroy output mix
217    (*outputMixObject)->Destroy(outputMixObject);
218
219    // destroy engine
220    (*engineObject)->Destroy(engineObject);
221
222    return EXIT_SUCCESS;
223}
224