I have been unable to get any of the Core Audio write functions to write data to a sound file. I can read files, view the samples (they are correct), and create a new file with the correct format settings. The write functions do not return any errors, but they fail to write data to the file. I have been struggling with this for a few days and am hoping someone can help. Below is a very simple example. I'm just opening a 16-bit/44.1kHz aiff file and writing it to a new file (no conversions, no processing). What am I doing wrong here?
- (void)saveAudioFileToPath: (NSString*)str
{
ExtAudioFileRef infile, outfile;
OSStatus theErr = noErr;
CFStringRef inPath = CFStringCreateWithCString(NULL,
[str cStringUsingEncoding:NSUTF8StringEncoding],
kCFStringEncodingMacRoman );
CFURLRef inFileURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
inPath,
kCFURLPOSIXPathStyle,
false );
CFStringRef outPath = CFStringCreateWithCString(NULL,
"/Users/home/soundfile.aif", /
kCFStringEncodingMacRoman );
CFURLRef outFileURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
outPath,
kCFURLPOSIXPathStyle,
false );
theErr = ExtAudioFileOpenURL (inFileURL, &infile);
CheckError(theErr,"Error in saveAudioFileToPath: calling ExtAudioFileOpenURL()");
AudioStreamBasicDescription inFormat = {0};
UInt32 size = sizeof(inFormat);
theErr = ExtAudioFileGetProperty(infile,
kExtAudioFileProperty_FileDataFormat,
&size,
&inFormat);
CheckError(theErr,"Error in saveAudioFileToPath: calling ExtAudioFileGetProperty()");
SInt64 totalNumFrames = 0;
size = sizeof(totalNumFrames);
theErr = ExtAudioFileGetProperty(infile,
kExtAudioFileProperty_FileLengthFrames,
&size,
&totalNumFrames);
CheckError(theErr,"Error in saveAudioFileToPath: calling ExtAudioFileGetProperty()");
SInt16 *audioData = calloc(totalNumFrames, sizeof(SInt16));
AudioBufferList fillBufList;
UInt32 numFrames = (UInt32)totalNumFrames;
while (1) {
fillBufList.mNumberBuffers = 1;
fillBufList.mBuffers[0].mNumberChannels = inFormat.mChannelsPerFrame;
fillBufList.mBuffers[0].mDataByteSize = (UInt32)totalNumFrames * sizeof(SInt16);
fillBufList.mBuffers[0].mData = audioData;
theErr = ExtAudioFileRead (infile, &numFrames, &fillBufList);
CheckError(theErr,"Error in saveAudioFileToPath: calling ExtAudioFileRead()");
if (!numFrames) {
break;
}
}
SInt16 *ptr = fillBufList.mBuffers[0].mData;
SInt16 s;
for(int k = 0; k < numFrames; k++) {
s = CFSwapInt16BigToHost(*ptr);
ptr++;
}
AudioStreamBasicDescription outFormat = {0};
outFormat = inFormat;
outFormat.mReserved = 0;
theErr = ExtAudioFileCreateWithURL (outFileURL,
kAudioFileAIFFType,
&outFormat, NULL,
kAudioFileFlags_EraseFile,
&outfile);
CheckError(theErr,"Error in saveAudioFileToPath: calling ExtAudioFileCreateWithURL()");
size = sizeof(outFormat);
theErr = ExtAudioFileSetProperty(infile,
kExtAudioFileProperty_ClientDataFormat,
size,
&outFormat); /
CheckError(theErr,"Error in saveAudioFileToPath: calling ExtAudioFileSetProperty()");
while(1) {
theErr = ExtAudioFileWrite(outfile, numFrames, &fillBufList);
CheckError(theErr,"Error in saveAudioFileToPath: calling ExtAudioFileWrite()");
if (!numFrames) {
/
break;
}
}
ExtAudioFileDispose(infile);
ExtAudioFileDispose(outfile);
free(audioData);
return;
}
Just to clarify, despite the method name, the string being passed into the method is actually the path to the input file. The path to the output file is hard-coded in the method itself. This is a result of me ripping the code apart as I try to get this working. I also want to add that I'm trying to read very short files so this is why the buffer size is the entire length of the file. I have also tried using a smaller buffer and reading the file in fragments with code copied directly from the AudioToolboxConverter sample code... same issue. I have also tried using Audio File Services functions instead of Extended Audio File Services... same issue. I'm wondering if the problem could be something other than Core Audio. I have App Sandboxing off in xCode and so I'm not doing anything with entitlements. Those aren't necessary with Sandboxing off, right? Plus, I am able to create a file and write to it using standard C file io from this same application.