configbq.c revision c6853892c94800e72c0bd676d5d2136d48cea76e
1b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien/*
2b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien * Copyright (C) 2010 The Android Open Source Project
3b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien *
4b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien * Licensed under the Apache License, Version 2.0 (the "License");
5b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien * you may not use this file except in compliance with the License.
6b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien * You may obtain a copy of the License at
7b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien *
8b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien *      http://www.apache.org/licenses/LICENSE-2.0
9b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien *
10b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien * Unless required by applicable law or agreed to in writing, software
11b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien * distributed under the License is distributed on an "AS IS" BASIS,
12b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien * See the License for the specific language governing permissions and
14b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien * limitations under the License.
15b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien */
16b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien
17b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien// Test various buffer queue configurations
18b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien
19b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien#include <assert.h>
20b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien#include <math.h>
21b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien#include <stdio.h>
22b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien#include <stdlib.h>
23b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien#include <unistd.h>
24b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien
25b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien#include <SLES/OpenSLES.h>
26b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien
27b80c1f19c58b927820a8a24bf2218e5645724608Raph Levientypedef struct {
28b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien    SLuint8 numChannels;
29b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien    SLuint32 milliHz;
30b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien    SLuint8 bitsPerSample;
31b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien} PCM;
32b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien
33b80c1f19c58b927820a8a24bf2218e5645724608Raph LevienPCM formats[] = {
34b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien    {1, SL_SAMPLINGRATE_8,      8},
35b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien    {2, SL_SAMPLINGRATE_8,      8},
36b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien    {1, SL_SAMPLINGRATE_8,      16},
37b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien    {2, SL_SAMPLINGRATE_8,      16},
38b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien    {1, SL_SAMPLINGRATE_11_025, 8},
39b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien    {2, SL_SAMPLINGRATE_11_025, 8},
406c60831cfce24b0749f50f37231e0a56d8fd4b85Seigo Nonaka    {1, SL_SAMPLINGRATE_11_025, 16},
416c60831cfce24b0749f50f37231e0a56d8fd4b85Seigo Nonaka    {2, SL_SAMPLINGRATE_11_025, 16},
426c60831cfce24b0749f50f37231e0a56d8fd4b85Seigo Nonaka    {1, SL_SAMPLINGRATE_12,     8},
436c60831cfce24b0749f50f37231e0a56d8fd4b85Seigo Nonaka    {2, SL_SAMPLINGRATE_12,     8},
446c60831cfce24b0749f50f37231e0a56d8fd4b85Seigo Nonaka    {1, SL_SAMPLINGRATE_12,     16},
456c60831cfce24b0749f50f37231e0a56d8fd4b85Seigo Nonaka    {2, SL_SAMPLINGRATE_12,     16},
466c60831cfce24b0749f50f37231e0a56d8fd4b85Seigo Nonaka    {1, SL_SAMPLINGRATE_16,     8},
476c60831cfce24b0749f50f37231e0a56d8fd4b85Seigo Nonaka    {2, SL_SAMPLINGRATE_16,     8},
486c60831cfce24b0749f50f37231e0a56d8fd4b85Seigo Nonaka    {1, SL_SAMPLINGRATE_16,     16},
496c60831cfce24b0749f50f37231e0a56d8fd4b85Seigo Nonaka    {2, SL_SAMPLINGRATE_16,     16},
506c60831cfce24b0749f50f37231e0a56d8fd4b85Seigo Nonaka    {1, SL_SAMPLINGRATE_22_05,  8},
516c60831cfce24b0749f50f37231e0a56d8fd4b85Seigo Nonaka    {2, SL_SAMPLINGRATE_22_05,  8},
526c60831cfce24b0749f50f37231e0a56d8fd4b85Seigo Nonaka    {1, SL_SAMPLINGRATE_22_05,  16},
536c60831cfce24b0749f50f37231e0a56d8fd4b85Seigo Nonaka    {2, SL_SAMPLINGRATE_22_05,  16},
546c60831cfce24b0749f50f37231e0a56d8fd4b85Seigo Nonaka    {1, SL_SAMPLINGRATE_24,     8},
556c60831cfce24b0749f50f37231e0a56d8fd4b85Seigo Nonaka    {2, SL_SAMPLINGRATE_24,     8},
566c60831cfce24b0749f50f37231e0a56d8fd4b85Seigo Nonaka    {1, SL_SAMPLINGRATE_24,     16},
57b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien    {2, SL_SAMPLINGRATE_24,     16},
58b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien    {1, SL_SAMPLINGRATE_32,     8},
59b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien    {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: %u, 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 %u\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