playbq.c revision 0a058cc3d720cdf3f0f8222472a862258482f34f
10a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten/*
20a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten * Copyright (C) 2010 The Android Open Source Project
30a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten *
40a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten * Licensed under the Apache License, Version 2.0 (the "License");
50a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten * you may not use this file except in compliance with the License.
60a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten * You may obtain a copy of the License at
70a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten *
80a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten *      http://www.apache.org/licenses/LICENSE-2.0
90a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten *
100a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten * Unless required by applicable law or agreed to in writing, software
110a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten * distributed under the License is distributed on an "AS IS" BASIS,
120a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten * See the License for the specific language governing permissions and
140a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten * limitations under the License.
150a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten */
160a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
170a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten// Play an audio file using buffer queue
180a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
190a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten#include <assert.h>
200a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten#include <math.h>
210a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten#include <stdio.h>
220a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten#include <stdlib.h>
230a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten#include <string.h>
240a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten#include <unistd.h>
250a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
260a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten#include "SLES/OpenSLES.h"
270a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten#ifdef ANDROID
280a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten#include "sndfile.h"
290a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten#else
300a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten#include <sndfile.h>
310a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten#endif
320a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
330a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kastenunsigned numBuffers = 2;
340a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kastenint framesPerBuffer = 512;
350a058cc3d720cdf3f0f8222472a862258482f34fGlenn KastenSNDFILE *sndfile;
360a058cc3d720cdf3f0f8222472a862258482f34fGlenn KastenSF_INFO sfinfo;
370a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kastenunsigned which; // which buffer to use next
380a058cc3d720cdf3f0f8222472a862258482f34fGlenn KastenSLboolean eof;  // whether we have hit EOF on input yet
390a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kastenshort *buffers;
400a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
410a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten// This callback is called each time a buffer finishes playing
420a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
430a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kastenstatic void callback(SLBufferQueueItf bufq, void *param)
440a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten{
450a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    if (!eof) {
460a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        short *buffer = &buffers[framesPerBuffer * sfinfo.channels * which];
470a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        sf_count_t count;
480a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        count = sf_readf_short(sndfile, buffer, (sf_count_t) framesPerBuffer);
490a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        if (0 >= count) {
500a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            eof = SL_BOOLEAN_TRUE;
510a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        } else {
520a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            SLresult result = (*bufq)->Enqueue(bufq, buffer, count * sfinfo.channels *
530a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten                    sizeof(short));
540a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            assert(SL_RESULT_SUCCESS == result);
550a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            if (++which >= numBuffers)
560a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten                which = 0;
570a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        }
580a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    }
590a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten}
600a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
610a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kastenint main(int argc, char **argv)
620a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten{
630a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLboolean enableReverb = SL_BOOLEAN_FALSE;
640a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
650a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    // process command-line options
660a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    int i;
670a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    for (i = 1; i < argc; ++i) {
680a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        char *arg = argv[i];
690a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        if (arg[0] != '-')
700a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            break;
710a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        if (!strncmp(arg, "-f", 2)) {
720a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            framesPerBuffer = atoi(&arg[2]);
730a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        } else if (!strncmp(arg, "-n", 2)) {
740a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            numBuffers = atoi(&arg[2]);
750a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        } else if (!strcmp(arg, "-r")) {
760a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            enableReverb = SL_BOOLEAN_TRUE;
770a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        } else {
780a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            fprintf(stderr, "option %s ignored\n", arg);
790a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        }
800a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    }
810a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
820a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    if (argc - i != 1) {
830a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        fprintf(stderr, "usage: [-r] %s filename\n", argv[0]);
840a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        return EXIT_FAILURE;
850a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    }
860a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
870a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    const char *filename = argv[i];
880a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    //memset(&sfinfo, 0, sizeof(SF_INFO));
890a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    sfinfo.format = 0;
900a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    sndfile = sf_open(filename, SFM_READ, &sfinfo);
910a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    if (NULL == sndfile) {
920a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        perror(filename);
930a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        return EXIT_FAILURE;
940a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    }
950a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
960a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    // verify the file format
970a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    switch (sfinfo.channels) {
980a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    case 1:
990a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    case 2:
1000a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        break;
1010a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    default:
1020a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        fprintf(stderr, "unsupported channel count %d\n", sfinfo.channels);
1030a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        break;
1040a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    }
1050a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    switch (sfinfo.samplerate) {
1060a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    case  8000:
1070a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    case 11025:
1080a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    case 12000:
1090a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    case 16000:
1100a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    case 22050:
1110a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    case 24000:
1120a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    case 32000:
1130a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    case 44100:
1140a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    case 48000:
1150a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        break;
1160a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    default:
1170a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        fprintf(stderr, "unsupported sample rate %d\n", sfinfo.samplerate);
1180a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        break;
1190a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    }
1200a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    switch (sfinfo.format & SF_FORMAT_TYPEMASK) {
1210a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    case SF_FORMAT_WAV:
1220a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        break;
1230a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    default:
1240a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        fprintf(stderr, "unsupported format type 0x%x\n", sfinfo.format & SF_FORMAT_TYPEMASK);
1250a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        break;
1260a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    }
1270a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    switch (sfinfo.format & SF_FORMAT_SUBMASK) {
1280a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    case SF_FORMAT_PCM_16:
1290a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    case SF_FORMAT_PCM_U8:
1300a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    case SF_FORMAT_ULAW:
1310a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    case SF_FORMAT_ALAW:
1320a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    case SF_FORMAT_IMA_ADPCM:
1330a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        break;
1340a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    default:
1350a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        fprintf(stderr, "unsupported sub-format 0x%x\n", sfinfo.format & SF_FORMAT_SUBMASK);
1360a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        break;
1370a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    }
1380a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
1390a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    buffers = (short *) malloc(framesPerBuffer * sfinfo.channels * sizeof(short) * numBuffers);
1400a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
1410a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    // create engine
1420a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLresult result;
1430a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLObjectItf engineObject;
1440a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
1450a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
1460a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLEngineItf engineEngine;
1470a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
1480a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
1490a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
1500a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
1510a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
1520a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    // create output mix
1530a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLObjectItf outputMixObject;
1540a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLInterfaceID ids[1] = {SL_IID_ENVIRONMENTALREVERB};
1550a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLboolean req[1] = {SL_BOOLEAN_TRUE};
1560a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, enableReverb ? 1 : 0,
1570a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            ids, req);
1580a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
1590a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
1600a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
1610a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
1620a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    // configure environmental reverb on output mix
1630a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLEnvironmentalReverbItf mixEnvironmentalReverb = NULL;
1640a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    if (enableReverb) {
1650a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        result = (*outputMixObject)->GetInterface(outputMixObject, SL_IID_ENVIRONMENTALREVERB,
1660a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten                &mixEnvironmentalReverb);
1670a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        assert(SL_RESULT_SUCCESS == result);
1680a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        SLEnvironmentalReverbSettings settings = SL_I3DL2_ENVIRONMENT_PRESET_STONECORRIDOR;
1690a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        result = (*mixEnvironmentalReverb)->SetEnvironmentalReverbProperties(mixEnvironmentalReverb,
1700a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten                &settings);
1710a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        assert(SL_RESULT_SUCCESS == result);
1720a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    }
1730a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
1740a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    // configure audio source
1750a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLDataLocator_BufferQueue loc_bufq;
1760a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    loc_bufq.locatorType = SL_DATALOCATOR_BUFFERQUEUE;
1770a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    loc_bufq.numBuffers = numBuffers;
1780a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLDataFormat_PCM format_pcm;
1790a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    format_pcm.formatType = SL_DATAFORMAT_PCM;
1800a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    format_pcm.numChannels = sfinfo.channels;
1810a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    format_pcm.samplesPerSec = sfinfo.samplerate * 1000;
1820a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    format_pcm.bitsPerSample = 16;
1830a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    format_pcm.containerSize = format_pcm.bitsPerSample;
1840a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    format_pcm.channelMask = 1 == format_pcm.numChannels ? SL_SPEAKER_FRONT_CENTER :
1850a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
1860a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
1870a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLDataSource audioSrc;
1880a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    audioSrc.pLocator = &loc_bufq;
1890a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    audioSrc.pFormat = &format_pcm;
1900a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
1910a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    // configure audio sink
1920a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLDataLocator_OutputMix loc_outmix;
1930a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
1940a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    loc_outmix.outputMix = outputMixObject;
1950a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLDataSink audioSnk;
1960a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    audioSnk.pLocator = &loc_outmix;
1970a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    audioSnk.pFormat = NULL;
1980a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
1990a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    // create audio player
2000a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLInterfaceID ids2[2] = {SL_IID_BUFFERQUEUE, SL_IID_EFFECTSEND};
2010a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLboolean req2[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
2020a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLObjectItf playerObject;
2030a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    result = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, &audioSrc,
2040a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            &audioSnk, enableReverb ? 2 : 1, ids2, req2);
2050a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
2060a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
2070a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    // realize the player
2080a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    result = (*playerObject)->Realize(playerObject, SL_BOOLEAN_FALSE);
2090a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
2100a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
2110a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    // get the effect send interface and enable effect send reverb for this player
2120a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    if (enableReverb) {
2130a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        SLEffectSendItf playerEffectSend;
2140a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        result = (*playerObject)->GetInterface(playerObject, SL_IID_EFFECTSEND, &playerEffectSend);
2150a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        assert(SL_RESULT_SUCCESS == result);
2160a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        result = (*playerEffectSend)->EnableEffectSend(playerEffectSend, mixEnvironmentalReverb,
2170a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten                SL_BOOLEAN_TRUE, (SLmillibel) 0);
2180a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        assert(SL_RESULT_SUCCESS == result);
2190a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    }
2200a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
2210a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    // get the play interface
2220a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLPlayItf playerPlay;
2230a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAY, &playerPlay);
2240a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
2250a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
2260a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    // get the buffer queue interface
2270a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLBufferQueueItf playerBufferQueue;
2280a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    result = (*playerObject)->GetInterface(playerObject, SL_IID_BUFFERQUEUE,
2290a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            &playerBufferQueue);
2300a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
2310a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
2320a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    // loop until EOF or no more buffers
2330a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    for (which = 0; which < numBuffers; ++which) {
2340a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        short *buffer = &buffers[framesPerBuffer * sfinfo.channels * which];
2350a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        sf_count_t frames = framesPerBuffer;
2360a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        sf_count_t count;
2370a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        count = sf_readf_short(sndfile, buffer, frames);
2380a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        if (0 >= count) {
2390a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            eof = SL_BOOLEAN_TRUE;
2400a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            break;
2410a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        }
2420a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
2430a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        // enqueue a buffer
2440a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        result = (*playerBufferQueue)->Enqueue(playerBufferQueue, buffer, count * sfinfo.channels *
2450a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten                sizeof(short));
2460a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        assert(SL_RESULT_SUCCESS == result);
2470a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    }
2480a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    if (which >= numBuffers)
2490a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        which = 0;
2500a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
2510a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    // register a callback on the buffer queue
2520a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    result = (*playerBufferQueue)->RegisterCallback(playerBufferQueue, callback, NULL);
2530a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
2540a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
2550a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    // set the player's state to playing
2560a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING);
2570a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    assert(SL_RESULT_SUCCESS == result);
2580a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
2590a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    // wait until the buffer queue is empty
2600a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    SLBufferQueueState bufqstate;
2610a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    for (;;) {
2620a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        result = (*playerBufferQueue)->GetState(playerBufferQueue, &bufqstate);
2630a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        assert(SL_RESULT_SUCCESS == result);
2640a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        if (0 >= bufqstate.count) {
2650a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten            break;
2660a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        }
2670a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten        sleep(1);
2680a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    }
2690a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
2700a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    // destroy audio player
2710a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    (*playerObject)->Destroy(playerObject);
2720a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
2730a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    // destroy output mix
2740a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    (*outputMixObject)->Destroy(outputMixObject);
2750a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
2760a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    // destroy engine
2770a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    (*engineObject)->Destroy(engineObject);
2780a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten
2790a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten    return EXIT_SUCCESS;
2800a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten}
281