Ejemplo n.º 1
0
void	CAAudioFileConverter::PrintFormats(const CAAudioChannelLayout *origSrcFileLayout)
{
	const CAAudioChannelLayout &srcFileLayout = mSrcFile.GetFileChannelLayout();
	const CAAudioChannelLayout &destFileLayout = mDestFile.GetFileChannelLayout();
	
	// see where we've gotten
	if (mParams.flags & kOpt_Verbose) {
		printf("Formats:\n");
		mSrcFile.GetFileDataFormat().PrintFormat(stdout, "  ", "Input file   ");
		if (srcFileLayout.IsValid()) {
			printf("                 %s", 
				CAChannelLayouts::ConstantToString(srcFileLayout.Tag()));
			if (srcFileLayout.IsValid() && origSrcFileLayout != NULL &&
			srcFileLayout != *origSrcFileLayout)
				printf(" -- overriding layout %s in file", 
					CAChannelLayouts::ConstantToString(origSrcFileLayout->Tag()));
			printf("\n");
		}
		mDestFile.GetFileDataFormat().PrintFormat(stdout, "  ", "Output file  ");
		if (destFileLayout.IsValid())
			printf("                 %s\n", 
				CAChannelLayouts::ConstantToString(destFileLayout.Tag()));
		if (mSrcFile.HasConverter()) {
			mSrcFile.GetClientDataFormat().PrintFormat(stdout, "  ", "Input client ");
			CAShow(mSrcFile.GetConverter());
		}
		if (mDestFile.HasConverter()) {
			mDestFile.GetClientDataFormat().PrintFormat(stdout, "  ", "Output client");
			CAShow(mDestFile.GetConverter());
		}
	}
}
Ejemplo n.º 2
0
static void ca_start_w(CAData *d){
	OSStatus err= noErr;

	if (d->write_started==FALSE){
		AudioStreamBasicDescription inASBD;
		int i;
		
		i = ca_open_w(d);
		if (i<0)
			return;

		inASBD = d->caOutASBD;
		inASBD.mSampleRate = d->rate;
		inASBD.mFormatID = kAudioFormatLinearPCM;
		inASBD.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
		if (htonl(0x1234) == 0x1234)
		  inASBD.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian;
		inASBD.mChannelsPerFrame = d->stereo ? 2 : 1;
		inASBD.mBytesPerPacket = (d->bits / 8) * inASBD.mChannelsPerFrame;
		inASBD.mBytesPerFrame = (d->bits / 8) * inASBD.mChannelsPerFrame;
		inASBD.mFramesPerPacket = 1;
		inASBD.mBitsPerChannel = d->bits;


		err = AudioConverterNew( &inASBD, &d->caOutASBD, &d->caOutConverter);
		if(err != noErr)
			ms_error("AudioConverterNew %x %d", err, inASBD.mBytesPerFrame);
		else
			CAShow(d->caOutConverter);

		if (inASBD.mChannelsPerFrame == 1 && d->caOutASBD.mChannelsPerFrame == 2)
		{
			if (d->caOutConverter)
			{
				// 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
				SInt32 channelMap[] = { 0, 0 };
				err = AudioConverterSetProperty(d->caOutConverter, kAudioConverterChannelMap, 2*sizeof(SInt32), channelMap);
			}
		}

		memset((char*)&d->caOutRenderCallback, 0, sizeof(AURenderCallbackStruct));
		d->caOutRenderCallback.inputProc = writeRenderProc;
		d->caOutRenderCallback.inputProcRefCon = d;
		err = AudioUnitSetProperty (d->caOutAudioUnit, 
                            kAudioUnitProperty_SetRenderCallback, 
                            kAudioUnitScope_Input, 
                            0,
                            &d->caOutRenderCallback, 
                            sizeof(AURenderCallbackStruct));
		if(err != noErr)
			ms_error("AudioUnitSetProperty %x", err);

		if(err == noErr) {
			if(AudioOutputUnitStart(d->caOutAudioUnit) == noErr)
				d->write_started=TRUE;
		}
	}
}
Ejemplo n.º 3
0
bool FIOSAudioDevice::Exec(UWorld* InWorld, const TCHAR* Cmd, FOutputDevice& Ar)
{
	if (FParse::Command(&Cmd, TEXT("DumpAUGraph")) && AudioUnitGraph)
	{
		CAShow(AudioUnitGraph);
		return true;
	}
	
	return FAudioDevice::Exec(InWorld, Cmd, Ar);
}
Ejemplo n.º 4
0
static void ca_start_r(CAData *d){
	OSStatus err= noErr;
	
	if (d->read_started==FALSE){
		AudioStreamBasicDescription outASBD;
		int i;
		
		i = ca_open_r(d);
		if (i<0)
			return;
		
		outASBD = d->caInASBD;
		outASBD.mSampleRate = d->rate;
		outASBD.mFormatID = kAudioFormatLinearPCM;
		outASBD.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
		if (htonl(0x1234) == 0x1234)
		  outASBD.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian;
		outASBD.mChannelsPerFrame = d->stereo ? 2 : 1;
		outASBD.mBytesPerPacket = (d->bits / 8) * outASBD.mChannelsPerFrame;
		outASBD.mBytesPerFrame = (d->bits / 8) * outASBD.mChannelsPerFrame;
		outASBD.mFramesPerPacket = 1;
		outASBD.mBitsPerChannel = d->bits;

		err = AudioConverterNew( &d->caInASBD, &outASBD, &d->caInConverter);
		if(err != noErr)
			ms_error("AudioConverterNew %x %d", err, outASBD.mBytesPerFrame);
		else
			CAShow(d->caInConverter);

		d->caInRenderCallback.inputProc = readRenderProc;
		d->caInRenderCallback.inputProcRefCon = d;
		err = AudioUnitSetProperty(d->caInAudioUnit,
						kAudioOutputUnitProperty_SetInputCallback,
						kAudioUnitScope_Global,
						0,
						&d->caInRenderCallback,
						sizeof(AURenderCallbackStruct));

		if(AudioOutputUnitStart(d->caInAudioUnit) == noErr)
			d->read_started = TRUE;
	}
}
Ejemplo n.º 5
0
int main(int argc, char *argv[])
{
   AUGraph audioGraph;
   NewAUGraph(&audioGraph);
   
   AudioComponentDescription cd;
   AUNode outputNode;
   AudioUnit outputUnit;
   
   cd.componentManufacturer = kAudioUnitManufacturer_Apple;
   cd.componentFlags = 0;
   cd.componentFlagsMask = 0;
   cd.componentType = kAudioUnitType_Output;
   cd.componentSubType = kAudioUnitSubType_DefaultOutput;

   AUGraphAddNode(audioGraph, &cd, &outputNode);
   AUGraphNodeInfo(audioGraph, outputNode, &cd, &outputUnit);
   
   AUNode mixerNode;
   AudioUnit mixerUnit;
   
   cd.componentManufacturer = kAudioUnitManufacturer_Apple;
   cd.componentFlags = 0;
   cd.componentFlagsMask = 0;
   cd.componentType = kAudioUnitType_Mixer;
   cd.componentSubType = kAudioUnitSubType_StereoMixer;
   
   AUGraphAddNode(audioGraph, &cd, &mixerNode);
   AUGraphNodeInfo(audioGraph, mixerNode, &cd, &mixerUnit);
   
   AUGraphConnectNodeInput(audioGraph, mixerNode, 0, outputNode, 0);
   
   AUGraphOpen(audioGraph);
   AUGraphInitialize(audioGraph);
   AUGraphStart(audioGraph);
   
   AUNode synthNode;
   AudioUnit synthUnit;
   
   cd.componentManufacturer = kAudioUnitManufacturer_Apple;
   cd.componentFlags = 0;
   cd.componentFlagsMask = 0;
   cd.componentType = kAudioUnitType_MusicDevice;
   cd.componentSubType = kAudioUnitSubType_DLSSynth;
   
   AUGraphAddNode(audioGraph, &cd, &synthNode);
   AUGraphNodeInfo(audioGraph, synthNode, &cd, &synthUnit);
   
   AUGraphConnectNodeInput(audioGraph, synthNode, 0, mixerNode, 0);
   
   AUGraphUpdate(audioGraph, NULL);
   CAShow(audioGraph);
   
   MusicDeviceMIDIEvent(synthUnit, 0x90, 60, 127, 0);
   sleep(1);
   MusicDeviceMIDIEvent(synthUnit, 0x90, 62, 127, 0);
   sleep(1);
   MusicDeviceMIDIEvent(synthUnit, 0x90, 64, 127, 0);
   sleep(1);
   
   sleep(5);
   
   return(0);
}
Ejemplo n.º 6
0
void CCoreAudioGraph::ShowGraph()
{
  CAShow(m_audioGraph);
}
Ejemplo n.º 7
0
int main (int argc, const char * argv[]) {
	AUGraph graph = 0;
	AudioUnit synthUnit;
	OSStatus result;
	char* bankPath = 0;
	
	UInt8 midiChannelInUse = 0; //we're using midi channel 1...
	
		// this is the only option to main that we have...
		// just the full path of the sample bank...
		
		// On OS X there are known places were sample banks can be stored
		// Library/Audio/Sounds/Banks - so you could scan this directory and give the user options
		// about which sample bank to use...
	if (argc > 1)
		bankPath = const_cast<char*>(argv[1]);
	
	require_noerr (result = CreateAUGraph (graph, synthUnit), home);
	
// if the user supplies a sound bank, we'll set that before we initialize and start playing
	if (bankPath) 
	{
		FSSpec soundBankSpec;
		require_noerr (result = PathToFSSpec (bankPath, soundBankSpec), home);
		
		printf ("Setting Sound Bank:%s\n", bankPath);
		
		require_noerr (result = AudioUnitSetProperty (synthUnit,
											kMusicDeviceProperty_SoundBankFSSpec,
											kAudioUnitScope_Global, 0,
											&soundBankSpec, sizeof(soundBankSpec)), home);
    
	}
	
	// ok we're set up to go - initialize and start the graph
	require_noerr (result = AUGraphInitialize (graph), home);

		//set our bank
	require_noerr (result = MusicDeviceMIDIEvent(synthUnit, 
								kMidiMessage_ControlChange << 4 | midiChannelInUse, 
								kMidiMessage_BankMSBControl, 0,
								0/*sample offset*/), home);

	require_noerr (result = MusicDeviceMIDIEvent(synthUnit, 
								kMidiMessage_ProgramChange << 4 | midiChannelInUse, 
								0/*prog change num*/, 0,
								0/*sample offset*/), home);

	CAShow (graph); // prints out the graph so we can see what it looks like...
	
	require_noerr (result = AUGraphStart (graph), home);

	// we're going to play an octave of MIDI notes: one a second
	for (int i = 0; i < 13; i++) {
		UInt32 noteNum = i + 60;
		UInt32 onVelocity = 127;
		UInt32 noteOnCommand = 	kMidiMessage_NoteOn << 4 | midiChannelInUse;
			
			printf ("Playing Note: Status: 0x%lX, Note: %ld, Vel: %ld\n", noteOnCommand, noteNum, onVelocity);
		
		require_noerr (result = MusicDeviceMIDIEvent(synthUnit, noteOnCommand, noteNum, onVelocity, 0), home);
		
			// sleep for a second
		usleep (1 * 1000 * 1000);

		require_noerr (result = MusicDeviceMIDIEvent(synthUnit, noteOnCommand, noteNum, 0, 0), home);
	}
	
	// ok we're done now

home:
	if (graph) {
		AUGraphStop (graph); // stop playback - AUGraphDispose will do that for us but just showing you what to do
		DisposeAUGraph (graph);
	}
	return result;
}
Ejemplo n.º 8
0
        void start(int midiChannel, char const*const bankPath)
        {
            if (auGraph != 0)
                return;		// don't multiply init
            
            midiChannelInUse = midiChannel;
            
            OSStatus result;
            
            //create the nodes of the graph
            AUNode synthNode;
            
            AudioComponentDescription cd;
            cd.componentManufacturer = kAudioUnitManufacturer_Apple;
            cd.componentFlags = 0;
            cd.componentFlagsMask = 0;
            
            require_noerr (result = NewAUGraph (&auGraph), home);
            
            cd.componentType = kAudioUnitType_MusicDevice;
            cd.componentSubType = kAudioUnitSubType_DLSSynth;
            
            require_noerr (result = AUGraphAddNode (auGraph, &cd, &synthNode), home);
            
            cd.componentType = kAudioUnitType_Effect;
            cd.componentSubType = kAudioUnitSubType_PeakLimiter;
            
            require_noerr (result = AUGraphAddNode (auGraph, &cd, &limiterNode), home);
            
            cd.componentType = kAudioUnitType_Output;
            cd.componentSubType = kAudioUnitSubType_DefaultOutput;
            require_noerr (result = AUGraphAddNode (auGraph, &cd, &outNode), home);
            
            require_noerr (result = AUGraphOpen (auGraph), home);
            
            require_noerr (result = AUGraphConnectNodeInput(auGraph, synthNode, 0, limiterNode, 0), home);
            require_noerr (result = AUGraphConnectNodeInput(auGraph, limiterNode, 0, outNode, 0), home);
            
            // ok we're good to go - get the Synth Unit...
            require_noerr (result = AUGraphNodeInfo(auGraph, synthNode, 0, &synthUnit), home);
            
            // if the user supplies a sound bank, we'll set that before we initialize and start playing
            if (bankPath)
            {
                // note: bankpath is a soundfont
                CFURLRef url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8 *)bankPath, strlen(bankPath), false);

                if (url) {
                    require_noerr (result = AudioUnitSetProperty(synthUnit,
                                                                 kMusicDeviceProperty_SoundBankURL, kAudioUnitScope_Global,
                                                                 0,
                                                                 &url, sizeof(url)
                                                                 ), home);

                    CFRelease(url);
                }
            }
            
            // ok we're set up to go - initialize and start the graph
            require_noerr (result = AUGraphInitialize (auGraph), home);
            
            //set our bank
            require_noerr (result = MusicDeviceMIDIEvent(synthUnit,
                                                         kMidiMessage_ControlChange << 4 | midiChannelInUse,
                                                         kMidiMessage_BankMSBControl, 0,
                                                         0/*sample offset*/), home);
            
            require_noerr (result = MusicDeviceMIDIEvent(synthUnit,
                                                         kMidiMessage_ProgramChange << 4 | midiChannelInUse,
                                                         0/*prog change num*/, 0,
                                                         0/*sample offset*/), home);
            
            CAShow(auGraph); // prints out the graph so we can see what it looks like...
            
            require_noerr (result = AUGraphStart(auGraph), home);
            return;
            
        home:
            shutdown();
        }
