playbq.c revision ad6c970f500cf99dd1eb23b9f5b2360948db90e7
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> 21ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten#include <pthread.h> 220a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten#include <stdio.h> 230a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten#include <stdlib.h> 240a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten#include <string.h> 25701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten#include <time.h> 260a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten#include <unistd.h> 270a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten 28c6853892c94800e72c0bd676d5d2136d48cea76eGlenn Kasten#include <SLES/OpenSLES.h> 290a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten#ifdef ANDROID 3056847632bc2fd39a8fff68fa1e883f06310c876aGlenn Kasten#include <audio_utils/sndfile.h> 310a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten#else 320a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten#include <sndfile.h> 330a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten#endif 340a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten 35ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten#include <media/nbaio/MonoPipe.h> 36ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten#include <media/nbaio/MonoPipeReader.h> 37ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten 38701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten#define max(a, b) ((a) > (b) ? (a) : (b)) 39701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten#define min(a, b) ((a) < (b) ? (a) : (b)) 40701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten 410a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kastenunsigned numBuffers = 2; 420a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kastenint framesPerBuffer = 512; 430a058cc3d720cdf3f0f8222472a862258482f34fGlenn KastenSNDFILE *sndfile; 440a058cc3d720cdf3f0f8222472a862258482f34fGlenn KastenSF_INFO sfinfo; 450a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kastenunsigned which; // which buffer to use next 460a058cc3d720cdf3f0f8222472a862258482f34fGlenn KastenSLboolean eof; // whether we have hit EOF on input yet 470a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kastenshort *buffers; 48ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn KastenSLuint32 byteOrder; // desired to use for PCM buffers 49ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn KastenSLuint32 nativeByteOrder; // of platform 50ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn KastenSLuint32 bitsPerSample = 16; 51ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten 52ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten// swap adjacent bytes; this would normally be in <unistd.h> but is missing here 53ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kastenstatic void swab(const void *from, void *to, ssize_t n) 54ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten{ 55ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten // from and to as char pointers 56ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten const char *from_ch = (const char *) from; 57ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten char *to_ch = (char *) to; 58ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten // note that we don't swap the last odd byte 59ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten while (n >= 2) { 60ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten to_ch[0] = from_ch[1]; 61ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten to_ch[1] = from_ch[0]; 62ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten to_ch += 2; 63ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten from_ch += 2; 64ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten n -= 2; 65ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten } 66ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten} 67ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten 68ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten// squeeze 16-bit signed PCM samples down to 8-bit unsigned PCM samples by truncation; no dithering 69ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kastenstatic void squeeze(const short *from, unsigned char *to, ssize_t n) 70ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten{ 71ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten // note that we don't squeeze the last odd byte 72ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten while (n >= 2) { 73ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten *to++ = (*from++ + 32768) >> 8; 74ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten n -= 2; 75ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten } 76ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten} 770a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten 78ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kastenstatic android::MonoPipeReader *pipeReader; 79ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kastenstatic android::MonoPipe *pipeWriter; 80ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kastenstatic unsigned underruns = 0; 81ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten 820a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten// This callback is called each time a buffer finishes playing 830a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten 840a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kastenstatic void callback(SLBufferQueueItf bufq, void *param) 850a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten{ 869a6c9db763121c3b11765c6c8cf935983c0385bfGlenn Kasten assert(NULL == param); 870a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten if (!eof) { 880a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten short *buffer = &buffers[framesPerBuffer * sfinfo.channels * which]; 89ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten ssize_t count = pipeReader->read(buffer, framesPerBuffer, (int64_t) -1); 90ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten // on underrun from pipe, substitute silence 910a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten if (0 >= count) { 92ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten memset(buffer, 0, framesPerBuffer * sfinfo.channels * sizeof(short)); 93ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten count = framesPerBuffer; 94ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten ++underruns; 95ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten } 96ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten if (count > 0) { 97ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten SLuint32 nbytes = count * sfinfo.channels * sizeof(short); 98ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten if (byteOrder != nativeByteOrder) { 99ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten swab(buffer, buffer, nbytes); 100ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten } 101ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten if (bitsPerSample == 8) { 102ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten squeeze(buffer, (unsigned char *) buffer, nbytes); 103ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten nbytes /= 2; 104ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten } 105ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten SLresult result = (*bufq)->Enqueue(bufq, buffer, nbytes); 1060a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten assert(SL_RESULT_SUCCESS == result); 1070a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten if (++which >= numBuffers) 1080a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten which = 0; 1090a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten } 1100a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten } 1110a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten} 1120a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten 113ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten// This thread reads from a (slow) filesystem with unpredictable latency and writes to pipe 114ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten 115ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kastenstatic void *file_reader_loop(void *arg) 116ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten{ 117ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten#define READ_FRAMES 256 118ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten short *temp = (short *) malloc(READ_FRAMES * sfinfo.channels * sizeof(short)); 119ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten sf_count_t total = 0; 120ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten for (;;) { 121ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten sf_count_t count = sf_readf_short(sndfile, temp, (sf_count_t) READ_FRAMES); 122ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten if (0 >= count) { 123ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten eof = SL_BOOLEAN_TRUE; 124ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten break; 125ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten } 126ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten const short *ptr = temp; 127ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten while (count > 0) { 128ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten ssize_t actual = pipeWriter->write(ptr, (size_t) count); 129ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten if (actual < 0) { 130ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten break; 131ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten } 132ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten if ((sf_count_t) actual < count) { 133ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten usleep(10000); 134ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten } 135ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten ptr += actual * sfinfo.channels; 136ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten count -= actual; 137ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten total += actual; 138ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten } 139ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten // simulate occasional filesystem latency 140ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten if ((total & 0xFF00) == 0xFF00) { 141ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten usleep(100000); 142ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten } 143ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten } 144ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten free(temp); 145ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten return NULL; 146ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten} 147ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten 148ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten// Main program 149ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten 1500a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kastenint main(int argc, char **argv) 1510a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten{ 152ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten // Determine the native byte order (SL_BYTEORDER_NATIVE not available until 1.1) 153ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten union { 154ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten short s; 155ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten char c[2]; 156ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten } u; 157ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten u.s = 0x1234; 158ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten if (u.c[0] == 0x34) { 159ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten nativeByteOrder = SL_BYTEORDER_LITTLEENDIAN; 160ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten } else if (u.c[0] == 0x12) { 161ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten nativeByteOrder = SL_BYTEORDER_BIGENDIAN; 162ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten } else { 163ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten fprintf(stderr, "Unable to determine native byte order\n"); 164ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten return EXIT_FAILURE; 165ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten } 166ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten byteOrder = nativeByteOrder; 167ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten 1680a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten SLboolean enableReverb = SL_BOOLEAN_FALSE; 169f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten SLboolean enablePlaybackRate = SL_BOOLEAN_FALSE; 170701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten SLpermille initialRate = 0; 171701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten SLpermille finalRate = 0; 172701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten SLpermille deltaRate = 1; 173701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten SLmillisecond deltaRateMs = 0; 1740a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten 1750a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten // process command-line options 1760a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten int i; 1770a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten for (i = 1; i < argc; ++i) { 1780a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten char *arg = argv[i]; 179701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten if (arg[0] != '-') { 1800a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten break; 181701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten } 182ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten if (!strcmp(arg, "-b")) { 183ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten byteOrder = SL_BYTEORDER_BIGENDIAN; 184ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten } else if (!strcmp(arg, "-l")) { 185ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten byteOrder = SL_BYTEORDER_LITTLEENDIAN; 186ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten } else if (!strcmp(arg, "-8")) { 187ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten bitsPerSample = 8; 188ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten } else if (!strncmp(arg, "-f", 2)) { 1890a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten framesPerBuffer = atoi(&arg[2]); 1900a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten } else if (!strncmp(arg, "-n", 2)) { 1910a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten numBuffers = atoi(&arg[2]); 1929a6c9db763121c3b11765c6c8cf935983c0385bfGlenn Kasten } else if (!strncmp(arg, "-p", 2)) { 193701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten initialRate = atoi(&arg[2]); 194f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten enablePlaybackRate = SL_BOOLEAN_TRUE; 195701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten } else if (!strncmp(arg, "-P", 2)) { 196701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten finalRate = atoi(&arg[2]); 197f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten enablePlaybackRate = SL_BOOLEAN_TRUE; 198701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten } else if (!strncmp(arg, "-q", 2)) { 199701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten deltaRate = atoi(&arg[2]); 200701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten // deltaRate is a magnitude, so take absolute value 201701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten if (deltaRate < 0) { 202701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten deltaRate = -deltaRate; 203701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten } 204f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten enablePlaybackRate = SL_BOOLEAN_TRUE; 205701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten } else if (!strncmp(arg, "-Q", 2)) { 206701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten deltaRateMs = atoi(&arg[2]); 207f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten enablePlaybackRate = SL_BOOLEAN_TRUE; 2080a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten } else if (!strcmp(arg, "-r")) { 2090a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten enableReverb = SL_BOOLEAN_TRUE; 2100a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten } else { 2110a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten fprintf(stderr, "option %s ignored\n", arg); 2120a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten } 2130a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten } 2140a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten 2150a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten if (argc - i != 1) { 216ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten fprintf(stderr, "usage: [-b/l] [-8] [-f#] [-n#] [-p#] [-r] %s filename\n", argv[0]); 217701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten fprintf(stderr, " -b force big-endian byte order (default is native byte order)\n"); 218701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten fprintf(stderr, " -l force little-endian byte order (default is native byte order)\n"); 219701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten fprintf(stderr, " -8 output 8-bits per sample (default is 16-bits per sample)\n"); 220701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten fprintf(stderr, " -f# frames per buffer (default 512)\n"); 221701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten fprintf(stderr, " -n# number of buffers (default 2)\n"); 222701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten fprintf(stderr, " -p# initial playback rate in per mille (default 1000)\n"); 223701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten fprintf(stderr, " -P# final playback rate in per mille (default same as -p#)\n"); 224701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten fprintf(stderr, " -q# magnitude of playback rate changes in per mille (default 1)\n"); 225701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten fprintf(stderr, " -Q# period between playback rate changes in ms (default 50)\n"); 226701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten fprintf(stderr, " -r enable reverb (default disabled)\n"); 2270a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten return EXIT_FAILURE; 2280a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten } 2290a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten 2300a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten const char *filename = argv[i]; 2310a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten //memset(&sfinfo, 0, sizeof(SF_INFO)); 2320a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten sfinfo.format = 0; 2330a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten sndfile = sf_open(filename, SFM_READ, &sfinfo); 2340a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten if (NULL == sndfile) { 2350a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten perror(filename); 2360a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten return EXIT_FAILURE; 2370a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten } 2380a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten 239ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten // The sample rate is a lie, but it doesn't actually matter 240ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten const android::NBAIO_Format nbaio_format = android::Format_from_SR_C(44100, sfinfo.channels); 241ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten 2420a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten // verify the file format 2430a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten switch (sfinfo.channels) { 2440a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten case 1: 2450a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten case 2: 2460a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten break; 2470a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten default: 2480a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten fprintf(stderr, "unsupported channel count %d\n", sfinfo.channels); 249701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten goto close_sndfile; 2500a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten } 251701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten 2520a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten switch (sfinfo.samplerate) { 2530a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten case 8000: 2540a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten case 11025: 2550a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten case 12000: 2560a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten case 16000: 2570a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten case 22050: 2580a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten case 24000: 2590a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten case 32000: 2600a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten case 44100: 2610a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten case 48000: 2620a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten break; 2630a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten default: 2640a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten fprintf(stderr, "unsupported sample rate %d\n", sfinfo.samplerate); 265701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten goto close_sndfile; 2660a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten } 267701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten 2680a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten switch (sfinfo.format & SF_FORMAT_TYPEMASK) { 2690a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten case SF_FORMAT_WAV: 2700a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten break; 2710a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten default: 2720a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten fprintf(stderr, "unsupported format type 0x%x\n", sfinfo.format & SF_FORMAT_TYPEMASK); 273701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten goto close_sndfile; 2740a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten } 275701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten 2760a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten switch (sfinfo.format & SF_FORMAT_SUBMASK) { 2770a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten case SF_FORMAT_PCM_16: 2780a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten case SF_FORMAT_PCM_U8: 2790a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten break; 2800a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten default: 2810a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten fprintf(stderr, "unsupported sub-format 0x%x\n", sfinfo.format & SF_FORMAT_SUBMASK); 282701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten goto close_sndfile; 2830a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten } 2840a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten 285ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten { 286ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten 2870a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten buffers = (short *) malloc(framesPerBuffer * sfinfo.channels * sizeof(short) * numBuffers); 2880a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten 2890a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten // create engine 2900a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten SLresult result; 2910a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten SLObjectItf engineObject; 2920a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); 2930a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten assert(SL_RESULT_SUCCESS == result); 2940a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten SLEngineItf engineEngine; 2950a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); 2960a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten assert(SL_RESULT_SUCCESS == result); 2970a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine); 2980a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten assert(SL_RESULT_SUCCESS == result); 2990a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten 3000a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten // create output mix 3010a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten SLObjectItf outputMixObject; 3020a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten SLInterfaceID ids[1] = {SL_IID_ENVIRONMENTALREVERB}; 3030a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten SLboolean req[1] = {SL_BOOLEAN_TRUE}; 3040a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, enableReverb ? 1 : 0, 3050a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten ids, req); 3060a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten assert(SL_RESULT_SUCCESS == result); 3070a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE); 3080a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten assert(SL_RESULT_SUCCESS == result); 3090a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten 3100a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten // configure environmental reverb on output mix 3110a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten SLEnvironmentalReverbItf mixEnvironmentalReverb = NULL; 3120a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten if (enableReverb) { 3130a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten result = (*outputMixObject)->GetInterface(outputMixObject, SL_IID_ENVIRONMENTALREVERB, 3140a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten &mixEnvironmentalReverb); 3150a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten assert(SL_RESULT_SUCCESS == result); 3160a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten SLEnvironmentalReverbSettings settings = SL_I3DL2_ENVIRONMENT_PRESET_STONECORRIDOR; 3170a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten result = (*mixEnvironmentalReverb)->SetEnvironmentalReverbProperties(mixEnvironmentalReverb, 3180a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten &settings); 3190a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten assert(SL_RESULT_SUCCESS == result); 3200a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten } 3210a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten 3220a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten // configure audio source 3230a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten SLDataLocator_BufferQueue loc_bufq; 3240a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten loc_bufq.locatorType = SL_DATALOCATOR_BUFFERQUEUE; 3250a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten loc_bufq.numBuffers = numBuffers; 3260a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten SLDataFormat_PCM format_pcm; 3270a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten format_pcm.formatType = SL_DATAFORMAT_PCM; 3280a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten format_pcm.numChannels = sfinfo.channels; 3290a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten format_pcm.samplesPerSec = sfinfo.samplerate * 1000; 330ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten format_pcm.bitsPerSample = bitsPerSample; 3310a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten format_pcm.containerSize = format_pcm.bitsPerSample; 3320a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten format_pcm.channelMask = 1 == format_pcm.numChannels ? SL_SPEAKER_FRONT_CENTER : 3330a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; 334ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten format_pcm.endianness = byteOrder; 3350a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten SLDataSource audioSrc; 3360a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten audioSrc.pLocator = &loc_bufq; 3370a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten audioSrc.pFormat = &format_pcm; 3380a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten 3390a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten // configure audio sink 3400a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten SLDataLocator_OutputMix loc_outmix; 3410a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX; 3420a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten loc_outmix.outputMix = outputMixObject; 3430a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten SLDataSink audioSnk; 3440a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten audioSnk.pLocator = &loc_outmix; 3450a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten audioSnk.pFormat = NULL; 3460a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten 3470a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten // create audio player 3489a6c9db763121c3b11765c6c8cf935983c0385bfGlenn Kasten SLInterfaceID ids2[3] = {SL_IID_BUFFERQUEUE, SL_IID_PLAYBACKRATE, SL_IID_EFFECTSEND}; 3499a6c9db763121c3b11765c6c8cf935983c0385bfGlenn Kasten SLboolean req2[3] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; 3500a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten SLObjectItf playerObject; 3510a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten result = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, &audioSrc, 352f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten &audioSnk, enableReverb ? 3 : (enablePlaybackRate ? 2 : 1), ids2, req2); 353701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten if (SL_RESULT_SUCCESS != result) { 354701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten fprintf(stderr, "can't create audio player\n"); 355701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten goto no_player; 356701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten } 3570a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten 358ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten { 359ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten 3600a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten // realize the player 3610a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten result = (*playerObject)->Realize(playerObject, SL_BOOLEAN_FALSE); 3620a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten assert(SL_RESULT_SUCCESS == result); 3630a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten 3640a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten // get the effect send interface and enable effect send reverb for this player 3650a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten if (enableReverb) { 3660a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten SLEffectSendItf playerEffectSend; 3670a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten result = (*playerObject)->GetInterface(playerObject, SL_IID_EFFECTSEND, &playerEffectSend); 3680a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten assert(SL_RESULT_SUCCESS == result); 3690a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten result = (*playerEffectSend)->EnableEffectSend(playerEffectSend, mixEnvironmentalReverb, 3700a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten SL_BOOLEAN_TRUE, (SLmillibel) 0); 3710a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten assert(SL_RESULT_SUCCESS == result); 3720a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten } 3730a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten 3749a6c9db763121c3b11765c6c8cf935983c0385bfGlenn Kasten // get the playback rate interface and configure the rate 3759a6c9db763121c3b11765c6c8cf935983c0385bfGlenn Kasten SLPlaybackRateItf playerPlaybackRate; 376f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten SLpermille currentRate; 377f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten if (enablePlaybackRate) { 378f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAYBACKRATE, 379f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten &playerPlaybackRate); 380f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten assert(SL_RESULT_SUCCESS == result); 381f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten SLpermille defaultRate; 382f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten result = (*playerPlaybackRate)->GetRate(playerPlaybackRate, &defaultRate); 383f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten assert(SL_RESULT_SUCCESS == result); 384f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten SLuint32 defaultProperties; 385f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten result = (*playerPlaybackRate)->GetProperties(playerPlaybackRate, &defaultProperties); 386f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten assert(SL_RESULT_SUCCESS == result); 387f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten printf("default playback rate %d per mille, properties 0x%x\n", defaultRate, 388f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten defaultProperties); 389f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten if (initialRate <= 0) { 390f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten initialRate = defaultRate; 391f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten } 392f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten if (finalRate <= 0) { 393f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten finalRate = initialRate; 394f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten } 395f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten currentRate = defaultRate; 396f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten if (finalRate == initialRate) { 397701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten deltaRate = 0; 398f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten } else if (finalRate < initialRate) { 399f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten deltaRate = -deltaRate; 400f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten } 401f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten if (initialRate != defaultRate) { 402f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten result = (*playerPlaybackRate)->SetRate(playerPlaybackRate, initialRate); 403f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten if (SL_RESULT_FEATURE_UNSUPPORTED == result) { 404f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten fprintf(stderr, "initial playback rate %d is unsupported\n", initialRate); 405f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten deltaRate = 0; 406f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten } else if (SL_RESULT_PARAMETER_INVALID == result) { 407f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten fprintf(stderr, "initial playback rate %d is invalid\n", initialRate); 408f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten deltaRate = 0; 409f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten } else { 410f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten assert(SL_RESULT_SUCCESS == result); 411f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten currentRate = initialRate; 412f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten } 4139a6c9db763121c3b11765c6c8cf935983c0385bfGlenn Kasten } 4149a6c9db763121c3b11765c6c8cf935983c0385bfGlenn Kasten } 4159a6c9db763121c3b11765c6c8cf935983c0385bfGlenn Kasten 4160a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten // get the play interface 4170a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten SLPlayItf playerPlay; 4180a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAY, &playerPlay); 4190a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten assert(SL_RESULT_SUCCESS == result); 4200a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten 4210a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten // get the buffer queue interface 4220a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten SLBufferQueueItf playerBufferQueue; 4230a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten result = (*playerObject)->GetInterface(playerObject, SL_IID_BUFFERQUEUE, 4240a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten &playerBufferQueue); 4250a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten assert(SL_RESULT_SUCCESS == result); 4260a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten 4270a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten // loop until EOF or no more buffers 4280a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten for (which = 0; which < numBuffers; ++which) { 4290a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten short *buffer = &buffers[framesPerBuffer * sfinfo.channels * which]; 4300a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten sf_count_t frames = framesPerBuffer; 4310a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten sf_count_t count; 4320a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten count = sf_readf_short(sndfile, buffer, frames); 4330a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten if (0 >= count) { 4340a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten eof = SL_BOOLEAN_TRUE; 4350a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten break; 4360a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten } 4370a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten 4380a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten // enqueue a buffer 439ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten SLuint32 nbytes = count * sfinfo.channels * sizeof(short); 440ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten if (byteOrder != nativeByteOrder) { 441ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten swab(buffer, buffer, nbytes); 442ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten } 443ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten if (bitsPerSample == 8) { 444ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten squeeze(buffer, (unsigned char *) buffer, nbytes); 445ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten nbytes /= 2; 446ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten } 447ebca1a420c4ada9eff2e82f0100abaea95b48f24Glenn Kasten result = (*playerBufferQueue)->Enqueue(playerBufferQueue, buffer, nbytes); 4480a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten assert(SL_RESULT_SUCCESS == result); 4490a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten } 450701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten if (which >= numBuffers) { 4510a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten which = 0; 452701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten } 4530a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten 4540a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten // register a callback on the buffer queue 4550a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten result = (*playerBufferQueue)->RegisterCallback(playerBufferQueue, callback, NULL); 4560a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten assert(SL_RESULT_SUCCESS == result); 4570a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten 458ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten pipeWriter = new android::MonoPipe(16384, nbaio_format, false /*writeCanBlock*/); 459ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten android::NBAIO_Format offer = nbaio_format; 460ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten size_t numCounterOffers = 0; 461ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten ssize_t neg = pipeWriter->negotiate(&offer, 1, NULL, numCounterOffers); 462ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten assert(0 == neg); 463ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten pipeReader = new android::MonoPipeReader(pipeWriter); 464ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten numCounterOffers = 0; 465ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten neg = pipeReader->negotiate(&offer, 1, NULL, numCounterOffers); 466ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten assert(0 == neg); 467ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten 468ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten // create thread to read from file 469ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten pthread_t thread; 470ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten int ok = pthread_create(&thread, (const pthread_attr_t *) NULL, file_reader_loop, NULL); 471ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten assert(0 == ok); 472ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten 473ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten // give thread a head start so that the pipe is initially filled 474ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten sleep(1); 475ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten 4760a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten // set the player's state to playing 4770a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING); 4780a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten assert(SL_RESULT_SUCCESS == result); 4790a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten 480701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten // get the initial time 481701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten struct timespec prevTs; 482701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten clock_gettime(CLOCK_MONOTONIC, &prevTs); 483701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten long elapsedNs = 0; 484701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten long deltaRateNs = deltaRateMs * 1000000; 485701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten 4860a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten // wait until the buffer queue is empty 4870a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten SLBufferQueueState bufqstate; 4880a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten for (;;) { 4890a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten result = (*playerBufferQueue)->GetState(playerBufferQueue, &bufqstate); 4900a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten assert(SL_RESULT_SUCCESS == result); 4910a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten if (0 >= bufqstate.count) { 4920a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten break; 4930a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten } 494f8d147df8f6dba1bb5bb0ea4c09795ee827569caGlenn Kasten if (!enablePlaybackRate || deltaRate == 0) { 495701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten sleep(1); 496701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten } else { 497701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten struct timespec curTs; 498701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten clock_gettime(CLOCK_MONOTONIC, &curTs); 499701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten elapsedNs += (curTs.tv_sec - prevTs.tv_sec) * 1000000000 + 500701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten // this term can be negative 501701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten (curTs.tv_nsec - prevTs.tv_nsec); 502701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten prevTs = curTs; 503701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten if (elapsedNs < deltaRateNs) { 504701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten usleep((deltaRateNs - elapsedNs) / 1000); 505701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten continue; 506701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten } 507701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten elapsedNs -= deltaRateNs; 508701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten SLpermille nextRate = currentRate + deltaRate; 509701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten result = (*playerPlaybackRate)->SetRate(playerPlaybackRate, nextRate); 510701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten if (SL_RESULT_SUCCESS != result) { 511701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten fprintf(stderr, "next playback rate %d is unsupported\n", nextRate); 512701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten } else if (SL_RESULT_PARAMETER_INVALID == result) { 513701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten fprintf(stderr, "next playback rate %d is invalid\n", nextRate); 514701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten } else { 515701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten assert(SL_RESULT_SUCCESS == result); 516701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten } 517701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten currentRate = nextRate; 518701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten if (currentRate >= max(initialRate, finalRate)) { 519701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten currentRate = max(initialRate, finalRate); 520701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten deltaRate = -abs(deltaRate); 521701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten } else if (currentRate <= min(initialRate, finalRate)) { 522701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten currentRate = min(initialRate, finalRate); 523701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten deltaRate = abs(deltaRate); 524701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten } 525701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten } 5260a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten } 5270a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten 5280a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten // destroy audio player 5290a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten (*playerObject)->Destroy(playerObject); 5300a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten 531ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten } 532ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten 533701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kastenno_player: 534701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten 5350a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten // destroy output mix 5360a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten (*outputMixObject)->Destroy(outputMixObject); 5370a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten 5380a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten // destroy engine 5390a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten (*engineObject)->Destroy(engineObject); 5400a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten 541ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten } 542ad6c970f500cf99dd1eb23b9f5b2360948db90e7Glenn Kasten 543701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kastenclose_sndfile: 544701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten 545701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten (void) sf_close(sndfile); 546701cf2a089c87ec5b8e5a953f637b250aee4a58aGlenn Kasten 5470a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten return EXIT_SUCCESS; 5480a058cc3d720cdf3f0f8222472a862258482f34fGlenn Kasten} 549