src/io/sink_apple_audio.c: added apple_audio sink, merge apple stuff
authorPaul Brossier <piem@piem.org>
Sun, 15 Jul 2012 18:02:27 +0000 (12:02 -0600)
committerPaul Brossier <piem@piem.org>
Sun, 15 Jul 2012 18:02:27 +0000 (12:02 -0600)
src/io/sink_apple_audio.c [new file with mode: 0644]
src/io/sink_apple_audio.h [new file with mode: 0644]
src/io/source_apple_audio.c
src/io/utils_apple_audio.c [new file with mode: 0644]

diff --git a/src/io/sink_apple_audio.c b/src/io/sink_apple_audio.c
new file mode 100644 (file)
index 0000000..c3fa0f4
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+  Copyright (C) 2012 Paul Brossier <piem@aubio.org>
+
+  This file is part of aubio.
+
+  aubio is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  aubio is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with aubio.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "config.h"
+#include "aubio_priv.h"
+#include "fvec.h"
+#include "io/sink_apple_audio.h"
+
+// CFURLRef, CFURLCreateWithFileSystemPath, ...
+#include <CoreFoundation/CoreFoundation.h>
+// ExtAudioFileRef, AudioStreamBasicDescription, AudioBufferList, ...
+#include <AudioToolbox/AudioToolbox.h>
+
+#define FLOAT_TO_SHORT(x) (short)(x * 32768)
+
+extern int createAubioBufferList(AudioBufferList *bufferList, int channels, int segmentSize);
+extern void freeAudioBufferList(AudioBufferList *bufferList);
+extern CFURLRef getURLFromPath(const char * path);
+
+#define MAX_SIZE 4096 // the maximum number of frames that can be written at a time
+
+struct _aubio_sink_apple_audio_t { 
+  uint_t samplerate;
+  uint_t channels;
+  char_t *path;
+
+  uint_t max_frames;
+
+  AudioBufferList bufferList;
+  ExtAudioFileRef audioFile;
+};
+
+aubio_sink_apple_audio_t * new_aubio_sink_apple_audio(char_t * uri, uint_t samplerate) {
+  aubio_sink_apple_audio_t * s = AUBIO_NEW(aubio_sink_apple_audio_t);
+  s->samplerate;
+  s->channels = 1;
+  s->path = uri;
+  s->max_frames = MAX_SIZE;
+
+  AudioStreamBasicDescription clientFormat;
+  UInt32 propSize = sizeof(clientFormat);
+  memset(&clientFormat, 0, sizeof(AudioStreamBasicDescription));
+  clientFormat.mFormatID         = kAudioFormatLinearPCM;
+  clientFormat.mSampleRate       = (Float64)(s->samplerate);
+  clientFormat.mFormatFlags      = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
+  clientFormat.mChannelsPerFrame = s->channels;
+  clientFormat.mBitsPerChannel   = sizeof(short) * 8;
+  clientFormat.mFramesPerPacket  = 1;
+  clientFormat.mBytesPerFrame    = clientFormat.mBitsPerChannel * clientFormat.mChannelsPerFrame / 8;
+  clientFormat.mBytesPerPacket   = clientFormat.mFramesPerPacket * clientFormat.mBytesPerFrame;
+  clientFormat.mReserved         = 0;
+
+  AudioFileTypeID fileType = kAudioFileWAVEType;
+  CFURLRef fileURL = getURLFromPath(uri);
+  bool overwrite = true;
+  OSStatus err = noErr;
+  err = ExtAudioFileCreateWithURL(fileURL, fileType, &clientFormat, NULL,
+     overwrite ? kAudioFileFlags_EraseFile : 0, &s->audioFile);
+  if (err) {
+    AUBIO_ERR("error when trying to access %s, in ExtAudioFileOpenURL, %d\n", s->path, (int)err);
+    goto beach;
+  }
+  if (createAubioBufferList(&s->bufferList, s->channels, s->max_frames * s->channels)) {
+    AUBIO_ERR("error when creating buffer list for %s, out of memory? \n", s->path);
+    goto beach;
+  }
+  return s;
+
+beach:
+  AUBIO_FREE(s);
+  return NULL;
+}
+
+void aubio_sink_apple_audio_do(aubio_sink_apple_audio_t * s, fvec_t * write_data, uint_t write) {
+  OSStatus err = noErr;
+  UInt32 c, v;
+  bool async = true;
+  short *data = (short*)s->bufferList.mBuffers[0].mData;
+  if (write > s->max_frames) { 
+    write = s->max_frames;
+    AUBIO_WRN("trying to write %d frames, but only %d can be written at a time",
+      write, s->max_frames);
+  }
+  smpl_t *buf = write_data->data;
+
+  if (buf) {
+      for (c = 0; c < s->channels; c++) {
+          for (v = 0; v < write; v++) {
+              data[v * s->channels + c] =
+                  FLOAT_TO_SHORT(buf[ v * s->channels + c]);
+          }
+      }
+  }
+  if (async) {
+    err = ExtAudioFileWriteAsync(s->audioFile, write, &s->bufferList);
+    if (err) { AUBIO_ERROR("error in ExtAudioFileWriteAsync, %d\n", (int)err); }
+  } else {
+    err = ExtAudioFileWrite(s->audioFile, write, &s->bufferList);
+    if (err) { AUBIO_ERROR("error in ExtAudioFileWrite, %d\n", (int)err); }
+  }
+  return;
+}
+
+void del_aubio_sink_apple_audio(aubio_sink_apple_audio_t * s) {
+  OSStatus err = noErr;
+  if (!s || !s->audioFile) { return; }
+  err = ExtAudioFileDispose(s->audioFile);
+  if (err) AUBIO_ERROR("error in ExtAudioFileDispose, %d\n", (int)err);
+  s->audioFile = NULL;
+  freeAudioBufferList(&s->bufferList);
+  AUBIO_FREE(s);
+  return;
+}
diff --git a/src/io/sink_apple_audio.h b/src/io/sink_apple_audio.h
new file mode 100644 (file)
index 0000000..5403fa2
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+  Copyright (C) 2012 Paul Brossier <piem@aubio.org>
+
+  This file is part of aubio.
+
+  aubio is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  aubio is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with aubio.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef _AUBIO_SINK_APPLE_AUDIO_H
+#define _AUBIO_SINK_APPLE_AUDIO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** \file
+
+  Apple Audio Media
+
+*/
+
+typedef struct _aubio_sink_apple_audio_t aubio_sink_apple_audio_t;
+aubio_sink_apple_audio_t * new_aubio_sink_apple_audio(char_t * method, uint_t samplerate);
+void aubio_sink_apple_audio_do(aubio_sink_apple_audio_t * s, fvec_t * write_data, uint_t write);
+void del_aubio_sink_apple_audio(aubio_sink_apple_audio_t * s);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _AUBIO_SINK_APPLE_AUDIO_H */
index 475838c5f87ddc3131fe7020f2d4bb4af0ba42ca..e5dede1cfaef5700b782f3a8dfc0fd9f491d140d 100644 (file)
@@ -24,8 +24,6 @@
 #include "fvec.h"
 #include "io/source_apple_audio.h"
 
