Changes in src/io/sink_apple_audio.c [cf387e3:99365e9]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/io/sink_apple_audio.c
rcf387e3 r99365e9 32 32 #include <AudioToolbox/AudioToolbox.h> 33 33 34 #define FLOAT_TO_SHORT(x) (short)(x * 32768) 35 36 extern int createAubioBufferList(AudioBufferList *bufferList, int channels, int segmentSize); 34 extern int createAudioBufferList(AudioBufferList *bufferList, int channels, int segmentSize); 37 35 extern void freeAudioBufferList(AudioBufferList *bufferList); 38 36 extern CFURLRef createURLFromPath(const char * path); … … 40 38 41 39 uint_t aubio_sink_apple_audio_open(aubio_sink_apple_audio_t *s); 40 41 uint_t aubio_str_extension_matches(const char_t *ext, 42 const char_t *pattern); 43 const char_t *aubio_str_get_extension(const char_t *filename); 42 44 43 45 #define MAX_SIZE 4096 // the maximum number of frames that can be written at a time … … 55 57 ExtAudioFileRef audioFile; 56 58 bool async; 59 AudioFileTypeID fileType; 57 60 }; 58 61 … … 73 76 s->channels = 0; 74 77 78 aubio_sink_apple_audio_preset_format(s, aubio_str_get_extension(uri)); 79 75 80 // zero samplerate given. do not open yet 76 81 if ((sint_t)samplerate == 0) { 77 82 return s; 78 83 } 84 79 85 // invalid samplerate given, abort 80 86 if (aubio_io_validate_samplerate("sink_apple_audio", s->path, samplerate)) { … … 122 128 } 123 129 130 uint_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 AUBIO_WRN("sink_apple_audio: could not guess format for %s," 147 " using default (wav)\n", s->path); 148 s->fileType = kAudioFileWAVEType; 149 return AUBIO_FAIL; 150 } 151 return AUBIO_OK; 152 } 153 154 static void aubio_sink_apple_audio_set_client_format(aubio_sink_apple_audio_t* s, 155 AudioStreamBasicDescription *clientFormat) 156 { 157 memset(clientFormat, 0, sizeof(AudioStreamBasicDescription)); 158 // always set samplerate and channels first 159 clientFormat->mSampleRate = (Float64)(s->samplerate); 160 clientFormat->mChannelsPerFrame = s->channels; 161 162 switch (s->fileType) { 163 case kAudioFileM4AType: 164 clientFormat->mFormatID = kAudioFormatAppleLossless; 165 break; 166 case kAudioFileMPEG4Type: 167 clientFormat->mFormatID = kAudioFormatMPEG4AAC; 168 clientFormat->mFormatFlags = kMPEG4Object_AAC_Main; 169 clientFormat->mFormatFlags |= kAppleLosslessFormatFlag_16BitSourceData; 170 clientFormat->mFramesPerPacket = 1024; 171 break; 172 case kAudioFileWAVEType: 173 clientFormat->mFormatID = kAudioFormatLinearPCM; 174 clientFormat->mFormatFlags = kAudioFormatFlagIsSignedInteger; 175 clientFormat->mFormatFlags |= kAudioFormatFlagIsPacked; 176 clientFormat->mBitsPerChannel = sizeof(short) * 8; 177 clientFormat->mFramesPerPacket = 1; 178 clientFormat->mBytesPerFrame = clientFormat->mBitsPerChannel * clientFormat->mChannelsPerFrame / 8; 179 clientFormat->mBytesPerPacket = clientFormat->mFramesPerPacket * clientFormat->mBytesPerFrame; 180 break; 181 case kAudioFileAIFFType: 182 clientFormat->mFormatID = kAudioFormatLinearPCM; 183 clientFormat->mFormatFlags = kAudioFormatFlagIsSignedInteger; 184 clientFormat->mFormatFlags |= kAudioFormatFlagIsPacked; 185 clientFormat->mFormatFlags |= kAudioFormatFlagIsBigEndian; 186 clientFormat->mBitsPerChannel = sizeof(short) * 8; 187 clientFormat->mFramesPerPacket = 1; 188 clientFormat->mBytesPerFrame = clientFormat->mBitsPerChannel * clientFormat->mChannelsPerFrame / 8; 189 clientFormat->mBytesPerPacket = clientFormat->mFramesPerPacket * clientFormat->mBytesPerFrame; 190 break; 191 default: 192 break; 193 } 194 } 195 124 196 uint_t aubio_sink_apple_audio_get_samplerate(const aubio_sink_apple_audio_t *s) 125 197 { … … 136 208 if (s->samplerate == 0 || s->channels == 0) return AUBIO_FAIL; 137 209 138 AudioStreamBasicDescription clientFormat;139 memset(&clientFormat, 0, sizeof(AudioStreamBasicDescription));140 clientFormat.mFormatID = kAudioFormatLinearPCM;141 clientFormat.mSampleRate = (Float64)(s->samplerate);142 clientFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;143 clientFormat.mChannelsPerFrame = s->channels;144 clientFormat.mBitsPerChannel = sizeof(short) * 8;145 clientFormat.mFramesPerPacket = 1;146 clientFormat.mBytesPerFrame = clientFormat.mBitsPerChannel * clientFormat.mChannelsPerFrame / 8;147 clientFormat.mBytesPerPacket = clientFormat.mFramesPerPacket * clientFormat.mBytesPerFrame;148 clientFormat.mReserved = 0;149 150 AudioFileTypeID fileType = kAudioFileWAVEType;151 210 CFURLRef fileURL = createURLFromPath(s->path); 152 211 bool overwrite = true; 212 213 // set the in-memory format 214 AudioStreamBasicDescription inputFormat; 215 memset(&inputFormat, 0, sizeof(AudioStreamBasicDescription)); 216 inputFormat.mFormatID = kAudioFormatLinearPCM; 217 inputFormat.mSampleRate = (Float64)(s->samplerate); 218 inputFormat.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked; 219 inputFormat.mChannelsPerFrame = s->channels; 220 inputFormat.mBitsPerChannel = sizeof(smpl_t) * 8; 221 inputFormat.mFramesPerPacket = 1; 222 inputFormat.mBytesPerFrame = inputFormat.mBitsPerChannel * inputFormat.mChannelsPerFrame / 8; 223 inputFormat.mBytesPerPacket = inputFormat.mFramesPerPacket * inputFormat.mBytesPerFrame; 224 225 // get the in-file format 226 AudioStreamBasicDescription clientFormat; 227 aubio_sink_apple_audio_set_client_format(s, &clientFormat); 228 153 229 OSStatus err = noErr; 154 err = ExtAudioFileCreateWithURL(fileURL, fileType, &clientFormat, NULL,230 err = ExtAudioFileCreateWithURL(fileURL, s->fileType, &clientFormat, NULL, 155 231 overwrite ? kAudioFileFlags_EraseFile : 0, &s->audioFile); 156 232 CFRelease(fileURL); … … 162 238 goto beach; 163 239 } 164 if (createAubioBufferList(&s->bufferList, s->channels, s->max_frames * s->channels)) { 240 241 #if defined(kAppleSoftwareAudioCodecManufacturer) 242 // on iOS, set software based encoding before setting clientDataFormat 243 UInt32 codecManf = kAppleSoftwareAudioCodecManufacturer; 244 err = ExtAudioFileSetProperty(s->audioFile, 245 kExtAudioFileProperty_CodecManufacturer, 246 sizeof(UInt32), &codecManf); 247 if (err) { 248 char_t errorstr[20]; 249 AUBIO_ERR("sink_apple_audio: error when trying to set sofware codec on %s " 250 "(%s)\n", s->path, getPrintableOSStatusError(errorstr, err)); 251 goto beach; 252 } 253 #endif 254 255 err = ExtAudioFileSetProperty(s->audioFile, 256 kExtAudioFileProperty_ClientDataFormat, 257 sizeof(AudioStreamBasicDescription), &inputFormat); 258 if (err) { 259 char_t errorstr[20]; 260 AUBIO_ERR("sink_apple_audio: error when trying to set output format on %s " 261 "(%s)\n", s->path, getPrintableOSStatusError(errorstr, err)); 262 goto beach; 263 } 264 265 if (createAudioBufferList(&s->bufferList, s->channels, s->max_frames * s->channels)) { 165 266 AUBIO_ERR("sink_apple_audio: error when creating buffer list for %s, " 166 267 "out of memory? \n", s->path); … … 175 276 void aubio_sink_apple_audio_do(aubio_sink_apple_audio_t * s, fvec_t * write_data, uint_t write) { 176 277 UInt32 c, v; 177 s hort *data = (short*)s->bufferList.mBuffers[0].mData;278 smpl_t *data = (smpl_t*)s->bufferList.mBuffers[0].mData; 178 279 uint_t length = aubio_sink_validate_input_length("sink_apple_audio", s->path, 179 280 s->max_frames, write_data->length, write); … … 181 282 for (c = 0; c < s->channels; c++) { 182 283 for (v = 0; v < length; v++) { 183 data[v * s->channels + c] = FLOAT_TO_SHORT(write_data->data[v]);284 data[v * s->channels + c] = write_data->data[v]; 184 285 } 185 286 } … … 190 291 void aubio_sink_apple_audio_do_multi(aubio_sink_apple_audio_t * s, fmat_t * write_data, uint_t write) { 191 292 UInt32 c, v; 192 s hort *data = (short*)s->bufferList.mBuffers[0].mData;293 smpl_t *data = (smpl_t*)s->bufferList.mBuffers[0].mData; 193 294 uint_t channels = aubio_sink_validate_input_channels("sink_apple_audio", 194 295 s->path, s->channels, write_data->height); … … 198 299 for (c = 0; c < channels; c++) { 199 300 for (v = 0; v < length; v++) { 200 data[v * s->channels + c] = FLOAT_TO_SHORT(write_data->data[c][v]);301 data[v * s->channels + c] = write_data->data[c][v]; 201 302 } 202 303 } … … 207 308 void aubio_sink_apple_audio_write(aubio_sink_apple_audio_t *s, uint_t write) { 208 309 OSStatus err = noErr; 310 // set mDataByteSize to match the number of frames to be written 311 // see https://www.mail-archive.com/coreaudio-api@lists.apple.com/msg01109.html 312 s->bufferList.mBuffers[0].mDataByteSize = write * s->channels 313 * sizeof(smpl_t); 209 314 if (s->async) { 210 315 err = ExtAudioFileWriteAsync(s->audioFile, write, &s->bufferList);
Note: See TracChangeset
for help on using the changeset viewer.