File: programming/cocoa/UKSoundFileRecorder.zip/UKSoundFileRecorder/UKSoundFileRecorder/UKSoundFileRecorder.m


//
//  UKSoundFileRecorder.m
//  UKSoundFileRecorder
//
//  Created by Uli Kusterer on 14.07.07.
//  Copyright 2007 M. Uli Kusterer. All rights reserved.
//
 
// -----------------------------------------------------------------------------
//	Headers:
// -----------------------------------------------------------------------------
 
#import "UKSoundFileRecorder.h"
#import "NSString+CarbonUtilities.h"
#import <sys/param.h>	// for MAX().
 
 
// -----------------------------------------------------------------------------
//	Private method prototypes:
// -----------------------------------------------------------------------------
// Returns error string, NIL on success.
// Returns error string, NIL on success.
// -----------------------------------------------------------------------------
//	defaultOutputFormat:
//		Returns a dictionary containing our default output format for the sound
//		data. This is what you get if you don't call setOutputFormat:.
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//	* DESIGNATED INITIALIZER:
// -----------------------------------------------------------------------------
// Apply a sensible default.
// -----------------------------------------------------------------------------
//	* CONVENIENCE INITIALIZER:
// -----------------------------------------------------------------------------
// SELF, not SUPER! We want the rest of the init to happen regularly.
// -----------------------------------------------------------------------------
//	* DESTRUCTOR:
// -----------------------------------------------------------------------------
// cleanUp calls stop, which may throw.
"[UKSoundFileRecorder dealloc]: Ignoring exception during clean-up. %@ : %@"// -----------------------------------------------------------------------------
//	Delegate accessors:
// -----------------------------------------------------------------------------
// Don't retain delegate, it's very likely our owner. Wouldn't want a retain circle!
// -----------------------------------------------------------------------------
//	AudioInputProc:
//		Callback function that is called by the audio unit on its high-priority
//		thread when we have sound input. Here's where we write out the data
//		to the file. Try not to do too much here.
// -----------------------------------------------------------------------------
// Render into audio buffer
"AudioUnitRender() failed with error %i\n", err );
	
	// Write to file, ExtAudioFile auto-magicly handles conversion/encoding
	// NOTE: Async writes may not be flushed to disk until a the file
	// reference is disposed using ExtAudioFileDispose
'\0'"ExtAudioFileWrite FAILED! %d '%-4.4s'\n"// Don't waste time syncing to other threads if nobody is listening:
// Used by our AudioInputProc to easily call this delegate method from another thread:
// In case we queued one up but were already finished by the time it got executed.
// -----------------------------------------------------------------------------
//	outputFilePath Accessors:
//		The file at outputFilePath mustn't exist yet.
// -----------------------------------------------------------------------------
"outputFilePath"// Make sure we recreate our objects for the new format.
"outputFilePath"// Handy method for hooking up this object to a text field:
// -----------------------------------------------------------------------------
//	outputFormat Accessors:
// -----------------------------------------------------------------------------
"UKSoundFileRecorderBusyRecording""Can't change output format when recording has already started."// Make sure we recreate our objects for the new format.
// -----------------------------------------------------------------------------
//	prepare:
//		Set up all the CoreAudio magic that makes this work.
// -----------------------------------------------------------------------------
"UKSoundFileRecorderCantPrepare""%@.", errStr];
	}
}
 
 
// -----------------------------------------------------------------------------
//	isRecording accessor:
//		Returns YES if we are currently recording, NO otherwise.
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//	start:
//		Start recording sound, like, right now.
// -----------------------------------------------------------------------------
// Start pulling audio data:
"isRecording""isRecording""UKSoundFileRecorderCantStart""Could not start recording (ID=%d)", err];
}
 
 
// -----------------------------------------------------------------------------
//	stop:
//		Stop recording sound and flush the file to disk.
// -----------------------------------------------------------------------------
// Stop pulling audio data
"UKSoundFileRecorderCantStop""Could not stop recording (ID=%d)""isRecording""isRecording"// Make sure file gets flushed to disk.
// Make sure Finder updates file size.
// -----------------------------------------------------------------------------
//	cleanUp:
//		Called in various places, but also in the destructor, to tear down our
//		CoreAudio stuff. This also causes the file to be written to disk.
//		This is essentially the opposite to -prepare.
// -----------------------------------------------------------------------------
// Stop pulling audio data.
// Dispose our audio file reference.
	// Also responsible for flushing async data to disk.
