15 #include <AudioToolbox/AudioToolbox.h>
27 "title" :
"VuoAudioFile",
36 "VuoList_VuoAudioSamples",
37 "AudioToolbox.framework",
38 "CoreFoundation.framework"
73 float *buffer = (
float*)malloc(bufferSize);
74 bzero(buffer, bufferSize);
77 VuoInteger framesRemaining = VuoAudioSamples_bufferSize;
78 float *subBuffer = buffer;
80 while (framesRemaining)
82 AudioBufferList bufferList;
83 bufferList.mNumberBuffers = 1;
84 bufferList.mBuffers[0].mNumberChannels = afi->outputFormat.mChannelsPerFrame;
85 bufferList.mBuffers[0].mDataByteSize = sizeof(float) * afi->outputFormat.mChannelsPerFrame * framesRemaining;
86 bufferList.mBuffers[0].mData = (void *)subBuffer;
88 UInt32 numFrames = framesRemaining;
89 OSStatus err = ExtAudioFileRead(afi->audioFile, &numFrames, &bufferList);
93 char *errStr = VuoOsStatus_getText(err);
94 VUserLog(
"Error reading samples: %s", errStr);
97 if (afi->finishedPlayback)
98 afi->finishedPlayback();
108 framesRemaining -= numFrames;
109 subBuffer += numFrames * afi->outputFormat.mChannelsPerFrame;
123 case VuoLoopType_Loop:
125 const SInt64 targetFrame = 0;
127 OSStatus err = ExtAudioFileSeek(afi->audioFile, targetFrame + afi->headerFrames);
131 char *errStr = VuoOsStatus_getText(err);
132 VUserLog(
"Error seeking to sample: %s", errStr);
134 afi->playing = false;
150 for (
VuoInteger channel = 0; channel < afi->outputFormat.mChannelsPerFrame; ++channel)
156 samples.
samples[sample] = buffer[sample*afi->outputFormat.mChannelsPerFrame + channel];
162 dispatch_sync(afi->audioFileQueue, ^{
163 if (afi->decodedChannels)
164 afi->decodedChannels(channels);
168 VuoRelease(channels);
213 afi->
loop = VuoLoopType_None;
220 CFStringRef urlCFS = CFStringCreateWithCString(NULL, normalizedURL, kCFStringEncodingUTF8);
221 CFURLRef url = CFURLCreateWithString(NULL, urlCFS, NULL);
224 VUserLog(
"Couldn't open '%s': Invalid URL.", normalizedURL);
233 OSStatus err = ExtAudioFileOpenURL(url, &afi->
audioFile);
239 VUserLog(
"Couldn't open '%s': %s", normalizedURL, errStr);
249 OSStatus err = ExtAudioFileGetProperty(afi->
audioFile, kExtAudioFileProperty_FileDataFormat, &size, &afi->
inputFormat);
253 VUserLog(
"Error getting file format for '%s': %s", url, errStr);
261 OSStatus err = ExtAudioFileGetProperty(afi->
audioFile, kExtAudioFileProperty_FileLengthFrames, &size, &afi->
totalFrameCount);
265 VUserLog(
"Error getting frame count for '%s': %s", url, errStr);
275 afi->
outputFormat.mFormatFlags = kAudioFormatFlagIsFloat;
281 OSStatus err = ExtAudioFileSetProperty(afi->
audioFile, kExtAudioFileProperty_ClientDataFormat, size, &afi->
outputFormat);
285 VUserLog(
"Error setting output format for '%s': %s", url, errStr);
292 AudioConverterRef ac;
293 UInt32 size =
sizeof(AudioConverterRef);
295 OSStatus err = ExtAudioFileGetProperty(afi->
audioFile, kExtAudioFileProperty_AudioConverter, &size, &ac);
299 VUserLog(
"Error getting audio converter info for '%s': %s", url, errStr);
304 AudioConverterPrimeInfo pi;
305 UInt32 size =
sizeof(AudioConverterPrimeInfo);
307 OSStatus err = AudioConverterGetProperty(ac, kAudioConverterPrimeInfo, &size, &pi);
310 if (err != kAudioFormatUnsupportedPropertyError)
313 VUserLog(
"Error getting header info for '%s': %s", url, errStr);
323 dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
324 afi->
playbackTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, DISPATCH_TIMER_STRICT, q);
328 dispatch_source_set_timer(afi->
playbackTimer, dispatch_time(DISPATCH_TIME_NOW, nanoseconds), nanoseconds, 0);
330 VuoAudioFile_decodeChannels(afi);
333 dispatch_semaphore_signal(afi->playbackTimerCanceled);
362 *channelCount = afi->
inputFormat.mChannelsPerFrame;
381 afi->decodedChannels = decodedChannels;
382 afi->finishedPlayback = finishedPlayback;
397 afi->decodedChannels = NULL;
398 afi->finishedPlayback = NULL;
422 SInt64 targetFrame = time * afi->inputFormat.mSampleRate;
424 OSStatus err = ExtAudioFileSeek(afi->audioFile, targetFrame + afi->headerFrames);
427 char *errStr = VuoOsStatus_getText(err);
428 VUserLog(
"Error seeking to sample: %s", errStr);