-// CFURLRef, CFURLCreateWithFileSystemPath, ...
-#include <CoreFoundation/CoreFoundation.h>
 // ExtAudioFileRef, AudioStreamBasicDescription, AudioBufferList, ...
 #include <AudioToolbox/AudioToolbox.h>
 
@@ -44,13 +42,12 @@ struct _aubio_source_apple_audio_t {
   char_t *path;
 
   ExtAudioFileRef audioFile;
-  AudioStreamBasicDescription fileFormat;
   AudioBufferList bufferList;
 };
 
-static int createAubioBufferList(AudioBufferList *bufferList, int channels, int segmentSize);
-static void freeAudioBufferList(AudioBufferList *bufferList);
-static CFURLRef getURLFromPath(const char * path);
+extern int createAubioBufferList(AudioBufferList *bufferList, int channels, int segmentSize);
+extern void freeAudioBufferList(AudioBufferList *bufferList);
+extern CFURLRef getURLFromPath(const char * path);
 
 aubio_source_apple_audio_t * new_aubio_source_apple_audio(char_t * path, uint_t samplerate, uint_t block_size)
 {
@@ -95,8 +92,9 @@ aubio_source_apple_audio_t * new_aubio_source_apple_audio(char_t * path, uint_t
   // set the client format description
   err = ExtAudioFileSetProperty(s->audioFile, kExtAudioFileProperty_ClientDataFormat,
       propSize, &clientFormat);
-  if (err) { fprintf(stderr, "error in ExtAudioFileSetProperty, %d\n", (int)err); goto beach;}
+  if (err) { AUBIO_ERROR("error in ExtAudioFileSetProperty, %d\n", (int)err); goto beach;}
 
+#if 0
   // print client and format descriptions
   AUBIO_DBG("Opened %s\n", s->path);
   AUBIO_DBG("file/client Format.mFormatID:        : %3c%c%c%c / %c%c%c%c\n",
@@ -112,6 +110,7 @@ aubio_source_apple_audio_t * new_aubio_source_apple_audio(char_t * path, uint_t
   AUBIO_DBG("file/client Format.mBytesPerFrame    : %6d / %d\n",    (int)fileFormat.mBytesPerFrame   , (int)clientFormat.mBytesPerFrame);
   AUBIO_DBG("file/client Format.mBytesPerPacket   : %6d / %d\n",    (int)fileFormat.mBytesPerPacket  , (int)clientFormat.mBytesPerPacket);
   AUBIO_DBG("file/client Format.mReserved         : %6d / %d\n",    (int)fileFormat.mReserved        , (int)clientFormat.mReserved);
+#endif
 
   // compute the size of the segments needed to read the input file
   UInt32 samples = s->block_size * clientFormat.mChannelsPerFrame;
@@ -165,35 +164,6 @@ beach:
   return;
 }
 
-static int createAubioBufferList(AudioBufferList * bufferList, int channels, int segmentSize) {
-  bufferList->mNumberBuffers = 1;
-  bufferList->mBuffers[0].mNumberChannels = channels;
-  bufferList->mBuffers[0].mData = (short *)malloc(segmentSize * sizeof(short));
-  bufferList->mBuffers[0].mDataByteSize = segmentSize * sizeof(short);
-  return 0;
-}
-
-static void freeAudioBufferList(AudioBufferList *bufferList) {
-  UInt32 i = 0;
-  if (!bufferList) return;
-  for (i = 0; i < bufferList->mNumberBuffers; i++) {
-    if (bufferList->mBuffers[i].mData) {
-      free (bufferList->mBuffers[i].mData);
-      bufferList->mBuffers[i].mData = NULL;
-    }
-  }
-  bufferList = NULL;
-}
-
-static CFURLRef getURLFromPath(const char * path) {
-  CFStringRef cfTotalPath = CFStringCreateWithCString (kCFAllocatorDefault,
-      path, kCFStringEncodingUTF8);
-
-  return CFURLCreateWithFileSystemPath(kCFAllocatorDefault, cfTotalPath,
-      kCFURLPOSIXPathStyle, false);
-}
-
-
 void del_aubio_source_apple_audio(aubio_source_apple_audio_t * s){
   OSStatus err = noErr;
   if (!s || !s->audioFile) { return; }
diff --git a/src/io/utils_apple_audio.c b/src/io/utils_apple_audio.c
new file mode 100644 (file)
index 0000000..dbd1fbd
--- /dev/null
@@ -0,0 +1,40 @@
+#ifdef __APPLE__
+
+// CFURLRef, CFURLCreateWithFileSystemPath, ...
+#include <CoreFoundation/CoreFoundation.h>
+// ExtAudioFileRef, AudioStreamBasicDescription, AudioBufferList, ...
+#include <AudioToolbox/AudioToolbox.h>
+
+int createAubioBufferList(AudioBufferList *bufferList, int channels, int segmentSize);
+void freeAudioBufferList(AudioBufferList *bufferList);
+CFURLRef getURLFromPath(const char * path);
+
+int createAubioBufferList(AudioBufferList * bufferList, int channels, int segmentSize) {
+  bufferList->mNumberBuffers = 1;
+  bufferList->mBuffers[0].mNumberChannels = channels;
+  bufferList->mBuffers[0].mData = (short *)malloc(segmentSize * sizeof(short));
+  bufferList->mBuffers[0].mDataByteSize = segmentSize * sizeof(short);
+  return 0;
+}
+
+void freeAudioBufferList(AudioBufferList *bufferList) {
+  UInt32 i = 0;
+  if (!bufferList) return;
+  for (i = 0; i < bufferList->mNumberBuffers; i++) {
+    if (bufferList->mBuffers[i].mData) {
+      free (bufferList->mBuffers[i].mData);
+      bufferList->mBuffers[i].mData = NULL;
+    }
+  }
+  bufferList = NULL;
+}
+
+CFURLRef getURLFromPath(const char * path) {
+  CFStringRef cfTotalPath = CFStringCreateWithCString (kCFAllocatorDefault,
+      path, kCFStringEncodingUTF8);
+
+  return CFURLCreateWithFileSystemPath(kCFAllocatorDefault, cfTotalPath,
+      kCFURLPOSIXPathStyle, false);
+}
+
+#endif /* __APPLE__ */