Ejemplo n.º 9
0
// _______________________________________________________________________________________
//
void	CAAudioFile::SetClientFormat(const CAStreamBasicDescription &dataFormat, const CAAudioChannelLayout *layout)
{
	LOG_FUNCTION("CAAudioFile::SetClientFormat", "%p", this);
	XThrowIf(!dataFormat.IsPCM(), kExtAudioFileError_NonPCMClientFormat, "non-PCM client format on audio file");

	bool dataFormatChanging = (mClientDataFormat.mFormatID == 0 || mClientDataFormat != dataFormat);

	if (dataFormatChanging) {
		CloseConverter();
		if (mWriteBufferList) {
			delete mWriteBufferList;
			mWriteBufferList = NULL;
		}
		mClientDataFormat = dataFormat;
	}

	if (layout && layout->IsValid()) {
		XThrowIf(layout->NumberChannels() != mClientDataFormat.NumberChannels(), kExtAudioFileError_InvalidChannelMap, "inappropriate channel map");
		mClientChannelLayout = *layout;
	}

	bool differentLayouts;
	if (mClientChannelLayout.IsValid()) {
		if (mFileChannelLayout.IsValid()) {
			differentLayouts = mClientChannelLayout.Tag() != mFileChannelLayout.Tag();
#if VERBOSE_CHANNELMAP
			printf("two valid layouts, %s\n", differentLayouts ? "different" : "same");
#endif
		} else {
			differentLayouts = false;
#if VERBOSE_CHANNELMAP
			printf("valid client layout, unknown file layout\n");
#endif
		}
	} else {
		differentLayouts = false;
#if VERBOSE_CHANNELMAP
		if (mFileChannelLayout.IsValid())
			printf("valid file layout, unknown client layout\n");
		else
			printf("two invalid layouts\n");
#endif
	}

	if (mClientDataFormat != mFileDataFormat || differentLayouts) {
		// We need an AudioConverter.
		if (mMode == kReading) {
			// file -> client (decode)
//mFileDataFormat.PrintFormat(  stdout, "", "File:   ");
//mClientDataFormat.PrintFormat(stdout, "", "Client: ");

			if (mConverter == NULL)
				XThrowIfError(AudioConverterNew(&mFileDataFormat, &mClientDataFormat, &mConverter),
				"create audio converter");

#if VERBOSE_CONVERTER
			printf("CAAudioFile %p -- created converter\n", this);
			CAShow(mConverter);
#endif
			// set the magic cookie, if any (for decode)
			if (mMagicCookie)
				SetConverterProperty(kAudioConverterDecompressionMagicCookie, mMagicCookieSize, mMagicCookie, mFileDataFormat.IsPCM());
					// we get cookies from some AIFF's but the converter barfs on them,
					// so we set canFail to true for PCM

			SetConverterChannelLayout(false, mFileChannelLayout);
			SetConverterChannelLayout(true, mClientChannelLayout);

			// propagate leading/trailing frame counts
			if (mFileDataFormat.mBitsPerChannel == 0) {
				UInt32 propertySize;
				OSStatus err;
				AudioFilePacketTableInfo pti;
				propertySize = sizeof(pti);
				err = AudioFileGetProperty(mAudioFile, kAudioFilePropertyPacketTableInfo, &propertySize, &pti);
				if (err == noErr && (pti.mPrimingFrames > 0 || pti.mRemainderFrames > 0)) {
					AudioConverterPrimeInfo primeInfo;
					primeInfo.leadingFrames = pti.mPrimingFrames;
					primeInfo.trailingFrames = pti.mRemainderFrames;
					/* ignore any error. better to play it at all than not. */
					/*err = */AudioConverterSetProperty(mConverter, kAudioConverterPrimeInfo, sizeof(primeInfo), &primeInfo);
					//XThrowIfError(err, "couldn't set prime info on converter");
				}
			}
		} else if (mMode == kPreparingToCreate || mMode == kPreparingToWrite) {
			// client -> file (encode)
			if (mConverter == NULL)
				XThrowIfError(AudioConverterNew(&mClientDataFormat, &mFileDataFormat, &mConverter), "create audio converter");
			mWriteBufferList = CABufferList::New("", mClientDataFormat);
			SetConverterChannelLayout(false, mClientChannelLayout);
			SetConverterChannelLayout(true, mFileChannelLayout);
			if (mMode == kPreparingToWrite)
				FileFormatChanged();
		} else
			XThrowIfError(kExtAudioFileError_InvalidOperationOrder, "audio file format not yet known");
	}
	UpdateClientMaxPacketSize();
}
Ejemplo n.º 10
0
int main (int argc, const char * argv[]) 
{
	if (argc == 1) {
		fprintf (stderr, "%s\n", usageStr);
		exit(0);
	}
	
	char* filePath = 0;
	bool shouldPlay = false;
	bool shouldSetBank = false;
    bool shouldUseMIDIEndpoint = false;
	bool shouldPrint = true;
	bool waitAtEnd = false;
	bool diskStream = false;
	
	OSType dataFormat = 0;
	Float64 srate = 0;
	const char* outputFilePath = 0;
	
	MusicSequenceLoadFlags	loadFlags = 0;
	
	char* bankPath = 0;
	Float32 startTime = 0;
	UInt32 numFrames = 512;
	
	std::set<int> trackSet;
	
	for (int i = 1; i < argc; ++i)
	{
		if (!strcmp ("-p", argv[i]))
		{
			shouldPlay = true;
		}
		else if (!strcmp ("-w", argv[i]))
		{
			waitAtEnd = true;
		}
		else if (!strcmp ("-d", argv[i]))
		{
			diskStream = true;
		}
		else if (!strcmp ("-b", argv[i])) 
		{
			shouldSetBank = true;
			if (++i == argc) goto malformedInput;
			bankPath = const_cast<char*>(argv[i]);
		}
		else if (!strcmp ("-n", argv[i]))
		{
			shouldPrint = false;
		}
		else if ((filePath == 0) && (argv[i][0] == '/' || argv[i][0] == '~'))
		{
			filePath = const_cast<char*>(argv[i]);
		}
		else if (!strcmp ("-s", argv[i])) 
		{
			if (++i == argc) goto malformedInput;
			sscanf (argv[i], "%f", &startTime);
		}
		else if (!strcmp ("-t", argv[i])) 
		{
			int index;
			if (++i == argc) goto malformedInput;
			sscanf (argv[i], "%d", &index);
			trackSet.insert(--index);
		}
		else if (!strcmp("-e", argv[i]))
        {
            shouldUseMIDIEndpoint = true;
        }
		else if (!strcmp("-c", argv[i]))
        {
            loadFlags = kMusicSequenceLoadSMF_ChannelsToTracks;
        }
        else if (!strcmp ("-i", argv[i])) 
		{
			if (++i == argc) goto malformedInput;
			sscanf (argv[i], "%lu", (unsigned long*)(&numFrames));
		}
        else if (!strcmp ("-f", argv[i])) 
		{
			if (i + 3 >= argc) goto malformedInput;
			outputFilePath = argv[++i];
			StrToOSType (argv[++i], dataFormat);
			sscanf (argv[++i], "%lf", &srate);
		}
		else
		{
malformedInput:
			fprintf (stderr, "%s\n", usageStr);
			exit (1);
		}
	}
	
	if (filePath == 0) {
		fprintf (stderr, "You have to specify a MIDI file to print or play\n");
		fprintf (stderr, "%s\n", usageStr);
		exit (1);
	}
	
	if (shouldUseMIDIEndpoint && outputFilePath) {
		printf ("can't write a file when you try to play out to a MIDI Endpoint\n");
		exit (1);
	}
	
	MusicSequence sequence;
	OSStatus result;
	
	FailIf ((result = LoadSMF (filePath, sequence, loadFlags)), fail, "LoadSMF");
			
	if (shouldPrint) 
		CAShow (sequence);
	
	if (shouldPlay)
	{
        AUGraph graph = 0;
        AudioUnit theSynth = 0;
		
		FailIf ((result = MusicSequenceGetAUGraph (sequence, &graph)), fail, "MusicSequenceGetAUGraph");
		FailIf ((result = AUGraphOpen (graph)), fail, "AUGraphOpen");     
		  
		FailIf ((result = GetSynthFromGraph (graph, theSynth)), fail, "GetSynthFromGraph");
		FailIf ((result = AudioUnitSetProperty (theSynth,
										kAudioUnitProperty_CPULoad,
										kAudioUnitScope_Global, 0,
										&maxCPULoad, sizeof(maxCPULoad))), fail, "AudioUnitSetProperty: kAudioUnitProperty_CPULoad");

        if (shouldUseMIDIEndpoint) 
		{
			MIDIClientRef	theMidiClient;
			MIDIClientCreate(CFSTR("Play Sequence"), NULL, NULL, &theMidiClient);		
            
			ItemCount destCount = MIDIGetNumberOfDestinations();
            if (destCount == 0) {
                fprintf (stderr, "No MIDI Endpoints to play to.\n");
                exit(1);
            }
            
            FailIf ((result = MusicSequenceSetMIDIEndpoint (sequence, MIDIGetDestination(0))), fail, "MusicSequenceSetMIDIEndpoint");
        } 
		else 
		{   
			if (shouldSetBank) {
				CFURLRef soundBankURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8*)bankPath, strlen(bankPath), false);
								
				printf ("Setting Sound Bank:%s\n", bankPath);
					
				result = AudioUnitSetProperty (theSynth,
                                               kMusicDeviceProperty_SoundBankURL,
                                               kAudioUnitScope_Global, 0,
                                               &soundBankURL, sizeof(soundBankURL));
                if (soundBankURL) CFRelease(soundBankURL);
                FailIf (result, fail, "AudioUnitSetProperty: kMusicDeviceProperty_SoundBankURL");								
			}
						
			if (diskStream) {
				UInt32 value = diskStream;
				FailIf ((result = AudioUnitSetProperty (theSynth,
											kMusicDeviceProperty_StreamFromDisk,
											kAudioUnitScope_Global, 0,
											&value, sizeof(value))), fail, "AudioUnitSetProperty: kMusicDeviceProperty_StreamFromDisk");
			}

			if (outputFilePath) {
				// need to tell synth that is going to render a file.
				UInt32 value = 1;
				FailIf ((result = AudioUnitSetProperty (theSynth,
												kAudioUnitProperty_OfflineRender,
												kAudioUnitScope_Global, 0,
												&value, sizeof(value))), fail, "AudioUnitSetProperty: kAudioUnitProperty_OfflineRender");
			}
			
			FailIf ((result = SetUpGraph (graph, numFrames, srate, (outputFilePath != NULL))), fail, "SetUpGraph");
			
			if (shouldPrint) {
				printf ("Sample Rate: %.1f \n", srate);
				printf ("Disk Streaming is enabled: %c\n", (diskStream ? 'T' : 'F'));
			}
			
			FailIf ((result = AUGraphInitialize (graph)), fail, "AUGraphInitialize");

            if (shouldPrint)
				CAShow (graph);
        }
        
		MusicPlayer player;
		FailIf ((result = NewMusicPlayer (&player)), fail, "NewMusicPlayer");

		FailIf ((result = MusicPlayerSetSequence (player, sequence)), fail, "MusicPlayerSetSequence");

		// figure out sequence length
		UInt32 ntracks;
		FailIf ((MusicSequenceGetTrackCount (sequence, &ntracks)), fail, "MusicSequenceGetTrackCount");
		MusicTimeStamp sequenceLength = 0;
		bool shouldPrintTracks = shouldPrint && !trackSet.empty();
		if (shouldPrintTracks)
			printf ("Only playing specified tracks:\n\t");
		
		for (UInt32 i = 0; i < ntracks; ++i) {
			MusicTrack track;
			MusicTimeStamp trackLength;
			UInt32 propsize = sizeof(MusicTimeStamp);
			FailIf ((result = MusicSequenceGetIndTrack(sequence, i, &track)), fail, "MusicSequenceGetIndTrack");
			FailIf ((result = MusicTrackGetProperty(track, kSequenceTrackProperty_TrackLength,
							&trackLength, &propsize)), fail, "MusicTrackGetProperty: kSequenceTrackProperty_TrackLength");
			if (trackLength > sequenceLength)
				sequenceLength = trackLength;
			
			if (!trackSet.empty() && (trackSet.find(i) == trackSet.end()))
			{
				Boolean mute = true;
				FailIf ((result = MusicTrackSetProperty(track, kSequenceTrackProperty_MuteStatus, &mute, sizeof(mute))), fail, "MusicTrackSetProperty: kSequenceTrackProperty_MuteStatus");
			} 
			else if (shouldPrintTracks) {
				printf ("%d, ", int(i+1));
			}
		}
		if (shouldPrintTracks) 
			printf ("\n");
			
	// now I'm going to add 8 beats on the end for the reverb/long releases to tail off...
		sequenceLength += 8;
		
		FailIf ((result = MusicPlayerSetTime (player, startTime)), fail, "MusicPlayerSetTime");
		
		FailIf ((result = MusicPlayerPreroll (player)), fail, "MusicPlayerPreroll");
		
		if (shouldPrint) {
			printf ("Ready to play: %s, %.2f beats long\n\t<Enter> to continue: ", filePath, sequenceLength); 

			getc(stdin);
		}
		
        startRunningTime = CAHostTimeBase::GetTheCurrentTime();
		
