### To play *.pcm file from Jiarong
1. play system sound
* 9:50 am. can play system sound now. ( 1:30 hours )
Summary:
# must have a "-" for methods
# adding a resources file ( tap.cif ) to projet
# adding a framework ( AudioBoxTool.framework ) to project
2. let SpeakHere to play *.pcm file
Q: Can *.pcm be handled directly ? or should it be handled via a *.caf file ?
Used *.pcm to replace *.caf file.
Seems crash in the AQBufferCallBack method on the following statement:
OSStatus result =AudioFileReadPackets(THIS->GetAudioFileID(),false, &numBytes, inCompleteAQBuffer->mPacketDescriptions, THIS->GetCurrentPacket(), &nPackets,
EXC_BAD_ACCESS !
NOTE:可能Audio File Services并不支持*.pcm文件
enum { kAudioFileAIFFType = 'AIFF', kAudioFileAIFCType = 'AIFC', kAudioFileWAVEType = 'WAVE', kAudioFileSoundDesigner2Type = 'Sd2f', kAudioFileNextType = 'NeXT', kAudioFileMP3Type = 'MPG3', kAudioFileMP2Type = 'MPG2', kAudioFileMP1Type = 'MPG1', kAudioFileAC3Type = 'ac-3', kAudioFileAAC_ADTSType = 'adts', kAudioFileMPEG4Type = 'mp4f', kAudioFileM4AType = 'm4af', kAudioFileCAFType = 'caff', kAudioFile3GPType = '3gpp', kAudioFile3GP2Type = '3gp2', kAudioFileAMRType = 'amrf' };
3. read "Audio Queue Services Programming Guide ".
* Audio Queue Services ---- a C programming interface
* Audio Queue composition
audio data buffers
buffer queue - an ordered list of audio data buffers
callbacks
* Audio Queue buffers
typedef struct AudioQueueBuffer {
mAudioDataBytesCapacity;
mAudioDataByteSize;
void } AudioQueueBuffer;
typedef AudioQueueBuffer *AudioQueueBufferRef;
Note: a queue could have N buffers, but 3 for most cases.
* Codec and Audio Data Format
ASBD.mFormatID = determines the Codec automatically.
* setting up parameters for audio
format id ( codec )
sample rate
channel count
Q: the callback does not need to know the format ? I doubt it !
* Audio Queue contral and state
Q: AudioQueuePrime ??? Why not used in SpeakHere sample code ?
Q: magic cookies ?
* playing audio steps
1.Define a custom structure to manage state, format, and path information.
2.Write an audio queue callback function to perform the actual playback.
3.Write code to determine a good size for the audio queue buffers.
4.Open an audio file for playback and determine its audio data format.
5.Create a playback audio queue and configure it for playback.
6.Allocate and enqueue audio queue buffers. Tell the audio queue to start playing. When done, the playback callback tells the audio queue to stop.
7.Dispose of the audio queue. Release resources.
* get audio data format
UInt32 dataFormatSize = sizeof (aqData.mDataFormat);//1
AudioFileGetProperty (//2
aqData.mAudioFile,//3
kAudioFilePropertyDataFormat,//4
&dataFormatSize,//5
&aqData.mDataFormat//6
);
Note: the data format information is read from the audio file itself, rather than configured manually.
* run the audio queue loop
do { CFRunLoopRunInMode (
kCFRunLoopDefaultMode, 0.25, false
); } while (aqData.mIsRunning);
CFRunLoopRunInMode ( kCFRunLoopDefaultMode, 1, false
);
Q: What's this run loop stuff ???
4. Understanding SpeakHere
Q: where is the recording file specified ?
A: in stopRecord() action method:
- (void)stopRecord
{
// Disconnect our level meter from the audio queue
[lvlMeter_insetAq:nil];
recorder->StopRecord();
// dispose the previous playback queue
player->DisposeQueue(true);
// now create a new queue for the recorded file
recordFilePath = (CFStringRef)[NSTemporaryDirectory()stringByAppendingPathComponent:@"recordedFile.caf"];
player->CreateQueueForFile(recordFilePath);
// Set the button's state back to "record"
btn_record.title = @"Record";
btn_play.enabled = YES;
}