⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 audio.cc

📁 LastWave
💻 CC
字号:
/* This code takes an audio file and uses the FilePlayer AU to play this to the default output unit  It takes any valid audio file of any format that is understood by the AudioFile API */extern "C" {  #include "lastwave.h"  }#include <AudioToolbox/AudioToolbox.h>#include "CAXException.h"#include "CAStreamBasicDescription.h"#include "CAAudioUnit.h"void UsageString(int exitCode){//	Printf ("Usage: PlayFile /path/to/file\n");	exit(exitCode);}// helper functionsdouble PrepareFileAU (CAAudioUnit &au, CAStreamBasicDescription &fileFormat, AudioFileID audioFile);void MakeSimpleGraph (AUGraph &theGraph, CAAudioUnit &fileAU, CAStreamBasicDescription &fileFormat, AudioFileID audioFile);void PlaySoundFile (char *filename){  	AudioFileID audioFile;		const char* inputFile = filename;  	FSRef theRef;	XThrowIfError (FSPathMakeRef ((const UInt8 *)inputFile, &theRef, NULL), "FSPathMakeRef");  	XThrowIfError (AudioFileOpen (&theRef, fsRdPerm, 0, &audioFile), "AudioFileOpen");    // get the number of channels of the file	CAStreamBasicDescription fileFormat;	UInt32 propsize = sizeof(CAStreamBasicDescription);	XThrowIfError (AudioFileGetProperty(audioFile, kAudioFilePropertyDataFormat, &propsize, &fileFormat), "AudioFileGetProperty");	//	Printf ("playing file: %s\n", inputFile);//	Printf ("format: "); fileFormat.Print();      // lets set up our playing state now	AUGraph theGraph;	CAAudioUnit fileAU;    // this makes the graph, the file AU and sets it all up for playing	MakeSimpleGraph (theGraph, fileAU, fileFormat, audioFile);      // now we load the file contents up for playback before we start playing  // this has to be done the AU is initialized and anytime it is reset or uninitialized	Float64 fileDuration = PrepareFileAU (fileAU, fileFormat, audioFile);//  Printf ("file duration: %f secs\n", fileDuration);    // start playing	XThrowIfError (AUGraphStart (theGraph), "AUGraphStart");	  // sleep until the file is finished	usleep ((int)(fileDuration * 1000. * 1000.));    // lets clean up	XThrowIfError (AUGraphStop (theGraph), "AUGraphStop");	XThrowIfError (AUGraphUninitialize (theGraph), "AUGraphUninitialize");	XThrowIfError (AudioFileClose (audioFile), "AudioFileClose");	XThrowIfError (AUGraphClose (theGraph), "AUGraphClose");	}	double PrepareFileAU (CAAudioUnit &au, CAStreamBasicDescription &fileFormat, AudioFileID audioFile){	  //   // calculate the duration	UInt64 nPackets;	UInt32 propsize = sizeof(nPackets);	XThrowIfError (AudioFileGetProperty(audioFile, kAudioFilePropertyAudioDataPacketCount, &propsize, &nPackets), "kAudioFilePropertyAudioDataPacketCount");  	Float64 fileDuration = (nPackets * fileFormat.mFramesPerPacket) / fileFormat.mSampleRate;  	ScheduledAudioFileRegion rgn;	memset (&rgn.mTimeStamp, 0, sizeof(rgn.mTimeStamp));	rgn.mTimeStamp.mFlags = kAudioTimeStampSampleTimeValid;	rgn.mTimeStamp.mSampleTime = 0;	rgn.mCompletionProc = NULL;	rgn.mCompletionProcUserData = NULL;	rgn.mAudioFile = audioFile;	rgn.mLoopCount = 1;	rgn.mStartFrame = 0;	rgn.mFramesToPlay = UInt32(nPackets * fileFormat.mFramesPerPacket);    // tell the file player AU to play all of the file	XThrowIfError (au.SetProperty (kAudioUnitProperty_ScheduledFileRegion,                                  kAudioUnitScope_Global, 0,&rgn, sizeof(rgn)), "kAudioUnitProperty_ScheduledFileRegion");	  // prime the fp AU with default values	UInt32 defaultVal = 0;	XThrowIfError (au.SetProperty (kAudioUnitProperty_ScheduledFilePrime,                                  kAudioUnitScope_Global, 0, &defaultVal, sizeof(defaultVal)), "kAudioUnitProperty_ScheduledFilePrime");    // tell the fp AU when to start playing (this ts is in the AU's render time stamps; -1 means next render cycle)	AudioTimeStamp startTime;	memset (&startTime, 0, sizeof(startTime));	startTime.mFlags = kAudioTimeStampSampleTimeValid;	startTime.mSampleTime = -1;	XThrowIfError (au.SetProperty(kAudioUnitProperty_ScheduleStartTimeStamp,                                 kAudioUnitScope_Global, 0, &startTime, sizeof(startTime)), "kAudioUnitProperty_ScheduleStartTimeStamp");  	return fileDuration;}void MakeSimpleGraph (AUGraph &theGraph, CAAudioUnit &fileAU, CAStreamBasicDescription &fileFormat, AudioFileID audioFile){	XThrowIfError (NewAUGraph (&theGraph), "NewAUGraph");		CAComponentDescription cd;  	// output node	cd.componentType = kAudioUnitType_Output;	cd.componentSubType = kAudioUnitSubType_DefaultOutput;	cd.componentManufacturer = kAudioUnitManufacturer_Apple;  	AUNode outputNode;	XThrowIfError (AUGraphAddNode (theGraph, &cd, &outputNode), "AUGraphAddNode");		// file AU node	AUNode fileNode;	cd.componentType = kAudioUnitType_Generator;	cd.componentSubType = kAudioUnitSubType_AudioFilePlayer;		XThrowIfError (AUGraphAddNode (theGraph, &cd, &fileNode), "AUGraphAddNode");		// connect & setup	XThrowIfError (AUGraphOpen (theGraph), "AUGraphOpen");		// install overload listener to detect when something is wrong	AudioUnit anAU;	XThrowIfError (AUGraphNodeInfo(theGraph, fileNode, NULL, &anAU), "AUGraphNodeInfo");		fileAU = CAAudioUnit (fileNode, anAU);    // prepare the file AU for playback  // set its output channels	XThrowIfError (fileAU.SetNumberChannels (kAudioUnitScope_Output, 0, fileFormat.NumberChannels()), "SetNumberChannels");    // set the output sample rate of the file AU to be the same as the file:	XThrowIfError (fileAU.SetSampleRate (kAudioUnitScope_Output, 0, fileFormat.mSampleRate), "SetSampleRate");    // load in the file 	XThrowIfError (fileAU.SetProperty(kAudioUnitProperty_ScheduledFileIDs,                                     kAudioUnitScope_Global, 0, &audioFile, sizeof(audioFile)), "SetScheduleFile");    	XThrowIfError (AUGraphConnectNodeInput (theGraph, fileNode, 0, outputNode, 0), "AUGraphConnectNodeInput");    // AT this point we make sure we have the file player AU initialized  // this also propogates the output format of the AU to the output unit	XThrowIfError (AUGraphInitialize (theGraph), "AUGraphInitialize");		// workaround a race condition in the file player AU	usleep (10 * 1000);    // if we have a surround file, then we should try to tell the output AU what the order of the channels will be	if (fileFormat.NumberChannels() > 2) {		UInt32 layoutSize = 0;		OSStatus err;		XThrowIfError (err = AudioFileGetPropertyInfo (audioFile, kAudioFilePropertyChannelLayout, &layoutSize, NULL),                   "kAudioFilePropertyChannelLayout");				if (!err && layoutSize) {			char* layout = new char[layoutSize];						err = AudioFileGetProperty(audioFile, kAudioFilePropertyChannelLayout, &layoutSize, layout);			XThrowIfError (err, "Get Layout From AudioFile");						// ok, now get the output AU and set its layout			XThrowIfError (AUGraphNodeInfo(theGraph, outputNode, NULL, &anAU), "AUGraphNodeInfo");						err = AudioUnitSetProperty (anAU, kAudioUnitProperty_AudioChannelLayout,                                   kAudioUnitScope_Input, 0, layout, layoutSize);			XThrowIfError (err, "kAudioUnitProperty_AudioChannelLayout");						delete [] layout;		}	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -