00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "OSX_WavPlayer.h"
00017
00018 namespace OVR { namespace Platform { namespace OSX {
00019
00020 WavPlayer::WavPlayer(const char* fileName)
00021 {
00022 FileName = fileName;
00023 }
00024
00025 bool WavPlayer::isDataChunk(unsigned char* buffer, int index)
00026 {
00027 unsigned char a = buffer[index];
00028 unsigned char b = buffer[index + 1];
00029 unsigned char c = buffer[index + 2];
00030 unsigned char d = buffer[index + 3];
00031 return (a == 'D' || a == 'd') && (b == 'A' || b == 'a') &&
00032 (c == 'T' || c == 't') && (d == 'A' || d == 'a');
00033 }
00034
00035 int WavPlayer::getWord(unsigned char* buffer, int index)
00036 {
00037 unsigned char a = buffer[index];
00038 unsigned char b = buffer[index + 1];
00039 unsigned char c = buffer[index + 2];
00040 unsigned char d = buffer[index + 3];
00041 int result = 0;
00042 result |= a;
00043 result |= b << 8;
00044 result |= c << 16;
00045 result |= d << 24;
00046 return result;
00047 }
00048
00049 short WavPlayer::getHalf(unsigned char* buffer, int index)
00050 {
00051 unsigned char a = buffer[index];
00052 unsigned char b = buffer[index + 1];
00053 short result = 0;
00054 result |= a;
00055 result |= b << 8;
00056 return result;
00057 }
00058
00059 void *WavPlayer::LoadPCM(const char *filename, unsigned long *len)
00060 {
00061 FILE *file;
00062 struct stat s;
00063 void *pcm;
00064
00065 if(stat(filename, &s))
00066 {
00067 return NULL;
00068 }
00069 *len = s.st_size;
00070 pcm = (void *) malloc(s.st_size);
00071 if(!pcm)
00072 {
00073 return NULL;
00074 }
00075 file = fopen(filename, "rb");
00076 if(!file)
00077 {
00078 free(pcm);
00079 return NULL;
00080 }
00081 fread(pcm, s.st_size, 1, file);
00082 fclose(file);
00083 return pcm;
00084 }
00085
00086 int WavPlayer::PlayBuffer(void *pcmbuffer, unsigned long len)
00087 {
00088 AQCallbackStruct aqc;
00089 UInt32 err, bufferSize;
00090 int i;
00091
00092 aqc.DataFormat.mSampleRate = SampleRate;
00093 aqc.DataFormat.mFormatID = kAudioFormatLinearPCM;
00094 if(BitsPerSample == 16)
00095 {
00096 aqc.DataFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger
00097 | kAudioFormatFlagIsPacked;
00098 }
00099 aqc.DataFormat.mBytesPerPacket = NumChannels * (BitsPerSample / 8);
00100 aqc.DataFormat.mFramesPerPacket = 1;
00101 aqc.DataFormat.mBytesPerFrame = NumChannels * (BitsPerSample / 8);
00102 aqc.DataFormat.mChannelsPerFrame = NumChannels;
00103 aqc.DataFormat.mBitsPerChannel = BitsPerSample;
00104 aqc.FrameCount = SampleRate / 60;
00105 aqc.SampleLen = (UInt32)(len);
00106 aqc.PlayPtr = 0;
00107 aqc.PCMBuffer = static_cast<unsigned char*>(pcmbuffer);
00108
00109 err = AudioQueueNewOutput(&aqc.DataFormat,
00110 aqBufferCallback,
00111 &aqc,
00112 NULL,
00113 kCFRunLoopCommonModes,
00114 0,
00115 &aqc.Queue);
00116 if(err)
00117 {
00118 return err;
00119 }
00120
00121 aqc.FrameCount = SampleRate / 60;
00122 bufferSize = aqc.FrameCount * aqc.DataFormat.mBytesPerPacket;
00123
00124 for(i = 0; i < AUDIO_BUFFERS; i++)
00125 {
00126 err = AudioQueueAllocateBuffer(aqc.Queue, bufferSize,
00127 &aqc.Buffers[i]);
00128 if(err)
00129 {
00130 return err;
00131 }
00132 aqBufferCallback(&aqc, aqc.Queue, aqc.Buffers[i]);
00133 }
00134
00135 err = AudioQueueStart(aqc.Queue, NULL);
00136 if(err)
00137 {
00138 return err;
00139 }
00140
00141 while(true)
00142 {
00143 }
00144 sleep(1);
00145 return 0;
00146 }
00147
00148 void WavPlayer::aqBufferCallback(void *in, AudioQueueRef inQ, AudioQueueBufferRef outQB)
00149 {
00150 AQCallbackStruct *aqc;
00151 unsigned char *coreAudioBuffer;
00152
00153 aqc = (AQCallbackStruct *) in;
00154 coreAudioBuffer = (unsigned char*) outQB->mAudioData;
00155
00156 printf("Sync: %u / %u\n", aqc->PlayPtr, aqc->SampleLen);
00157
00158 if(aqc->FrameCount > 0)
00159 {
00160 outQB->mAudioDataByteSize = aqc->DataFormat.mBytesPerFrame * aqc->FrameCount;
00161 for(int i = 0; i < aqc->FrameCount * aqc->DataFormat.mBytesPerFrame; i++)
00162 {
00163 if(aqc->PlayPtr > aqc->SampleLen)
00164 {
00165 aqc->PlayPtr = 0;
00166 i = 0;
00167 }
00168 coreAudioBuffer[i] = aqc->PCMBuffer[aqc->PlayPtr];
00169 aqc->PlayPtr++;
00170 }
00171 AudioQueueEnqueueBuffer(inQ, outQB, 0, NULL);
00172 }
00173 }
00174
00175 int WavPlayer::PlayAudio()
00176 {
00177 unsigned long len;
00178 void *pcmbuffer;
00179 int ret;
00180
00181 pcmbuffer = LoadPCM(FileName, &len);
00182 if(!pcmbuffer)
00183 {
00184 fprintf(stderr, "%s: %s\n", FileName, strerror(errno));
00185 exit(EXIT_FAILURE);
00186 }
00187
00188 unsigned char* bytes = (unsigned char*)pcmbuffer;
00189 int index = 0;
00190
00191
00192 getWord(bytes, index);
00193 index += 4;
00194
00195 getWord(bytes, index);
00196 index += 4;
00197
00198 getWord(bytes, index);
00199 index += 4;
00200
00201 getWord(bytes, index);
00202 index += 4;
00203
00204
00205 int fmtLen = getWord(bytes, index);
00206 index += 4;
00207 AudioFormat = getHalf(bytes, index);
00208 index += 2;
00209 NumChannels = getHalf(bytes, index);
00210 index += 2;
00211 SampleRate = getWord(bytes, index);
00212 index += 4;
00213 ByteRate = getWord(bytes, index);
00214 index += 4;
00215 BlockAlign = getHalf(bytes, index);
00216 index += 2;
00217 BitsPerSample = getHalf(bytes, index);
00218 index += 2;
00219 index += fmtLen - 16;
00220 while(!isDataChunk(bytes, index))
00221 {
00222
00223 getWord(bytes, index);
00224 index += 4;
00225
00226 int anyChunkLen = getWord(bytes, index);
00227 index += 4 + anyChunkLen;
00228 }
00229
00230 getWord(bytes, index);
00231 index += 4;
00232
00233 unsigned long dataLen = getWord(bytes, index);
00234 index += 4;
00235 unsigned char* target = &bytes[index];
00236
00237 ret = PlayBuffer((void *)target, dataLen);
00238 free(pcmbuffer);
00239 return ret;
00240 }
00241
00242 }}}