summaryrefslogtreecommitdiff
path: root/examples/osxplay.c
diff options
context:
space:
mode:
authorGraydon, Tracy <tracy.graydon@intel.com>2012-11-28 18:07:32 -0800
committerGraydon, Tracy <tracy.graydon@intel.com>2012-11-28 18:07:32 -0800
commitf9151a123d7943fb7e944a38b1aa835c03b0188e (patch)
treee7dfd84705f5db614d08449cb3e70c4dad74ff97 /examples/osxplay.c
downloadaudiofile-f9151a123d7943fb7e944a38b1aa835c03b0188e.tar.gz
audiofile-f9151a123d7943fb7e944a38b1aa835c03b0188e.tar.bz2
audiofile-f9151a123d7943fb7e944a38b1aa835c03b0188e.zip
Diffstat (limited to 'examples/osxplay.c')
-rw-r--r--examples/osxplay.c257
1 files changed, 257 insertions, 0 deletions
diff --git a/examples/osxplay.c b/examples/osxplay.c
new file mode 100644
index 0000000..0708c68
--- /dev/null
+++ b/examples/osxplay.c
@@ -0,0 +1,257 @@
+/*
+ Audio File Library
+
+ Copyright (c) 2003, Michael Pruett. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or
+ without modification, are permitted provided that the following
+ conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+
+ 3. The name of the author may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ osxplay.c
+
+ This program demonstrates audio file playback using the Audio
+ File Library and Core Audio.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <audiofile.h>
+
+#include <CoreServices/CoreServices.h>
+#include <AudioUnit/AudioUnit.h>
+#include <CoreAudio/CoreAudio.h>
+
+#define BUFFER_FRAME_COUNT 1024
+
+int isPlaying = 1;
+void *buffer = NULL;
+
+void getASBDForFile (AFfilehandle file, int track,
+ AudioStreamBasicDescription *asbd)
+{
+ int sampleFormat, sampleWidth, channelCount;
+ double rate;
+
+ afGetVirtualSampleFormat(file, track, &sampleFormat, &sampleWidth);
+ channelCount = afGetChannels(file, track);
+ rate = afGetRate(file, track);
+
+ asbd->mSampleRate = rate;
+ asbd->mFormatID = kAudioFormatLinearPCM;
+ switch (sampleFormat)
+ {
+ case AF_SAMPFMT_TWOSCOMP:
+ asbd->mFormatFlags = kAudioFormatFlagIsSignedInteger;
+ asbd->mBitsPerChannel = sampleWidth;
+ break;
+ case AF_SAMPFMT_UNSIGNED:
+ asbd->mFormatFlags = 0;
+ asbd->mBitsPerChannel = sampleWidth;
+ break;
+ case AF_SAMPFMT_FLOAT:
+ asbd->mFormatFlags = kAudioFormatFlagIsFloat;
+ asbd->mBitsPerChannel = 32;
+ break;
+ case AF_SAMPFMT_DOUBLE:
+ asbd->mFormatFlags = kAudioFormatFlagIsFloat;
+ asbd->mBitsPerChannel = 64;
+ break;
+ }
+
+ asbd->mChannelsPerFrame = channelCount;
+ asbd->mFramesPerPacket = 1;
+ asbd->mBytesPerFrame = ceilf(afGetVirtualFrameSize(file, track, 1));
+ asbd->mBytesPerPacket = asbd->mBytesPerFrame;
+
+ if (afGetVirtualByteOrder(file, track) == AF_BYTEORDER_BIGENDIAN)
+ asbd->mFormatFlags |= kAudioFormatFlagIsBigEndian;
+}
+
+OSStatus openOutput (AudioUnit *outputUnit)
+{
+ OSStatus status = noErr;
+ ComponentDescription description;
+ Component component;
+
+ description.componentType = kAudioUnitType_Output;
+ description.componentSubType = kAudioUnitSubType_DefaultOutput;
+ description.componentManufacturer = kAudioUnitManufacturer_Apple;
+ description.componentFlags = 0;
+ description.componentFlagsMask = 0;
+
+ component = FindNextComponent(NULL, &description);
+ if (component == NULL)
+ {
+ fprintf(stderr, "Could not find audio output device.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ status = OpenAComponent(component, outputUnit);
+ if (status != noErr)
+ {
+ fprintf(stderr, "Could not open audio output device.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ status = AudioUnitInitialize(*outputUnit);
+ if (status != noErr)
+ {
+ fprintf(stderr, "Could not initialize audio output device.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ return status;
+}
+
+OSStatus fileRenderProc (void *inRefCon,
+ AudioUnitRenderActionFlags *inActionFlags,
+ const AudioTimeStamp *inTimeStamp,
+ UInt32 inBusNumber,
+ UInt32 inNumFrames,
+ AudioBufferList *ioData)
+{
+ AFfilehandle file = (AFfilehandle) inRefCon;
+ AFframecount framesToRead, framesRead;
+
+ framesToRead = inNumFrames;
+ if (framesToRead > BUFFER_FRAME_COUNT)
+ framesToRead = BUFFER_FRAME_COUNT;
+
+ framesRead = afReadFrames(file, AF_DEFAULT_TRACK,
+ buffer, framesToRead);
+ if (framesRead > 0)
+ {
+ ioData->mBuffers[0].mData = buffer;
+ ioData->mBuffers[0].mDataByteSize = framesRead *
+ afGetVirtualFrameSize(file, AF_DEFAULT_TRACK, 1);
+ }
+ else
+ isPlaying = 0;
+
+ return noErr;
+}
+
+OSStatus setupOutput (AudioUnit *outputUnit, AFfilehandle file)
+{
+ OSStatus status = noErr;
+ UInt32 size;
+ Boolean outWritable;
+
+ AudioStreamBasicDescription fileASBD, inputASBD, outputASBD;
+ AURenderCallbackStruct renderCallback;
+
+ /* Set virtual sample format to single-precision floating-point. */
+ afSetVirtualSampleFormat(file, AF_DEFAULT_TRACK, AF_SAMPFMT_FLOAT, 32);
+
+ /* Get ASBD for virtual sample format. */
+ getASBDForFile(file, AF_DEFAULT_TRACK, &fileASBD);
+
+ status = AudioUnitGetPropertyInfo(*outputUnit,
+ kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output,
+ 0, &size, &outWritable);
+
+ status = AudioUnitGetProperty(*outputUnit,
+ kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output,
+ 0, &outputASBD, &size);
+
+ if (outWritable)
+ {
+ outputASBD = fileASBD;
+
+ status = AudioUnitSetProperty(*outputUnit,
+ kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output,
+ 0, &outputASBD, size);
+ }
+
+ inputASBD = fileASBD;
+
+ status = AudioUnitSetProperty(*outputUnit,
+ kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input,
+ 0, &inputASBD, size);
+ if (status != noErr)
+ {
+ fprintf(stderr, "Could not set input stream format.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /*
+ Set the render callback to a procedure which will
+ read from the file.
+ */
+ renderCallback.inputProc = fileRenderProc;
+ renderCallback.inputProcRefCon = file;
+
+ status = AudioUnitSetProperty(*outputUnit,
+ kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0,
+ &renderCallback, sizeof (AURenderCallbackStruct));
+ if (status != noErr)
+ {
+ fprintf(stderr, "Could not set render callback.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ return status;
+}
+
+int main (int argc, char **argv)
+{
+ AFfilehandle file;
+ AudioUnit outputUnit;
+
+ if (argc < 2)
+ {
+ fprintf(stderr, "usage: %s filename\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ file = afOpenFile(argv[1], "r", AF_NULL_FILESETUP);
+ if (file == AF_NULL_FILEHANDLE)
+ {
+ fprintf(stderr, "Could not open file '%s' for reading.\n", argv[1]);
+ exit(EXIT_FAILURE);
+ }
+
+ openOutput(&outputUnit);
+ setupOutput(&outputUnit, file);
+ AudioOutputUnitStart(outputUnit);
+
+ buffer = malloc(BUFFER_FRAME_COUNT *
+ afGetVirtualFrameSize(file, AF_DEFAULT_TRACK, 1));
+
+ while (isPlaying)
+ usleep(250000);
+
+ AudioOutputUnitStop(outputUnit);
+ AudioUnitUninitialize(outputUnit);
+ CloseComponent(outputUnit);
+
+ free(buffer);
+
+ afCloseFile(file);
+}