OSX_WavPlayer.cpp
Go to the documentation of this file.
00001 /************************************************************************************
00002 
00003 Filename    :   WavPlayer_OSX.cpp
00004 Content     :   An Apple OSX audio handler.
00005 Created     :   March 5, 2013
00006 Authors     :   Robotic Arm Software - Peter Hoff, Dan Goodman, Bryan Croteau
00007 
00008 Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
00009 
00010 Use of this software is subject to the terms of the Oculus LLC license
00011 agreement provided at the time of installation or download, or which
00012 otherwise accompanies this software in either electronic or hard copy form.
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     // 'RIFF'
00192     getWord(bytes, index);
00193     index += 4;
00194     // int Length
00195     getWord(bytes, index);
00196     index += 4;
00197     // 'WAVE'
00198     getWord(bytes, index);
00199     index += 4;
00200     // 'fmt '
00201     getWord(bytes, index);
00202     index += 4;
00203 
00204     // int Format Length
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         // Any Chunk
00223         getWord(bytes, index);
00224         index += 4;
00225         // Any Chunk Length
00226         int anyChunkLen = getWord(bytes, index);
00227         index += 4 + anyChunkLen;
00228     }
00229     // 'data'
00230     getWord(bytes, index);
00231     index += 4;
00232     // int Data Length
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 }}}


oculus_sdk
Author(s):
autogenerated on Mon Oct 6 2014 03:01:18