/*		if (waitAtEnd && graph)
			AUGraphStart(graph);
*/		
		FailIf ((result = MusicPlayerStart (player)), fail, "MusicPlayerStart");
		
		if (outputFilePath) 
			WriteOutputFile (outputFilePath, dataFormat, srate, sequenceLength, shouldPrint, graph, numFrames, player);
		else
			PlayLoop (player, graph, sequenceLength, shouldPrint, waitAtEnd);
					
		FailIf ((result = MusicPlayerStop (player)), fail, "MusicPlayerStop");
		if (shouldPrint) printf ("finished playing\n");

/*		if (waitAtEnd) {
			CFRunLoopRunInMode(kCFRunLoopDefaultMode, 10, false);
			if (graph)
				AUGraphStop(graph);
			if (shouldPrint) printf ("disposing\n");
		}
*/		
// this shows you how you should dispose of everything
		FailIf ((result = DisposeMusicPlayer (player)), fail, "DisposeMusicPlayer");
		FailIf ((result = DisposeMusicSequence(sequence)), fail, "DisposeMusicSequence");
		// don't own the graph so don't dispose it (the seq owns it as we never set it ourselves, we just got it....)
	}
	else {
		FailIf ((result = DisposeMusicSequence(sequence)), fail, "DisposeMusicSequence");
	}
	
	while (waitAtEnd)
		CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.25, false);
		
    return 0;
	
