Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/io/sink_apple_audio.c

    r7b5e1a5 r00c9444  
    3939uint_t aubio_sink_apple_audio_open(aubio_sink_apple_audio_t *s);
    4040
     41uint_t aubio_str_extension_matches(const char_t *ext,
     42    const char_t *pattern);
     43const char_t *aubio_str_get_extension(const char_t *filename);
     44
    4145#define MAX_SIZE 4096 // the maximum number of frames that can be written at a time
    4246
     
    5357  ExtAudioFileRef audioFile;
    5458  bool async;
     59  AudioFileTypeID fileType;
    5560};
    5661
     
    7176  s->channels = 0;
    7277
     78  aubio_sink_apple_audio_preset_format(s, aubio_str_get_extension(uri));
     79
    7380  // zero samplerate given. do not open yet
    7481  if ((sint_t)samplerate == 0) {
     
    121128}
    122129
     130uint_t aubio_sink_apple_audio_preset_format(aubio_sink_apple_audio_t *s,
     131    const char_t *fmt)
     132{
     133  if (aubio_str_extension_matches(fmt, "wav")) {
     134    s->fileType = kAudioFileWAVEType;
     135  } else if (aubio_str_extension_matches(fmt, "m4a")
     136      || aubio_str_extension_matches(fmt, "mp4") ) {
     137    // use alac for "mp4" and "m4a"
     138    s->fileType = kAudioFileM4AType;
     139  } else if (aubio_str_extension_matches(fmt, "aac") ) {
     140    // only use lossy codec for "aac"
     141    s->fileType = kAudioFileMPEG4Type;
     142  } else if (aubio_str_extension_matches(fmt, "aiff") ) {
     143    // only use lossy codec for "aac"
     144    s->fileType = kAudioFileAIFFType;
     145  } else {
     146    s->fileType = kAudioFileWAVEType;
     147    if (fmt && strnlen(fmt, PATH_MAX)) {
     148      AUBIO_WRN("sink_apple_audio: could not guess format for %s,"
     149         " using default (wav)\n", s->path);
     150      return AUBIO_FAIL;
     151    }
     152  }
     153  return AUBIO_OK;
     154}
     155
     156static void aubio_sink_apple_audio_set_client_format(aubio_sink_apple_audio_t* s,
     157    AudioStreamBasicDescription *clientFormat)
     158{
     159  memset(clientFormat, 0, sizeof(AudioStreamBasicDescription));
     160  // always set samplerate and channels first
     161  clientFormat->mSampleRate       = (Float64)(s->samplerate);
     162  clientFormat->mChannelsPerFrame = s->channels;
     163
     164  switch (s->fileType) {
     165    case kAudioFileM4AType:
     166      clientFormat->mFormatID         = kAudioFormatAppleLossless;
     167      break;
     168    case kAudioFileMPEG4Type:
     169      clientFormat->mFormatID         = kAudioFormatMPEG4AAC;
     170      clientFormat->mFormatFlags      = kMPEG4Object_AAC_Main;
     171      clientFormat->mFormatFlags     |= kAppleLosslessFormatFlag_16BitSourceData;
     172      clientFormat->mFramesPerPacket  = 1024;
     173      break;
     174    case kAudioFileWAVEType:
     175      clientFormat->mFormatID         = kAudioFormatLinearPCM;
     176      clientFormat->mFormatFlags      = kAudioFormatFlagIsSignedInteger;
     177      clientFormat->mFormatFlags     |= kAudioFormatFlagIsPacked;
     178      clientFormat->mBitsPerChannel   = sizeof(short) * 8;
     179      clientFormat->mFramesPerPacket  = 1;
     180      clientFormat->mBytesPerFrame    = clientFormat->mBitsPerChannel * clientFormat->mChannelsPerFrame / 8;
     181      clientFormat->mBytesPerPacket   = clientFormat->mFramesPerPacket * clientFormat->mBytesPerFrame;
     182      break;
     183    case kAudioFileAIFFType:
     184      clientFormat->mFormatID         = kAudioFormatLinearPCM;
     185      clientFormat->mFormatFlags      = kAudioFormatFlagIsSignedInteger;
     186      clientFormat->mFormatFlags     |= kAudioFormatFlagIsPacked;
     187      clientFormat->mFormatFlags     |= kAudioFormatFlagIsBigEndian;
     188      clientFormat->mBitsPerChannel   = sizeof(short) * 8;
     189      clientFormat->mFramesPerPacket  = 1;
     190      clientFormat->mBytesPerFrame    = clientFormat->mBitsPerChannel * clientFormat->mChannelsPerFrame / 8;
     191      clientFormat->mBytesPerPacket   = clientFormat->mFramesPerPacket * clientFormat->mBytesPerFrame;
     192      break;
     193    default:
     194      break;
     195  }
     196}
     197
    123198uint_t aubio_sink_apple_audio_get_samplerate(const aubio_sink_apple_audio_t *s)
    124199{
     
    135210  if (s->samplerate == 0 || s->channels == 0) return AUBIO_FAIL;
    136211
    137   AudioStreamBasicDescription clientFormat;
    138   memset(&clientFormat, 0, sizeof(AudioStreamBasicDescription));
    139   clientFormat.mFormatID         = kAudioFormatLinearPCM;
    140   clientFormat.mSampleRate       = (Float64)(s->samplerate);
    141   clientFormat.mFormatFlags      = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
    142   clientFormat.mChannelsPerFrame = s->channels;
    143   clientFormat.mBitsPerChannel   = sizeof(short) * 8;
    144   clientFormat.mFramesPerPacket  = 1;
    145   clientFormat.mBytesPerFrame    = clientFormat.mBitsPerChannel * clientFormat.mChannelsPerFrame / 8;
    146   clientFormat.mBytesPerPacket   = clientFormat.mFramesPerPacket * clientFormat.mBytesPerFrame;
    147   clientFormat.mReserved         = 0;
    148 
    149   AudioFileTypeID fileType = kAudioFileWAVEType;
    150212  CFURLRef fileURL = createURLFromPath(s->path);
    151213  bool overwrite = true;
     
    162224  inputFormat.mBytesPerFrame    = inputFormat.mBitsPerChannel * inputFormat.mChannelsPerFrame / 8;
    163225  inputFormat.mBytesPerPacket   = inputFormat.mFramesPerPacket * inputFormat.mBytesPerFrame;
     226
     227  // get the in-file format
     228  AudioStreamBasicDescription clientFormat;
     229  aubio_sink_apple_audio_set_client_format(s, &clientFormat);
     230
    164231  OSStatus err = noErr;
    165   err = ExtAudioFileCreateWithURL(fileURL, fileType, &clientFormat, NULL,
     232  err = ExtAudioFileCreateWithURL(fileURL, s->fileType, &clientFormat, NULL,
    166233     overwrite ? kAudioFileFlags_EraseFile : 0, &s->audioFile);
    167234  CFRelease(fileURL);
     
    173240    goto beach;
    174241  }
     242
     243#if defined(kAppleSoftwareAudioCodecManufacturer)
     244  // on iOS, set software based encoding before setting clientDataFormat
     245  UInt32 codecManf = kAppleSoftwareAudioCodecManufacturer;
     246  err = ExtAudioFileSetProperty(s->audioFile,
     247      kExtAudioFileProperty_CodecManufacturer,
     248      sizeof(UInt32), &codecManf);
     249  if (err) {
     250    char_t errorstr[20];
     251    AUBIO_ERR("sink_apple_audio: error when trying to set sofware codec on %s "
     252        "(%s)\n", s->path, getPrintableOSStatusError(errorstr, err));
     253    goto beach;
     254  }
     255#endif
    175256
    176257  err = ExtAudioFileSetProperty(s->audioFile,
Note: See TracChangeset for help on using the changeset viewer.