thanks for the response. I will consider a convenience function. When you write convenience functions such as one like that, do you use it across multiple projects? If so, do you do anything to facilitate that? Just create a .c,.h and import the headers wherever? just curious. So I was finally able to get the audio file to write the data. I played back the file in finder and heard my voice sound checking and it was glorious.
I got it to work by changing the file type enum to CAF. I guess that my ASBD was not compatible with a wav file format although i'm not certain about that. Here was what I was using with wav and am now successfully passing in as the inStreamDesc when creating the ExtAudioFile.
// asbd for audiofile
AudioStreamBasicDescription fmt;
fmt.mSampleRate = 44100.0;
fmt.mFormatID = kAudioFormatLinearPCM;
fmt.mFormatFlags = kAudioFormatFlagIsBigEndian | kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
fmt.mBytesPerPacket = 4;
fmt.mFramesPerPacket = 1;
fmt.mBytesPerFrame = 4;
fmt.mChannelsPerFrame = 2;
My guess is that there is something in this that isn't compatible with the wav file formatting structure. Still, it'd be nice not to have to construct this at all. Passing in a reference to the audio stream that I have in my struct (which comes from the audio unit) also results in a fmt? error. That stream is obtained like so:
// set sample rate between input and output scopes equal and assign stream to player struct
propertySize = sizeof (AudioStreamBasicDescription);
CheckError(AudioUnitGetProperty(player->inputUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output,
inputBus,
&player->streamFormat,
&propertySize), "Couldn't get ASBD from input unit");
AudioStreamBasicDescription deviceFormat;
CheckError(AudioUnitGetProperty(player->inputUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
inputBus,
&deviceFormat,
&propertySize), "Couldn't get ASBD from input unit");
player->streamFormat.mSampleRate = deviceFormat.mSampleRate;
propertySize = sizeof (AudioStreamBasicDescription);
CheckError(AudioUnitSetProperty(player->inputUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output,
inputBus,
&player->streamFormat,
propertySize), "Couldn't set ASBD on input unit");
I'm sure there is something in that as well that is not capable with the wav format. Anyway, CAF files are suitable for now. I would still like to know why WAV was such an issue.
fmt.mBitsPerChannel = 16;
On Thu, Jan 14, 2016 at 9:53 PM Christian Rober <
email@hidden> wrote:
Alexander,
Let's definitely try to resolve that error first... If you are getting that error from ExtAudioFileCreateWithURL then my guess is that the ASBD you are passing in does not match the enum type you are also passing in. In other words, if you pass kAudioFileWAVEType to the create function, then your ASBD should probably look something like this:
{
AudioStreamBasicDescription streamDescription = {0};
Float64 sampleRate = 44100;
int channels = 2; // Do you want Stereo?
streamDescription.mSampleRate = sampleRate;
streamDescription.mFormatID = kAudioFormatLinearPCM;
streamDescription.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
streamDescription.mBytesPerPacket = 4;
streamDescription.mFramesPerPacket = 1;
streamDescription.mBytesPerFrame = 4;
streamDescription.mChannelsPerFrame = channels;
streamDescription.mBitsPerChannel = 16;
}
That is just one way to do it (bordering on too manual IMO). I thought there were handy MACROS for this in the SDK but maybe I am conflating that with something else...
Minor related suggestion: consider creating this ASBD as a return value from a static function, it may be handy in the future... it was for me.
Lastly, and just for completeness: In terms of the client property, it should probably match the audio buffers you intend to pass into the WriteAsync functions and not necessarily the format of the WAV file itself. In your snippet you seem to be re-using the ASBD, which may not always apply.