summaryrefslogtreecommitdiffstats
path: root/src/uscxml/plugins/invoker/audio/AudioToolbox.mm
diff options
context:
space:
mode:
Diffstat (limited to 'src/uscxml/plugins/invoker/audio/AudioToolbox.mm')
-rw-r--r--src/uscxml/plugins/invoker/audio/AudioToolbox.mm152
1 files changed, 152 insertions, 0 deletions
diff --git a/src/uscxml/plugins/invoker/audio/AudioToolbox.mm b/src/uscxml/plugins/invoker/audio/AudioToolbox.mm
new file mode 100644
index 0000000..44720b1
--- /dev/null
+++ b/src/uscxml/plugins/invoker/audio/AudioToolbox.mm
@@ -0,0 +1,152 @@
+#include "AudioToolbox.h"
+#include <glog/logging.h>
+
+#import <Foundation/Foundation.h>
+#import <Foundation/NSURL.h>
+
+namespace uscxml {
+
+AudioToolbox::AudioToolbox(const std::string filename) {
+ @autoreleasepool {
+ _afId = 0;
+ NSString* filePath = [NSString stringWithCString:filename.c_str() encoding:NSASCIIStringEncoding];
+ NSURL* afUrl = [NSURL fileURLWithPath:filePath];
+
+ OSStatus result = noErr;
+
+ result = ExtAudioFileOpenURL((CFURLRef)afUrl, &_afId);
+
+ if (result != noErr) {
+ LOG(WARNING) << "Cannot open audio file " << filename;
+ return;
+ }
+ UInt32 thePropertySize = sizeof(_inputFormat);
+ result = ExtAudioFileGetProperty(_afId, kExtAudioFileProperty_FileDataFormat, &thePropertySize, &_inputFormat);
+ if (result != noErr) {
+ LOG(WARNING) << "Cannot determine input format of " << filename;
+ return;
+ }
+
+ // output format is input format
+ memcpy(&_outputFormat, &_inputFormat, sizeof(_inputFormat));
+
+ // except for things that make no sense for open al
+ _outputFormat.mFormatID = kAudioFormatLinearPCM;
+ _outputFormat.mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger;
+
+ ALenum bestFormat = formatToALEnum(_outputFormat);
+ alEnumToFormat(_outputFormat, bestFormat);
+
+ result = ExtAudioFileSetProperty(_afId, kExtAudioFileProperty_ClientDataFormat, sizeof(_outputFormat), &_outputFormat);
+
+ if (result != noErr) {
+ LOG(WARNING) << "Cannot set audio format file " << filename;
+ return;
+ }
+
+ }
+}
+
+AudioToolbox::~AudioToolbox() {
+ if (_afId)
+ ExtAudioFileDispose(_afId); //close the file
+}
+
+void AudioToolbox::seek(unsigned int pos) {
+ ExtAudioFileSeek(_afId, pos);
+}
+
+int AudioToolbox::read(char* buffer, unsigned int size) {
+ UInt32 read = size / _outputFormat.mBytesPerFrame;
+ OSStatus result = noErr;
+
+ SInt64 theFileLengthInFrames = 0;
+ UInt32 thePropertySize = sizeof(theFileLengthInFrames);
+ result = ExtAudioFileGetProperty(_afId, kExtAudioFileProperty_FileLengthFrames, &thePropertySize, &theFileLengthInFrames);
+
+ read = (theFileLengthInFrames < read ? theFileLengthInFrames : read);
+
+ AudioBufferList dataBuffer;
+ dataBuffer.mNumberBuffers = 1;
+ dataBuffer.mBuffers[0].mDataByteSize = size;
+ dataBuffer.mBuffers[0].mNumberChannels = _outputFormat.mChannelsPerFrame;
+ dataBuffer.mBuffers[0].mData = buffer;
+
+ result = ExtAudioFileRead(_afId, &read, &dataBuffer);
+ if (result != noErr) {
+ LOG(WARNING) << "Cannot read data";
+ return 0;
+ }
+
+ return read * _outputFormat.mBytesPerFrame;
+}
+
+ALenum AudioToolbox::formatToALEnum(AudioStreamBasicDescription asbd) {
+ if (asbd.mBitsPerChannel < 16) {
+ if (asbd.mChannelsPerFrame == 1) {
+ return AL_FORMAT_MONO8;
+ } else {
+ return AL_FORMAT_STEREO8;
+ }
+ } else {
+ if (asbd.mChannelsPerFrame == 1) {
+ return AL_FORMAT_MONO16;
+ } else {
+ return AL_FORMAT_STEREO16;
+ }
+ }
+}
+
+bool AudioToolbox::alEnumToFormat(AudioStreamBasicDescription& asbd, ALenum format) {
+ switch (format) {
+ case AL_FORMAT_MONO8:
+ asbd.mBitsPerChannel = 8;
+ asbd.mBytesPerFrame = 1;
+ asbd.mBytesPerPacket = 1;
+ asbd.mChannelsPerFrame = 1;
+ break;
+ case AL_FORMAT_MONO16:
+ asbd.mBitsPerChannel = 16;
+ asbd.mBytesPerFrame = 2;
+ asbd.mBytesPerPacket = 2;
+ asbd.mChannelsPerFrame = 1;
+ break;
+ case AL_FORMAT_STEREO8:
+ asbd.mBitsPerChannel = 8;
+ asbd.mBytesPerFrame = 2;
+ asbd.mBytesPerPacket = 2;
+ asbd.mChannelsPerFrame = 2;
+ break;
+ case AL_FORMAT_STEREO16:
+ asbd.mBitsPerChannel = 16;
+ asbd.mBytesPerFrame = 4;
+ asbd.mBytesPerPacket = 4;
+ asbd.mChannelsPerFrame = 2;
+ break;
+ default:
+ break;
+ }
+ return true;
+}
+
+void AudioToolbox::setOutFormat(const PCMFormat& format) {
+
+ alEnumToFormat(_outputFormat, format.alFormat);
+ _outputFormat.mSampleRate = format.sampleRate;
+
+ OSStatus result = ExtAudioFileSetProperty(_afId, kExtAudioFileProperty_ClientDataFormat, sizeof(_outputFormat), &_outputFormat);
+ if (result != noErr) {
+ LOG(WARNING) << "Cannot set audio format";
+ return;
+ }
+
+}
+
+PCMFormat AudioToolbox::getInFormat() {
+ PCMFormat format;
+ format.sampleRate = _inputFormat.mSampleRate;
+ format.alFormat = formatToALEnum(_inputFormat);
+ return format;
+}
+
+} \ No newline at end of file