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