// -----------------------------------------------------------------------------
//	setupAudioFile:
//		Init our ExtAudioFileRef object so it writes the correct kind of audio
//		to the correct file system location.
//		
//		Returns NIL on success, an error string on failure.
// -----------------------------------------------------------------------------
"Could not get reference to directory \"%@\""// Have an audio file already? Get rid of that.
// Create new MP4 file (kAudioFileM4AType)
'\0'"Could not create the audio file (ID=%d/'%-4.4s')"// Inform the file what format the data is we're going to give it, should be pcm
	// You must set this in order to encode or decode a non-PCM file data format.
'\0'"Could not set up data format for output file (ID=%d/'%-4.4s')"// If we're recording from a mono source, setup a simple channel map to split to stereo
// Get the underlying AudioConverterRef
// This should be as large as the number of output channels,
			// each element specifies which input channel's data is routed to that output channel
// Initialize async writes thus preparing it for IO
'\0'"Could not initialize asynchronous writing (ID=%d/'%-4.4s')"// -----------------------------------------------------------------------------
//	configureAU:
//		Create our Audio Unit that gives us data from the microphone.
//		
//		Returns NIL on success, an error string on failure.
// -----------------------------------------------------------------------------
// Open the AudioOutputUnit
	// There are several different types of Audio Units.
	// Some audio units serve as Outputs, Mixers, or DSP
	// units. See AUComponent.h for listing
"Couldn't open AudioUnit component (ID=%d)", err];
		}
	}
 
	// Configure the AudioOutputUnit
	// You must enable the Audio Unit (AUHAL) for input and output for the same  device.
	// When using AudioUnitSetProperty the 4th parameter in the method
	// refers to an AudioUnitElement.  When using an AudioOutputUnit
	// for input the element will be '1' and the output element will be '0'.	
	
	// Enable input on the AUHAL
// Disable Output on the AUHAL
"Couldn't set EnableIO property on the audio unit (ID=%d)", err];
		}
	}
 
	// Select the default input device
"Couldn't get default input device (ID=%d)", err];
	}
	
	// Set the current device to the default input unit.
"Failed to hook up input device to our AudioUnit (ID=%d)", err];
	}
	
	// Setup render callback
	// This will be called when the AUHAL has input data
"Could not install render callback on our AudioUnit (ID=%d)", err];
	}
	
	// get hardware device format
"Could not install render callback on our AudioUnit (ID=%d)", err];
	}
	
	// Twiddle the format to our liking
#if __BIG_ENDIAN__
#endif
// Set the AudioOutputUnit output data format
"Could not change the stream format of the output device (ID=%d)", err];
	}
	
	// Get the number of frames in the IO buffer(s)
"Could not determine audio sample size (ID=%d)", err];
	}
	
	// Initialize the AU
"Could not initialize the AudioUnit (ID=%d)", err];
	}
	
	// Allocate our audio buffers
"Could not allocate buffers for recording (ID=%d)"// -----------------------------------------------------------------------------
//	allocateAudioBufferListWithNumChannels:size:
//		Create our audio buffer list. A buffer list is the storage we use in
//		our AudioInputProc to get the sound data and hand it on to the sound
//		file writer.
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//	destroyAudioBufferList:size:
//		Dispose of our audio buffer list. A buffer list is the storage we use in
//		our AudioInputProc to get the sound data and hand it on to the sound
//		file writer.
// -----------------------------------------------------------------------------
 

This code uses the PclZip Zip File reading code, which is subject to the GNU LGPL. It also uses the GeSHi syntax highlighter, subject to the GPL. Ask if you want this for your own web site, it's free.