fail:
	if (shouldPrint) printf ("Error = %ld\n", (long)result);
	return result;
}
Ejemplo n.º 11
0
int main (int argc, const char * argv[]) 
{
	if (argc == 1) {
		fprintf (stderr, "%s\n", usageStr);
		exit(0);
	}
	
	char* filePath = 0;
	bool shouldPlay = false;
	bool shouldSetBank = false;
    bool shouldUseMIDIEndpoint = false;
	bool shouldPrint = true;
	bool waitAtEnd = false;
	bool diskStream = false;
	
	OSType dataFormat = 0;
	Float64 srate = 0;
	const char* outputFilePath = 0;
	
	MusicSequenceLoadFlags	loadFlags = 0;
	
	char* bankPath = 0;
	Float32 startTime = 0;
	UInt32 numFrames = 512;
	
	for (int i = 1; i < argc; ++i)
	{
		if (!strcmp ("-p", argv[i]))
		{
			shouldPlay = true;
		}
		else if (!strcmp ("-w", argv[i]))
		{
			waitAtEnd = true;
		}
		else if (!strcmp ("-d", argv[i]))
		{
			diskStream = true;
		}
		else if (!strcmp ("-b", argv[i])) 
		{
			shouldSetBank = true;
			if (++i == argc) goto malformedInput;
			bankPath = const_cast<char*>(argv[i]);
		}
		else if (!strcmp ("-n", argv[i]))
		{
			shouldPrint = false;
		}
		else if ((filePath == 0) && (argv[i][0] == '/' || argv[i][0] == '~'))
		{
			filePath = const_cast<char*>(argv[i]);
		}
		else if (!strcmp ("-t", argv[i])) 
		{
			if (++i == argc) goto malformedInput;
			sscanf (argv[i], "%f", &startTime);
		}
		else if (!strcmp("-e", argv[i]))
        {
            shouldUseMIDIEndpoint = true;
        }
		else if (!strcmp("-c", argv[i]))
        {
            loadFlags = kMusicSequenceLoadSMF_ChannelsToTracks;
        }
        else if (!strcmp ("-i", argv[i])) 
		{
			if (++i == argc) goto malformedInput;
			sscanf (argv[i], "%ld", &numFrames);
		}
        else if (!strcmp ("-f", argv[i])) 
		{
			if (i + 3 >= argc) goto malformedInput;
			outputFilePath = argv[++i];
			str2OSType (argv[++i], dataFormat);
			sscanf (argv[++i], "%lf", &srate);
		}
		else
		{
malformedInput:
			fprintf (stderr, "%s\n", usageStr);
			exit (1);
		}
	}
	
	if (filePath == 0) {
		fprintf (stderr, "You have to specify a MIDI file to print or play\n");
		fprintf (stderr, "%s\n", usageStr);
		exit (1);
	}
	
	if (shouldUseMIDIEndpoint && outputFilePath) {
		printf ("can't write a file when you try to play out to a MIDI Endpoint\n");
		exit (1);
	}
	
	MusicSequence sequence;
	OSStatus result;
	
	require_noerr (result = LoadSMF (filePath, sequence, loadFlags), fail);
			
	if (shouldPrint) 
		CAShow (sequence);
	
	if (shouldPlay)
	{
        AUGraph graph = 0;
        AudioUnit theSynth = 0;
		
		require_noerr (result = MusicSequenceGetAUGraph (sequence, &graph), fail);
		require_noerr (result = AUGraphOpen (graph), fail);     
		  
		require_noerr (result = GetSynthFromGraph (graph, theSynth), fail);
		require_noerr (result = AudioUnitSetProperty (theSynth,
										kAudioUnitProperty_CPULoad,
										kAudioUnitScope_Global, 0,
										&maxCPULoad, sizeof(maxCPULoad)), fail);

        if (shouldUseMIDIEndpoint) 
		{
			MIDIClientRef	theMidiClient;
			MIDIClientCreate(CFSTR("Play Sequence"), NULL, NULL, &theMidiClient);		
            
			ItemCount destCount = MIDIGetNumberOfDestinations();
            if (destCount == 0) {
                fprintf (stderr, "No MIDI Endpoints to play to.\n");
                exit(1);
            }
            
            require_noerr (result = MusicSequenceSetMIDIEndpoint (sequence, MIDIGetDestination(0)), fail);
        } 
		else 
		{   
			if (shouldSetBank) {                
				FSRef soundBankRef;
				require_noerr (result = FSPathMakeRef ((const UInt8*)bankPath, &soundBankRef, 0), fail);
								
				printf ("Setting Sound Bank:%s\n", bankPath);
					
				require_noerr (result = AudioUnitSetProperty (theSynth,
												kMusicDeviceProperty_SoundBankFSRef,
												kAudioUnitScope_Global, 0,
												&soundBankRef, sizeof(soundBankRef)), fail);
			}
						
			if (diskStream) {
				UInt32 value = diskStream;
				require_noerr (result = AudioUnitSetProperty (theSynth,
											kMusicDeviceProperty_StreamFromDisk,
											kAudioUnitScope_Global, 0,
											&value, sizeof(value)), fail);
			}

			if (outputFilePath) {
				// need to tell synth that is going to render a file.
				UInt32 value = 1;
				require_noerr (result = AudioUnitSetProperty (theSynth,
												kAudioUnitProperty_OfflineRender,
												kAudioUnitScope_Global, 0,
												&value, sizeof(value)), fail);
			}
			
			require_noerr (result = SetUpGraph (graph, numFrames, srate, (outputFilePath != NULL)), fail);
			
			if (shouldPrint) {
				printf ("Sample Rate: %.1f \n", srate);
				printf ("Disk Streaming is enabled: %c\n", (diskStream ? 'T' : 'F'));
			}
			
			require_noerr (result = AUGraphInitialize (graph), fail);

            if (shouldPrint)
				CAShow (graph);
        }
        
		MusicPlayer player;
		require_noerr (result = NewMusicPlayer (&player), fail);

		require_noerr (result = MusicPlayerSetSequence (player, sequence), fail);

	// figure out sequence length
		UInt32 ntracks;
		require_noerr(MusicSequenceGetTrackCount (sequence, &ntracks), fail);
		MusicTimeStamp sequenceLength = 0;
		for (UInt32 i = 0; i < ntracks; ++i) {
			MusicTrack track;
			MusicTimeStamp trackLength;
			UInt32 propsize = sizeof(MusicTimeStamp);
			require_noerr (result = MusicSequenceGetIndTrack(sequence, i, &track), fail);
			require_noerr (result = MusicTrackGetProperty(track, kSequenceTrackProperty_TrackLength,
							&trackLength, &propsize), fail);
			if (trackLength > sequenceLength)
				sequenceLength = trackLength;
		}
	
	// now I'm going to add 8 beats on the end for the reverb/long releases to tail off...
		sequenceLength += 8;
		
		require_noerr (result = MusicPlayerSetTime (player, startTime), fail);
		
		require_noerr (result = MusicPlayerPreroll (player), fail);
		
		if (shouldPrint) {
			printf ("Ready to play: %s, %.2f beats long\n\t<Enter> to continue: ", filePath, sequenceLength); 

			getc(stdin);
		}
		
		startRunningTime = AudioGetCurrentHostTime ();
		
		require_noerr (result = MusicPlayerStart (player), fail);
		
		if (outputFilePath) 
			WriteOutputFile (outputFilePath, dataFormat, srate, sequenceLength, shouldPrint, graph, numFrames, player);
		else
			PlayLoop (player, graph, sequenceLength, shouldPrint, waitAtEnd);
					
		require_noerr (result = MusicPlayerStop (player), fail);
		if (shouldPrint) printf ("finished playing\n");
			
// this shows you how you should dispose of everything
		require_noerr (result = DisposeMusicPlayer (player), fail);
		require_noerr (result = DisposeMusicSequence(sequence), fail);
		// don't own the graph so don't dispose it (the seq owns it as we never set it ourselves, we just got it....)
	}
	else {
		require_noerr (result = DisposeMusicSequence(sequence), fail);
	}
	
	while (waitAtEnd)
		CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.25, false);
		
    return 0;
	
fail:
	if (shouldPrint) printf ("Error = %ld\n", result);
	return result;
}
Ejemplo n.º 12
0
void CreateMyAUGraph(MyAUGraphPlayer *player)
{
	// create a new AUGraph
	CheckError(NewAUGraph(&player->graph),
			   "NewAUGraph failed");
	
	// generate description that will match our output device (speakers)
	AudioComponentDescription outputcd = {0};
	outputcd.componentType = kAudioUnitType_Output;
	outputcd.componentSubType = kAudioUnitSubType_DefaultOutput;
	outputcd.componentManufacturer = kAudioUnitManufacturer_Apple;
	
	// adds a node with above description to the graph
	AUNode outputNode;
	CheckError(AUGraphAddNode(player->graph, &outputcd, &outputNode),
			   "AUGraphAddNode[kAudioUnitSubType_DefaultOutput] failed");
	
	// generate description that will match a generator AU of type: speech synthesizer
	AudioComponentDescription speechcd = {0};
	speechcd.componentType = kAudioUnitType_Generator;
	speechcd.componentSubType = kAudioUnitSubType_SpeechSynthesis;
	speechcd.componentManufacturer = kAudioUnitManufacturer_Apple;
	
	// adds a node with above description to the graph
	AUNode speechNode;
	CheckError(AUGraphAddNode(player->graph, &speechcd, &speechNode),
			   "AUGraphAddNode[kAudioUnitSubType_SpeechSynthesis] failed");
	
	// opening the graph opens all contained audio units but does not allocate any resources yet
	CheckError(AUGraphOpen(player->graph),
			   "AUGraphOpen failed");
	
	// get the reference to the AudioUnit object for the speech synthesis graph node
	CheckError(AUGraphNodeInfo(player->graph, speechNode, NULL, &player->speechAU),
			   "AUGraphNodeInfo failed");
	
	//	// debug - get the asbd
	//	UInt32 propSize = sizeof (AudioStreamBasicDescription);
	//	CheckError(AudioUnitGetProperty(player->speechAU,
	//									kAudioUnitProperty_StreamFormat,
	//									kAudioUnitScope_Output,
	//									0,
	//									&player->streamFormat,
	//									&propSize),
	//			   "Couldn't get ASBD");	
	
#ifdef PART_II
	//
	// FUN! re-route the speech thru a reverb effect before sending to speakers
	//
	// generate description that will match out reverb effect
	AudioComponentDescription reverbcd = {0};
	reverbcd.componentType = kAudioUnitType_Effect;
	reverbcd.componentSubType = kAudioUnitSubType_MatrixReverb;
	reverbcd.componentManufacturer = kAudioUnitManufacturer_Apple;
	
	// adds a node with above description to the graph
	AUNode reverbNode;
	CheckError(AUGraphAddNode(player->graph, &reverbcd, &reverbNode),
			   "AUGraphAddNode[kAudioUnitSubType_MatrixReverb] failed");
	
	// connect the output source of the speech synthesizer AU to the input source of the reverb node
	CheckError(AUGraphConnectNodeInput(player->graph, speechNode, 0, reverbNode, 0),
			   "AUGraphConnectNodeInput");
	
	// connect the output source of the reverb AU to the input source of the output node
	CheckError(AUGraphConnectNodeInput(player->graph, reverbNode, 0, outputNode, 0),
			   "AUGraphConnectNodeInput");
	
	// get the reference to the AudioUnit object for the reverb graph node
	AudioUnit reverbUnit;
	CheckError(AUGraphNodeInfo(player->graph, reverbNode, NULL, &reverbUnit),
			   "AUGraphNodeInfo failed");
	
	/*
	 enum {
	 kReverbRoomType_SmallRoom		= 0,
	 kReverbRoomType_MediumRoom		= 1,
	 kReverbRoomType_LargeRoom		= 2,
	 kReverbRoomType_MediumHall		= 3,
	 kReverbRoomType_LargeHall		= 4,
	 kReverbRoomType_Plate			= 5,
	 kReverbRoomType_MediumChamber	= 6,
	 kReverbRoomType_LargeChamber	= 7,
	 kReverbRoomType_Cathedral		= 8,
	 kReverbRoomType_LargeRoom2		= 9,
	 kReverbRoomType_MediumHall2		= 10,
	 kReverbRoomType_MediumHall3		= 11,
	 kReverbRoomType_LargeHall2		= 12	
	 };
	 
	 */
	
	// now initialize the graph (causes resources to be allocated)
	CheckError(AUGraphInitialize(player->graph),
			   "AUGraphInitialize failed");
	
	
	// set the reverb preset for room size
	//	UInt32 roomType = kReverbRoomType_SmallRoom;
	//	UInt32 roomType = kReverbRoomType_MediumRoom;
	UInt32 roomType = kReverbRoomType_LargeHall;
	//	UInt32 roomType = kReverbRoomType_Cathedral;
	
	CheckError(AudioUnitSetProperty(reverbUnit, kAudioUnitProperty_ReverbRoomType, 
									kAudioUnitScope_Global, 0, &roomType, sizeof(UInt32)),
			   "AudioUnitSetProperty[kAudioUnitProperty_ReverbRoomType] failed");
	
	
#else
	
	// connect the output source of the speech synthesis AU to the input source of the output node
	CheckError(AUGraphConnectNodeInput(player->graph, speechNode, 0, outputNode, 0),
			   "AUGraphConnectNodeInput");
	
	// now initialize the graph (causes resources to be allocated)
	CheckError(AUGraphInitialize(player->graph),
			   "AUGraphInitialize failed");
	
#endif
	CAShow(player->graph);
}