Пример #1
0
OSStatus CAPlayThrough::SetupGraph(AudioDeviceID out)
{
	OSStatus err = noErr;
	AURenderCallbackStruct output;
	
	//Make a New Graph
    err = NewAUGraph(&mGraph);  
	checkErr(err);

	//Open the Graph, AudioUnits are opened but not initialized    
    err = AUGraphOpen(mGraph);
	checkErr(err);
	
	err = MakeGraph();
	checkErr(err);
		
	err = SetOutputDeviceAsCurrent(out);
	checkErr(err);
	
	//Tell the output unit not to reset timestamps 
	//Otherwise sample rate changes will cause sync los
	UInt32 startAtZero = 0;
	err = AudioUnitSetProperty(mOutputUnit, 
							  kAudioOutputUnitProperty_StartTimestampsAtZero, 
							  kAudioUnitScope_Global,
							  0,
							  &startAtZero, 
							  sizeof(startAtZero));
	checkErr(err);
	
	output.inputProc = OutputProc;
	output.inputProcRefCon = this;
	
	err = AudioUnitSetProperty(mVarispeedUnit, 
							  kAudioUnitProperty_SetRenderCallback, 
							  kAudioUnitScope_Input,
							  0,
							  &output, 
							  sizeof(output));
                              
                        
	checkErr(err);		
	
	return err;
}
Пример #2
0
/* This call creates the Graph and the Synth unit... */
static OSStatus CreateAUGraph(void)
{
	OSStatus result;
	/* Create the nodes of the graph */
	AUNode synthNode, limiterNode, outNode;
	ComponentDescription cd;

	cd.componentManufacturer = kAudioUnitManufacturer_Apple;
	cd.componentFlags = 0;
	cd.componentFlagsMask = 0;

	result = NewAUGraph(&s_graph);
	if (result != 0) return result;

	cd.componentType = kAudioUnitType_MusicDevice;
	cd.componentSubType = kAudioUnitSubType_DLSSynth;
	result = AUGraphNewNode(s_graph, &cd, 0, NULL, &synthNode);
	if (result != 0) return result;

	cd.componentType = kAudioUnitType_Effect;
	cd.componentSubType = kAudioUnitSubType_PeakLimiter;
	result = AUGraphNewNode(s_graph, &cd, 0, NULL, &limiterNode);
	if (result != 0) return result;

	cd.componentType = kAudioUnitType_Output;
	cd.componentSubType = kAudioUnitSubType_DefaultOutput;
	result = AUGraphNewNode(s_graph, &cd, 0, NULL, &outNode);
	if (result != 0) return result;

	result = AUGraphOpen(s_graph);
	if (result != 0) return result;

	result = AUGraphConnectNodeInput(s_graph, synthNode, 0, limiterNode, 0);
	if (result != 0) return result;
	result = AUGraphConnectNodeInput(s_graph, limiterNode, 0, outNode, 0);
	if (result != 0) return result;

	/* Ok we're good to go - get the Synth Unit... */
	result = AUGraphGetNodeInfo(s_graph, synthNode, 0, 0, 0, &s_synthUnit);
	return result;
}
Пример #3
0
// This call creates the Graph and the Synth unit...
OSStatus	CreateAUGraph (AUGraph &outGraph, AudioUnit &outSynth)
{
	OSStatus result;
	//create the nodes of the graph
	AUNode synthNode, limiterNode, outNode;
	
	ComponentDescription cd;
	cd.componentManufacturer = kAudioUnitManufacturer_Apple;
	cd.componentFlags = 0;
	cd.componentFlagsMask = 0;

	require_noerr (result = NewAUGraph (&outGraph), home);

	cd.componentType = kAudioUnitType_MusicDevice;
	cd.componentSubType = kAudioUnitSubType_DLSSynth;

	require_noerr (result = AUGraphNewNode (outGraph, &cd, 0, NULL, &synthNode), home);

	cd.componentType = kAudioUnitType_Effect;
	cd.componentSubType = kAudioUnitSubType_PeakLimiter;  

	require_noerr (result = AUGraphNewNode (outGraph, &cd, 0, NULL, &limiterNode), home);

	cd.componentType = kAudioUnitType_Output;
	cd.componentSubType = kAudioUnitSubType_DefaultOutput;  
	require_noerr (result = AUGraphNewNode (outGraph, &cd, 0, NULL, &outNode), home);
	
	require_noerr (result = AUGraphOpen (outGraph), home);
	
	require_noerr (result = AUGraphConnectNodeInput (outGraph, synthNode, 0, limiterNode, 0), home);
	require_noerr (result = AUGraphConnectNodeInput (outGraph, limiterNode, 0, outNode, 0), home);
	
	// ok we're good to go - get the Synth Unit...
	require_noerr (result = AUGraphGetNodeInfo(outGraph, synthNode, 0, 0, 0, &outSynth), home);

home:
	return result;
}
Пример #4
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();
        }
Пример #5
0
bool FIOSAudioDevice::InitializeHardware()
{
	SIZE_T SampleSize = sizeof(AudioSampleType);
	double GraphSampleRate = 44100.0;

	if (!SetHardwareSampleRate(GraphSampleRate) || !SetAudioSessionActive(true))
	{
		HandleError(TEXT("Failed to establish the audio session!"));
		return false;
	}

	// Retrieve the actual hardware sample rate
	GetHardwareSampleRate(GraphSampleRate);

	// Linear PCM stream format
	MixerFormat.mFormatID         = kAudioFormatLinearPCM;
	MixerFormat.mFormatFlags	  = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked;
	MixerFormat.mBytesPerPacket   = SampleSize;
	MixerFormat.mFramesPerPacket  = 1;
	MixerFormat.mBytesPerFrame    = SampleSize;
	MixerFormat.mChannelsPerFrame = 1;
	MixerFormat.mBitsPerChannel   = 8 * SampleSize;
	MixerFormat.mSampleRate       = GraphSampleRate;

	OSStatus Status = NewAUGraph(&AudioUnitGraph);
	if (Status != noErr)
	{
		HandleError(TEXT("Failed to create audio unit graph!"));
		return false;
	}

	AudioComponentDescription UnitDescription;

	// Setup audio output unit
	UnitDescription.componentType         = kAudioUnitType_Output;
	UnitDescription.componentSubType      = kAudioUnitSubType_RemoteIO;
	UnitDescription.componentManufacturer = kAudioUnitManufacturer_Apple;
	UnitDescription.componentFlags        = 0;
	UnitDescription.componentFlagsMask    = 0;
	Status = AUGraphAddNode(AudioUnitGraph, &UnitDescription, &OutputNode);
	if (Status != noErr)
	{
		HandleError(TEXT("Failed to initialize audio output node!"), true);
		return false;
	}

	// Setup audo mixer unit
	UnitDescription.componentType         = kAudioUnitType_Mixer;
	UnitDescription.componentSubType      = kAudioUnitSubType_AU3DMixerEmbedded;
	UnitDescription.componentManufacturer = kAudioUnitManufacturer_Apple;
	UnitDescription.componentFlags        = 0;
	UnitDescription.componentFlagsMask    = 0;
	Status = AUGraphAddNode(AudioUnitGraph, &UnitDescription, &MixerNode);
	if (Status != noErr)
	{
		HandleError(TEXT("Failed to initialize audio mixer node!"), true);
		return false;
	}
	
	Status = AUGraphOpen(AudioUnitGraph);
	if (Status != noErr)
	{
		HandleError(TEXT("Failed to open audio unit graph"), true);
		return false;
	}
	
	Status = AUGraphNodeInfo(AudioUnitGraph, OutputNode, NULL, &OutputUnit);
	if (Status != noErr)
	{
		HandleError(TEXT("Failed to retrieve output unit reference!"), true);
		return false;
	}
	
	Status = AUGraphNodeInfo(AudioUnitGraph, MixerNode, NULL, &MixerUnit);
	if (Status != noErr)
	{
		HandleError(TEXT("Failed to retrieve mixer unit reference!"), true);
		return false;
	}

	uint32 BusCount = MaxChannels * CHANNELS_PER_BUS;
	Status = AudioUnitSetProperty(MixerUnit,
	                              kAudioUnitProperty_ElementCount,
	                              kAudioUnitScope_Input,
	                              0,
	                              &BusCount,
	                              sizeof(BusCount));
	if (Status != noErr)
	{
		HandleError(TEXT("Failed to set kAudioUnitProperty_ElementCount for audio mixer unit!"), true);
		return false;
	}
	
	// Initialize sound source early on, allowing for render callback hookups
	InitSoundSources();

	// Setup the mixer unit sample rate
	Status = AudioUnitSetProperty(MixerUnit,
	                              kAudioUnitProperty_SampleRate,
	                              kAudioUnitScope_Output,
	                              0,
	                              &GraphSampleRate,
	                              sizeof(GraphSampleRate));
	if (Status != noErr)
	{
		HandleError(TEXT("Failed to set kAudioUnitProperty_SampleRate for audio mixer unit!"), true);
		return false;
	}
	
	// Connect mixer node output to output node input
	Status = AUGraphConnectNodeInput(AudioUnitGraph, MixerNode, 0, OutputNode, 0);
	if (Status != noErr)
	{
		HandleError(TEXT("Failed to connect mixer node to output node!"), true);
		return false;
	}

	// Initialize and start the audio unit graph
	Status = AUGraphInitialize(AudioUnitGraph);
	if (Status == noErr)
	{
		Status = AUGraphStart(AudioUnitGraph);
	}

	if (Status != noErr)
	{
		HandleError(TEXT("Failed to start audio graph!"), true);
		return false;
	}

	return true;
}
Пример #6
0
/**
 * Initializes the audio device and creates sources.
 *
 * @return true if initialization was successful, false otherwise
 */
bool FCoreAudioDevice::InitializeHardware()
{
	if (IsRunningDedicatedServer())
	{
		return false;
	}

	// Load ogg and vorbis dlls if they haven't been loaded yet
	LoadVorbisLibraries();

	InverseTransform = FMatrix::Identity;

	for( SInt32 Index = 0; Index < MAX_AUDIOCHANNELS; ++Index )
	{
		Mixer3DInputStatus[ Index ] = false;
	}

	for( SInt32 Index = 0; Index < MAX_MULTICHANNEL_AUDIOCHANNELS; ++Index )
	{
		MatrixMixerInputStatus[ Index ] = false;
	}

	// Make sure the output audio device exists
	AudioDeviceID HALDevice;
	UInt32 Size = sizeof( AudioDeviceID );
	AudioObjectPropertyAddress PropertyAddress;
	PropertyAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
	PropertyAddress.mScope = kAudioObjectPropertyScopeGlobal;
	PropertyAddress.mElement = kAudioObjectPropertyElementMaster;

	OSStatus Status = AudioObjectGetPropertyData( kAudioObjectSystemObject, &PropertyAddress, 0, NULL, &Size, &HALDevice );
	if( Status != noErr )
	{
		UE_LOG(LogInit, Log, TEXT( "No audio devices found!" ) );
		return false;
	}

	Status = NewAUGraph( &AudioUnitGraph );
	if( Status != noErr )
	{
		UE_LOG(LogInit, Log, TEXT( "Failed to create audio unit graph!" ) );
		return false;
	}

	AudioComponentDescription Desc;
	Desc.componentFlags = 0;
	Desc.componentFlagsMask = 0;
	Desc.componentType = kAudioUnitType_Output;
	Desc.componentSubType = kAudioUnitSubType_DefaultOutput;
	Desc.componentManufacturer = kAudioUnitManufacturer_Apple;
	Status = AUGraphAddNode( AudioUnitGraph, &Desc, &OutputNode );
	if( Status == noErr )
	{
		Status = AUGraphOpen( AudioUnitGraph );
		if( Status == noErr )
		{
			Status = AUGraphNodeInfo( AudioUnitGraph, OutputNode, NULL, &OutputUnit );
			if( Status == noErr )
			{
				Status = AudioUnitInitialize( OutputUnit );
			}
		}
	}

	if( Status != noErr )
	{
		UE_LOG(LogInit, Log, TEXT( "Failed to initialize audio output unit!" ) );
		Teardown();
		return false;
	}

	Desc.componentFlags = 0;
	Desc.componentFlagsMask = 0;
	Desc.componentType = kAudioUnitType_Mixer;
	Desc.componentSubType = kAudioUnitSubType_3DMixer;
	Desc.componentManufacturer = kAudioUnitManufacturer_Apple;
	
	Status = AUGraphAddNode( AudioUnitGraph, &Desc, &Mixer3DNode );
	if( Status == noErr )
	{
		Status = AUGraphNodeInfo( AudioUnitGraph, Mixer3DNode, NULL, &Mixer3DUnit );
		if( Status == noErr )
		{
			Status = AudioUnitInitialize( Mixer3DUnit );
		}
	}
	
	if( Status != noErr )
	{
		UE_LOG(LogInit, Log, TEXT( "Failed to initialize audio 3D mixer unit!" ) );
		Teardown();
		return false;
	}
	
	Desc.componentFlags = 0;
	Desc.componentFlagsMask = 0;
	Desc.componentType = kAudioUnitType_Mixer;
	Desc.componentSubType = kAudioUnitSubType_MatrixMixer;
	Desc.componentManufacturer = kAudioUnitManufacturer_Apple;
	
	Status = AUGraphAddNode( AudioUnitGraph, &Desc, &MatrixMixerNode );
	if( Status == noErr )
	{
		Status = AUGraphNodeInfo( AudioUnitGraph, MatrixMixerNode, NULL, &MatrixMixerUnit );
		
		// Set number of buses for input
		uint32 NumBuses = MAX_MULTICHANNEL_AUDIOCHANNELS;
		Size = sizeof( NumBuses );
		
		Status = AudioUnitSetProperty( MatrixMixerUnit, kAudioUnitProperty_ElementCount, kAudioUnitScope_Input, 0, &NumBuses, Size );
		if( Status == noErr )
		{
			// Set number fo buses for output
			NumBuses = 1;
			Status = AudioUnitSetProperty(	MatrixMixerUnit, kAudioUnitProperty_ElementCount, kAudioUnitScope_Output, 0, &NumBuses, Size );
		}

		if( Status != noErr )
		{
			UE_LOG(LogInit, Log, TEXT( "Failed to setup audio matrix mixer unit!" ) );
			Teardown();
			return false;
		}
		
		// Get default input stream format
		Size = sizeof( AudioStreamBasicDescription );
		Status = AudioUnitGetProperty( MatrixMixerUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &MatrixMixerInputFormat, &Size );
		
		// Set output stream format to SPEAKER_COUT (6 channels)
		MatrixMixerInputFormat.mChannelsPerFrame = SPEAKER_COUNT;
		MatrixMixerInputFormat.mFramesPerPacket = 1;
		MatrixMixerInputFormat.mBytesPerPacket = MatrixMixerInputFormat.mBytesPerFrame;
		MatrixMixerInputFormat.mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
		
		for( int32 Index = 0; Index < MAX_MULTICHANNEL_AUDIOCHANNELS; Index++ )
		{
			Status = AudioUnitSetProperty( MatrixMixerUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, Index, &MatrixMixerInputFormat, Size );

			if( Status != noErr )
			{
				UE_LOG(LogInit, Log, TEXT( "Failed to setup audio matrix mixer unit input format!" ) );
				Teardown();
				return false;
			}
		}
		
		// Set output stream format
		Size = sizeof( AudioStreamBasicDescription );
		Status = AudioUnitGetProperty( MatrixMixerUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &MatrixMixerOutputFormat, &Size );
		
		if( Status != noErr )
		{
			UE_LOG(LogInit, Log, TEXT( "Failed to setup audio matrix mixer unit output format!" ) );
			Teardown();
			return false;
		}
		
		// Initialize Matrix Mixer unit
		Status = AudioUnitInitialize( MatrixMixerUnit );
		
		if( Status != noErr )
		{
			UE_LOG(LogInit, Log, TEXT( "Failed to initialize audio matrix mixer unit!" ) );
			Teardown();
			return false;
		}
		
		// Enable Output
		AudioUnitSetParameter( MatrixMixerUnit, kMatrixMixerParam_Enable, kAudioUnitScope_Output, 0, 1.0, 0 );
		
		// Set Output volume
		AudioUnitSetParameter( MatrixMixerUnit, kMatrixMixerParam_Volume, kAudioUnitScope_Output, 0, 1.0, 0 );
		AudioUnitSetParameter( MatrixMixerUnit, kMatrixMixerParam_Volume, kAudioUnitScope_Output, 1, 1.0, 0 );
		
		// Set Master volume
		AudioUnitSetParameter( MatrixMixerUnit, kMatrixMixerParam_Volume, kAudioUnitScope_Global, 0xFFFFFFFF, 1.0, 0 );
	}
	
	Size = sizeof( AudioStreamBasicDescription );
	Status = AudioUnitGetProperty( Mixer3DUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &Mixer3DFormat, &Size );
	if( Status == noErr )
	{
		// Connect 3D Mixer to Output node
		Status = AUGraphConnectNodeInput( AudioUnitGraph, Mixer3DNode, 0, OutputNode, 0 );
	}

	if( Status != noErr )
	{
		UE_LOG(LogInit, Log, TEXT( "Failed to start audio graph!" ) );
		Teardown();
		return false;
	}
	
	// Connect Matrix Mixer to 3D Mixer node
	Status = AUGraphConnectNodeInput( AudioUnitGraph, MatrixMixerNode, 0, Mixer3DNode, 0 );
	Mixer3DInputStatus[0] = true;
	
	if( Status != noErr )
	{
		UE_LOG(LogInit, Log, TEXT( "Failed to start audio graph!" ) );
		Teardown();
		return false;
	}

	Status = AUGraphInitialize( AudioUnitGraph );
	if( Status == noErr )
	{
		Status = AUGraphStart( AudioUnitGraph );
	}

	if( Status != noErr )
	{
		UE_LOG(LogInit, Log, TEXT( "Failed to start audio graph!" ) );
		Teardown();
		return false;
	}

	return true;
}
Пример #7
0
int QBSoundMac::initGraph()
{
	OSStatus err;

	mAudioFormat.mSampleRate = 44100.000000;
	mAudioFormat.mFormatID = kAudioFormatLinearPCM;

#ifdef __FLOAT_BUFFER__
    mAudioFormat.mFormatFlags = 0
	| kLinearPCMFormatFlagIsPacked
	| kLinearPCMFormatFlagIsFloat
#if __BIG_ENDIAN__
	| kLinearPCMFormatFlagIsBigEndian
#endif
	;
	mAudioFormat.mBytesPerPacket = 8;
	mAudioFormat.mFramesPerPacket = 1;
	mAudioFormat.mBytesPerFrame = 8;
	mAudioFormat.mChannelsPerFrame = 2;
	mAudioFormat.mBitsPerChannel = 32;
	mAudioFormat.mReserved = 0;
#else
    mAudioFormat.mFormatFlags = 0
	| kLinearPCMFormatFlagIsPacked
	| kLinearPCMFormatFlagIsSignedInteger 
#if __BIG_ENDIAN__
	| kLinearPCMFormatFlagIsBigEndian
#endif
	;
	mAudioFormat.mBytesPerPacket = 4;
	mAudioFormat.mFramesPerPacket = 1;
	mAudioFormat.mBytesPerFrame = 4;
	mAudioFormat.mChannelsPerFrame = 2;
	mAudioFormat.mBitsPerChannel = 16;
	mAudioFormat.mReserved = 0;
#endif

	err = NewAUGraph(&mGraph);

#if !TARGET_OS_IPHONE
    AudioComponentDescription description;
    description.componentSubType = kAudioUnitSubType_DefaultOutput;
#else
	AudioComponentDescription description;
	description.componentSubType = kAudioUnitSubType_RemoteIO;
#endif
    description.componentType = kAudioUnitType_Output;
    description.componentManufacturer = kAudioUnitManufacturer_Apple;
    description.componentFlags = 0;
    description.componentFlagsMask = 0;
#if 1
	err = AUGraphAddNode(mGraph,&description,&mOutputNode);
#else
	err = AUGraphNewNode(mGraph,&description, 0, NULL, &mOutputNode);
#endif

	err = AUGraphOpen(mGraph);

#if 1
	err = AUGraphNodeInfo(mGraph,mOutputNode,NULL,&mAudioUnit);
#else
	err = AUGraphGetNodeInfo(mGraph,mOutputNode,NULL,NULL,NULL,&mAudioUnit);
#endif

   err =  AudioUnitSetProperty(mAudioUnit,
                                  kAudioUnitProperty_StreamFormat,
                                  kAudioUnitScope_Input,
                                  0,
                                  &mAudioFormat,
                                  sizeof(AudioStreamBasicDescription));

	{
		AURenderCallbackStruct input;
		input.inputProc = callback;
		input.inputProcRefCon = this;
	err = 	AudioUnitSetProperty(mAudioUnit,
									  kAudioUnitProperty_SetRenderCallback,
									  kAudioUnitScope_Input,
									  0,
									  &input, sizeof(input));
	}
	
//	{
//		AudioUnitSetParameter (mAudioUnit,
//										kHALOutputParam_Volume,
//										kAudioUnitScope_Global,0,1,0);
//	}

	err = AUGraphInitialize(mGraph);
	//err = AUGraphStart(mGraph);
	
	//pthread_mutex_init(&mLoaderThreadMutex,NULL);

#ifdef __USE_OGG_VORBIS__
	mThreadEnd = false;
	pthread_create(&mLoaderThread,NULL,LoaderThreadProc,this);
#endif

//	mOpenGraph = false;
//	mInitGraph = false;

//	startAUGraph();

//printf("openAUGraph\n");
	return err;
}
Пример #8
0
bool CCoreAudioGraph::Open(ICoreAudioSource *pSource, AEAudioFormat &format, bool allowMixing)
{
  OSStatus ret;

  AudioStreamBasicDescription inputFormat;
  AudioStreamBasicDescription outputFormat;

  m_allowMixing   = allowMixing;

  ret = NewAUGraph(&m_audioGraph);
  if (ret)
  {
    CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error create audio grpah. Error = %s", GetError(ret).c_str());
    return false;
  }
  ret = AUGraphOpen(m_audioGraph);
  if (ret)
  {
    CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error open audio grpah. Error = %s", GetError(ret).c_str());
    return false;
  }

  // get output unit
  if (m_audioUnit)
  {
    CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error audio unit already open. double call ?");
    return false;
  }

  m_audioUnit = new CAUOutputDevice();
  if (!m_audioUnit->Open(m_audioGraph, kAudioUnitType_Output, kAudioUnitSubType_RemoteIO, kAudioUnitManufacturer_Apple))
    return false;

  if (!m_audioUnit->EnableInputOuput())
    return false;

  m_audioUnit->GetFormatDesc(format, &inputFormat);

  //if(!allowMixing)
  //{
    if (!m_audioUnit->SetFormat(&inputFormat, kAudioUnitScope_Input, kOutputBus))
      return false;

    if (!m_audioUnit->SetFormat(&inputFormat, kAudioUnitScope_Output, kInputBus))
      return false;
  //}

  if (allowMixing)
  {
    // get mixer unit
    if (m_mixerUnit)
    {
      CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error mixer unit already open. double call ?");
      return false;
    }

    m_mixerUnit = new CAUMultiChannelMixer();

    if (!m_mixerUnit->Open(m_audioGraph, kAudioUnitType_Mixer, kAudioUnitSubType_MultiChannelMixer, kAudioUnitManufacturer_Apple))
      return false;

    // set number of input buses
    if (!m_mixerUnit->SetInputBusCount(MAX_CONNECTION_LIMIT))
      return false;

    //if(!m_mixerUnit->SetFormat(&fmt, kAudioUnitScope_Output, kOutputBus))
    //  return false;

    m_mixerUnit->SetBus(0);

    if (!m_audioUnit->GetFormat(&outputFormat, kAudioUnitScope_Input, kOutputBus))
      return false;

    /*
    if(!m_mixerUnit->SetInputBusFormat(MAX_CONNECTION_LIMIT, &outputFormat))
      return false;
    */

    ret =  AUGraphConnectNodeInput(m_audioGraph, m_mixerUnit->GetNode(), 0, m_audioUnit->GetNode(), 0);
    if (ret)
    {
      CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error connecting m_m_mixerNode. Error = %s", GetError(ret).c_str());
      return false;
    }

    // get output unit
    if (m_inputUnit)
    {
      CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error mixer unit already open. double call ?");
      return false;
    }

    m_inputUnit = new CAUOutputDevice();

    if (!m_inputUnit->Open(m_audioGraph, kAudioUnitType_FormatConverter, kAudioUnitSubType_AUConverter, kAudioUnitManufacturer_Apple))
      return false;

    if (!m_inputUnit->SetFormat(&inputFormat, kAudioUnitScope_Input, kOutputBus))
      return false;

    /*
    if(!m_inputUnit->SetFormat(&outputFormat, kAudioUnitScope_Output, kOutputBus))
      return false;
    */

    // configure output unit
    int busNumber = GetFreeBus();

    ret = AUGraphConnectNodeInput(m_audioGraph, m_inputUnit->GetNode(), 0, m_mixerUnit->GetNode(), busNumber);
    if (ret)
    {
      CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error connecting m_converterNode. Error = %s", GetError(ret).c_str());
      return false;
    }

    m_inputUnit->SetBus(busNumber);

    ret = AUGraphUpdate(m_audioGraph, NULL);
    if (ret)
    {
      CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error update graph. Error = %s", GetError(ret).c_str());
      return false;
    }
    ret = AUGraphInitialize(m_audioGraph);
    if (ret)
    {
      CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error initialize graph. Error = %s", GetError(ret).c_str());
      return false;
    }

    // Regenerate audio format and copy format for the Output AU
  }

  ret = AUGraphUpdate(m_audioGraph, NULL);
  if (ret)
  {
    CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error update graph. Error = %s", GetError(ret).c_str());
    return false;
  }

  std::string formatString;
  AudioStreamBasicDescription inputDesc_end, outputDesc_end;
  m_audioUnit->GetFormat(&inputDesc_end, kAudioUnitScope_Input, kOutputBus);
  m_audioUnit->GetFormat(&outputDesc_end, kAudioUnitScope_Output, kInputBus);
  CLog::Log(LOGINFO, "CCoreAudioGraph::Open: Input Stream Format  %s", StreamDescriptionToString(inputDesc_end, formatString));
  CLog::Log(LOGINFO, "CCoreAudioGraph::Open: Output Stream Format %s", StreamDescriptionToString(outputDesc_end, formatString));

  if (m_mixerUnit)
  {
    m_mixerUnit->GetFormat(&inputDesc_end, kAudioUnitScope_Input, kOutputBus);
    m_mixerUnit->GetFormat(&outputDesc_end, kAudioUnitScope_Output, kOutputBus);
    CLog::Log(LOGINFO, "CCoreAudioGraph::Open: Input Stream Format  %s", StreamDescriptionToString(inputDesc_end, formatString));
    CLog::Log(LOGINFO, "CCoreAudioGraph::Open: Output Stream Format %s", StreamDescriptionToString(outputDesc_end, formatString));
  }

  if (m_inputUnit)
  {
    m_inputUnit->GetFormat(&inputDesc_end, kAudioUnitScope_Input, kOutputBus);
    m_inputUnit->GetFormat(&outputDesc_end, kAudioUnitScope_Output, kOutputBus);
    CLog::Log(LOGINFO, "CCoreAudioGraph::Open: Input Stream Format  %s", StreamDescriptionToString(inputDesc_end, formatString));
    CLog::Log(LOGINFO, "CCoreAudioGraph::Open: Output Stream Format %s", StreamDescriptionToString(outputDesc_end, formatString));
  }

  ret = AUGraphInitialize(m_audioGraph);
  if (ret)
  {
    CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error initialize graph. Error = %s", GetError(ret).c_str());
    return false;
  }

  UInt32 bufferFrames = m_audioUnit->GetBufferFrameSize();

  m_audioUnit->SetMaxFramesPerSlice(bufferFrames);
  if (m_inputUnit)
    m_inputUnit->SetMaxFramesPerSlice(bufferFrames);

  SetInputSource(pSource);

  ShowGraph();

  return Start();
}
void setupAUGraph(MyMIDIPlayer *player) {
	
	CheckError(NewAUGraph(&player->graph),
			   "Couldn't open AU Graph");
	
	// 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");
	
	
	AudioComponentDescription instrumentcd = {0};
	instrumentcd.componentManufacturer = kAudioUnitManufacturer_Apple;
	instrumentcd.componentType = kAudioUnitType_MusicDevice;
	instrumentcd.componentSubType = kAudioUnitSubType_Sampler;  // changed!
	
	AUNode instrumentNode;
	CheckError(AUGraphAddNode(player->graph, &instrumentcd, &instrumentNode),
			   "AUGraphAddNode[kAudioUnitSubType_DLSSynth] 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 instrument graph node
	CheckError(AUGraphNodeInfo(player->graph, instrumentNode, NULL, &player->instrumentUnit),
			   "AUGraphNodeInfo failed");
	
	// connect the output source of the instrument AU to the input source of the output node
	CheckError(AUGraphConnectNodeInput(player->graph, instrumentNode, 0, outputNode, 0),
			   "AUGraphConnectNodeInput");
	
	// now initialize the graph (causes resources to be allocated)
	CheckError(AUGraphInitialize(player->graph),
			   "AUGraphInitialize failed");
	
	
	// configure the AUSampler
	// 2nd parameter obviously needs to be a full path on your system, and 3rd param is its length in characters
	CFURLRef presetURL = CFURLCreateFromFileSystemRepresentation(
						    kCFAllocatorDefault,
							"/Users/cadamson/Library/Audio/Presets/Apple/AUSampler/ch12-aupreset.aupreset",
							77,
							false);
	
	// load preset file into a CFDataRef
	CFDataRef presetData = NULL;
	SInt32 errorCode = noErr;
	Boolean gotPresetData =
	CFURLCreateDataAndPropertiesFromResource(kCFAllocatorSystemDefault,
											 presetURL,
											 &presetData,
											 NULL,
											 NULL,
											 &errorCode);
	CheckError(errorCode, "couldn't load .aupreset data");
	CheckError(!gotPresetData, "couldn't load .aupreset data");
	
	// convert this into a property list
	CFPropertyListFormat presetPlistFormat = {0};
	CFErrorRef presetPlistError = NULL;
	CFPropertyListRef presetPlist = CFPropertyListCreateWithData(kCFAllocatorSystemDefault,
																 presetData,
																 kCFPropertyListImmutable,
																 &presetPlistFormat, 
																 &presetPlistError);
	if (presetPlistError) {
		printf ("Couldn't create plist object for .aupreset");
		return;
	}
	
	// set this plist as the kAudioUnitProperty_ClassInfo on _auSampler
	if (presetPlist) {
		CheckError(AudioUnitSetProperty(player->instrumentUnit,
										kAudioUnitProperty_ClassInfo,
										kAudioUnitScope_Global,
										0,
										&presetPlist, 
										sizeof(presetPlist)),
				   "Couldn't set aupreset plist as sampler's class info");
	}

	
	
}
Пример #10
0
void I_InitMusic (void)
{
#ifdef UNIX
	struct stat buf;
	if(stat("/etc/timidity.cfg", &buf) && stat("/etc/timidity/timidity.cfg", &buf))
		Args.AppendArg("-nomusic");
#endif

	if(Args.CheckParm("-nomusic"))
	{
		Printf (PRINT_HIGH, "I_InitMusic: Music playback disabled\n");
		return;
	}

#ifdef OSX

	NewAUGraph(&graph);

	ComponentDescription d;

	d.componentType = kAudioUnitType_MusicDevice;
	d.componentSubType = kAudioUnitSubType_DLSSynth;
	d.componentManufacturer = kAudioUnitManufacturer_Apple;
	d.componentFlags = 0;
	d.componentFlagsMask = 0;
	AUGraphNewNode(graph, &d, 0, NULL, &synth);

	d.componentType = kAudioUnitType_Output;
	d.componentSubType = kAudioUnitSubType_DefaultOutput;
	d.componentManufacturer = kAudioUnitManufacturer_Apple;
	d.componentFlags = 0;
	d.componentFlagsMask = 0;
	AUGraphNewNode(graph, &d, 0, NULL, &output);

	if(AUGraphConnectNodeInput(graph, synth, 0, output, 0) != noErr)
	{
		Printf (PRINT_HIGH, "I_InitMusic: AUGraphConnectNodeInput failed\n");
		return;
	}

	if(AUGraphOpen(graph) != noErr)
	{
		Printf (PRINT_HIGH, "I_InitMusic: AUGraphOpen failed\n");
		return;
	}

	if(AUGraphInitialize(graph) != noErr)
	{
		Printf (PRINT_HIGH, "I_InitMusic: AUGraphInitialize failed\n");
		return;
	}

	if(AUGraphGetNodeInfo(graph, output, NULL, NULL, NULL, &unit) != noErr)
	{
		Printf (PRINT_HIGH, "I_InitMusic: AUGraphGetNodeInfo failed\n");
		return;
	}

	if(NewMusicPlayer(&player) != noErr)
	{
		Printf (PRINT_HIGH, "I_InitMusic: Music player creation failed using AudioToolbox\n");
		return;
	}

	Printf (PRINT_HIGH, "I_InitMusic: Music playback enabled using AudioToolbox\n");

#else

	Printf (PRINT_HIGH, "I_InitMusic: Music playback enabled\n");

#endif

	music_initialized = true;
}
Пример #11
0
    AudioTimeStamp startTime;
    memset(&startTime, 0, sizeof(startTime));
    startTime.mFlags = kAudioTimeStampSampleTimeValid;
    startTime.mSampleTime = -1;
    CoreAudioChkError(AudioUnitSetProperty(*au, kAudioUnitProperty_ScheduleStartTimeStamp,
                                           kAudioUnitScope_Global, 0, &startTime, sizeof(startTime)),
                      "AudioUnitSetproperty StartTime", 0.0);

    return fileDuration;
}

void
CoreAudio_MakeSimpleGraph(AUGraph * theGraph, AudioUnit * fileAU, AudioStreamBasicDescription * fileFormat,
                          AudioFileID audioFile)
{
    CoreAudioChkError(NewAUGraph(theGraph), "NewAUGraph",);

    AudioComponentDescription cd;
    memset(&cd, 0, sizeof(cd));

    /* Initialize and add Output Node */
    cd.componentType = kAudioUnitType_Output;
    cd.componentSubType = kAudioUnitSubType_DefaultOutput;
    cd.componentManufacturer = kAudioUnitManufacturer_Apple;

    AUNode outputNode;
    CoreAudioChkError(AUGraphAddNode(*theGraph, &cd, &outputNode), "AUGraphAddNode Output",);

    /* Initialize and add the AU node */
    AUNode fileNode;
    cd.componentType = kAudioUnitType_Generator;
Пример #12
0
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;
		}
	}
}
JNIEXPORT jint JNICALL Java_com_apple_audio_toolbox_AUGraph_NewAUGraph
  (JNIEnv *, jclass, jint outGraph)
{
	return (jint)NewAUGraph((AUGraph *)outGraph);
}
Пример #14
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);
}
Пример #15
0
bool CCoreAudioGraph::Open(ICoreAudioSource *pSource, AEAudioFormat &format,
  AudioDeviceID deviceId, bool allowMixing, AudioChannelLayoutTag layoutTag)
{
  AudioStreamBasicDescription fmt = {0};
  AudioStreamBasicDescription inputFormat = {0};
  AudioStreamBasicDescription outputFormat = {0};

  m_deviceId = deviceId;
  m_allowMixing = allowMixing;

  OSStatus ret = NewAUGraph(&m_audioGraph);
  if (ret)
  {
    CLog::Log(LOGERROR, "CCoreAudioGraph::Open: "
      "Error create audio grpah. Error = %s", GetError(ret).c_str());
    return false;
  }
  ret = AUGraphOpen(m_audioGraph);
  if (ret)
  {
    CLog::Log(LOGERROR, "CCoreAudioGraph::Open: "
      "Error open audio grpah. Error = %s", GetError(ret).c_str());
    return false;
  }

  // get output unit
  if (m_audioUnit)
  {
    CLog::Log(LOGERROR, "CCoreAudioGraph::Open: "
      "Error audio unit already open. double call ?");
    return false;
  }

  m_audioUnit = new CAUOutputDevice();
  if (!m_audioUnit->Open(m_audioGraph,
    kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple))
    return false;
  m_audioUnit->SetBus(GetFreeBus());

  m_audioUnit->GetFormatDesc(format, &inputFormat, &fmt);

  if (!m_audioUnit->EnableInputOuput())
    return false;

  if (!m_audioUnit->SetCurrentDevice(deviceId))
    return false;

  if (allowMixing)
  {
    delete m_mixMap;
    m_mixMap = CCoreAudioMixMap::CreateMixMap(m_audioUnit, format, layoutTag);

    if (m_mixMap || m_mixMap->IsValid())
    {
      // maximum input channel ber input bus
      //fmt.mChannelsPerFrame = MAXIMUM_MIXER_CHANNELS;

      // get output unit
      if (m_inputUnit)
      {
        CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error mixer unit already open. double call ?");
        return false;
      }

      m_inputUnit = new CAUOutputDevice();

      if (!m_inputUnit->Open(m_audioGraph,
        kAudioUnitType_FormatConverter, kAudioUnitSubType_AUConverter, kAudioUnitManufacturer_Apple))
        return false;

      if (!m_inputUnit->SetFormat(&inputFormat, kAudioUnitScope_Input, kOutputBus))
        return false;

      if (!m_inputUnit->SetFormat(&fmt, kAudioUnitScope_Output, kOutputBus))
        return false;

      // get mixer unit
      if (m_mixerUnit)
      {
        CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error mixer unit already open. double call ?");
        return false;
      }

      m_mixerUnit = new CAUMatrixMixer();

      if (!m_mixerUnit->Open(m_audioGraph,
        kAudioUnitType_Mixer, kAudioUnitSubType_MatrixMixer, kAudioUnitManufacturer_Apple))
        return false;

      // set number of input buses
      if (!m_mixerUnit->SetInputBusCount(MAX_CONNECTION_LIMIT))
        return false;

      // set number of output buses
      if (!m_mixerUnit->SetOutputBusCount(1))
        return false;

      if (!m_mixerUnit->SetInputBusFormat(MAX_CONNECTION_LIMIT, &fmt))
        return false;

      if (!m_mixerUnit->SetFormat(&fmt, kAudioUnitScope_Output, kOutputBus))
        return false;

      ret =  AUGraphConnectNodeInput(m_audioGraph, m_mixerUnit->GetNode(), 0, m_audioUnit->GetNode(), 0);
      if (ret)
      {
        CLog::Log(LOGERROR, "CCoreAudioGraph::Open: "
          "Error connecting m_m_mixerNode. Error = %s", GetError(ret).c_str());
        return false;
      }

      m_mixerUnit->SetBus(0);

      // configure output unit
      int busNumber = GetFreeBus();

      ret = AUGraphConnectNodeInput(m_audioGraph, m_inputUnit->GetNode(), 0, m_mixerUnit->GetNode(), busNumber);
      if (ret)
      {
        CLog::Log(LOGERROR, "CCoreAudioGraph::Open: "
          "Error connecting m_converterNode. Error = %s", GetError(ret).c_str());
        return false;
      }

      m_inputUnit->SetBus(busNumber);

      ret = AUGraphUpdate(m_audioGraph, NULL);
      if (ret)
      {
        CLog::Log(LOGERROR, "CCoreAudioGraph::Open: "
          "Error update graph. Error = %s", GetError(ret).c_str());
        return false;
      }
      ret = AUGraphInitialize(m_audioGraph);
      if (ret)
      {
        CLog::Log(LOGERROR, "CCoreAudioGraph::Open: "
          "Error initialize graph. Error = %s", GetError(ret).c_str());
        return false;
      }

      // Update format structure to reflect the desired format from the mixer
      // The output format of the mixer is identical to the input format, except for the channel count
      fmt.mChannelsPerFrame = m_mixMap->GetOutputChannels();

      UInt32 inputNumber = m_inputUnit->GetBus();
      int channelOffset = GetMixerChannelOffset(inputNumber);
      if (!CCoreAudioMixMap::SetMixingMatrix(m_mixerUnit, m_mixMap, &inputFormat, &fmt, channelOffset))
        return false;

      // Regenerate audio format and copy format for the Output AU
      outputFormat = fmt;
    }
    else
    {
      outputFormat = inputFormat;
    }

  }
  else
  {
    outputFormat = inputFormat;
  }

  if (!m_audioUnit->SetFormat(&outputFormat, kAudioUnitScope_Input, kOutputBus))
  {
    CLog::Log(LOGERROR, "CCoreAudioGraph::Open: "
      "Error setting input format on audio device. Channel count %d, set it to %d",
      (int)outputFormat.mChannelsPerFrame, format.m_channelLayout.Count());
    outputFormat.mChannelsPerFrame = format.m_channelLayout.Count();
    if (!m_audioUnit->SetFormat(&outputFormat, kAudioUnitScope_Input, kOutputBus))
      return false;
  }

  std::string formatString;
  // asume we are in dd-wave mode
  if (!m_inputUnit)
  {
    if (!m_audioUnit->SetFormat(&inputFormat, kAudioUnitScope_Output, kInputBus))
    {
      CLog::Log(LOGERROR, "CCoreAudioGraph::Open: "
        "Error setting Device Output Stream Format %s",
        StreamDescriptionToString(inputFormat, formatString));
    }
  }

  ret = AUGraphUpdate(m_audioGraph, NULL);
  if (ret)
  {
    CLog::Log(LOGERROR, "CCoreAudioGraph::Open: "
      "Error update graph. Error = %s", GetError(ret).c_str());
    return false;
  }

  AudioStreamBasicDescription inputDesc_end, outputDesc_end;
  m_audioUnit->GetFormat(&inputDesc_end, kAudioUnitScope_Input, kOutputBus);
  m_audioUnit->GetFormat(&outputDesc_end, kAudioUnitScope_Output, kInputBus);
  CLog::Log(LOGINFO, "CCoreAudioGraph::Open: Input Stream Format  %s",
    StreamDescriptionToString(inputDesc_end, formatString));
  CLog::Log(LOGINFO, "CCoreAudioGraph::Open: Output Stream Format %s",
    StreamDescriptionToString(outputDesc_end, formatString));

  if (m_mixerUnit)
  {
    m_mixerUnit->GetFormat(&inputDesc_end, kAudioUnitScope_Input, kOutputBus);
    m_mixerUnit->GetFormat(&outputDesc_end, kAudioUnitScope_Output, kOutputBus);
    CLog::Log(LOGINFO, "CCoreAudioGraph::Open: Input Stream Format  %s",
      StreamDescriptionToString(inputDesc_end, formatString));
    CLog::Log(LOGINFO, "CCoreAudioGraph::Open: Output Stream Format %s",
      StreamDescriptionToString(outputDesc_end, formatString));
  }

  if (m_inputUnit)
  {
    m_inputUnit->GetFormat(&inputDesc_end, kAudioUnitScope_Input, kOutputBus);
    m_inputUnit->GetFormat(&outputDesc_end, kAudioUnitScope_Output, kOutputBus);
    CLog::Log(LOGINFO, "CCoreAudioGraph::Open: Input Stream Format  %s",
      StreamDescriptionToString(inputDesc_end, formatString));
    CLog::Log(LOGINFO, "CCoreAudioGraph::Open: Output Stream Format %s",
      StreamDescriptionToString(outputDesc_end, formatString));
  }

  ret = AUGraphInitialize(m_audioGraph);
  if (ret)
  {
    CLog::Log(LOGERROR, "CCoreAudioGraph::Open: "
      "Error initialize graph. Error = %s", GetError(ret).c_str());
    return false;
  }

  UInt32 bufferFrames = m_audioUnit->GetBufferFrameSize();
  if (!m_audioUnit->SetMaxFramesPerSlice(bufferFrames))
    return false;

  SetInputSource(pSource);

  return Start();
}
Пример #16
0
int main(int argc, char *argv[])
{
    WindowRef window;
    HIViewRef content;
    HIViewRef combo;
    HIViewRef group;
    HIViewRef check;
    HIViewRef text;
    HIViewRef slider;
    HIViewRef quit;

    MenuRef menu;
    HIRect rect;

    // Window bounds

    Rect bounds = {0, 0, 436, 590};

    // Create window

    CreateNewWindow(kDocumentWindowClass,
                    kWindowStandardFloatingAttributes |
                    kWindowStandardHandlerAttribute |
		    kWindowInWindowMenuAttribute |
                    kWindowCompositingAttribute,
                    &bounds, &window);

    // Set the title

    SetWindowTitleWithCFString(window, CFSTR("Accordion"));

    // Create an application menu

    CreateNewMenu(0, 0, &menu);

    // Set menu title

    SetMenuTitleWithCFString(menu,
	CFStringCreateWithPascalString(kCFAllocatorDefault,
                                       "\p\024",
                                       kCFStringEncodingMacRoman));
    // Create an about item

    InsertMenuItemTextWithCFString(menu, CFSTR("About Accordion"),
                                   0, 0, kHICommandAbout);

    // Insert the menu

    InsertMenu(menu, 0);

    // Create a standard window menu

    CreateStandardWindowMenu(0, &menu);

    // Insert the menu

    InsertMenu(menu, 0);

    // Show and position the window

    ShowWindow(window);
    RepositionWindow(window, NULL, kWindowCascadeOnMainScreen);

    // Find the window content

    HIViewFindByID(HIViewGetRoot(window),
                   kHIViewWindowContentID,
                   &content);

    // Set bounds for group box

    bounds.bottom = 92;
    bounds.right  = 550;

    // Create group box

    CreateGroupBoxControl(window, &bounds, NULL, true, &group);

    // Place in the window

    HIViewAddSubview(content, group);
    HIViewPlaceInSuperviewAt(group, 20, 20);

    // Bounds of text

    bounds.bottom = 16;
    bounds.right = 74;

    // Create static text

    CreateStaticTextControl(window, &bounds, CFSTR("Instrument:"),
			    NULL, &text);

    // Place in the group box

    HIViewAddSubview(group, text);
    HIViewPlaceInSuperviewAt(text, 16, 18);

    // Bounds of combo box

    rect.size.height = 20;
    rect.size.width = 168;    

    // Create combo box

    HIComboBoxCreate(&rect, CFSTR(" Accordion"), NULL, NULL,
                     kHIComboBoxStandardAttributes,
                     &combo);

    // Set visible and set command ID

    HIViewSetVisible(combo, true);
    HIViewSetCommandID(combo, kCommandInst); 

    // Add the instruments

    for (int i = 0; i < Length(instruments); i++)
    {
        HIComboBoxAppendTextItem(combo,
            CFStringCreateWithCString(kCFAllocatorDefault,
                                      instruments[i],
                                      kCFStringEncodingMacRoman), NULL);

        // Set the current instrument

        if (strcmp(instruments[i], " Accordion") == 0)
            instrument = i;
    }

    // Place in the group box

    HIViewAddSubview(group, combo);
    HIViewPlaceInSuperviewAt(combo, 102, 16);

    // Bounds of check box

    bounds.bottom = 18;
    bounds.right = 121;

    // Create check box

    CreateCheckBoxControl(window, &bounds, CFSTR("Reverse"),
                          false, true, &check);

    // Set the control ID and the command ID

    HIViewSetID(check, kHIViewIDReverse);
    HIViewSetCommandID(check, kCommandReverse); 

    // Place in the group box

    HIViewAddSubview(group, check);
    HIViewPlaceInSuperviewAt(check, 286, 17);

    // Bounds of text

    bounds.bottom = 16;
    bounds.right  = 32;

    // Create static text

    CreateStaticTextControl(window, &bounds, CFSTR("Key:"), NULL, &text);

    // Place in the group box

    HIViewAddSubview(group, text);
    HIViewPlaceInSuperviewAt(text, 400, 18);

    // Bounds of combo box

    rect.size.width = 90;

    // Create combo box

    HIComboBoxCreate(&rect, CFSTR(" A/D/G"), NULL, NULL,
                     kHIComboBoxStandardAttributes,
                     &combo);

    // Set visible and set command ID

    HIViewSetVisible(combo, true);
    HIViewSetID(combo, kHIViewIDKey);
    HIViewSetCommandID(combo, kCommandKey); 

    // Add keys

    for (int i = 0; i < Length(keys); i++)
    {
        HIComboBoxAppendTextItem(combo,
            CFStringCreateWithCString(kCFAllocatorDefault,
                                      keys[i],
                                      kCFStringEncodingMacRoman), NULL);

        // Set current key

        if (strcmp(keys[i], " A/D/G") == 0)
            key = i;
    }

    // Place in the group box

    HIViewAddSubview(group, combo);
    HIViewPlaceInSuperviewAt(combo, 440, 16);

    // Bounds of text

    bounds.bottom = 16;
    bounds.right  = 54;

    // Create static text

    CreateStaticTextControl(window, &bounds, CFSTR("Volume:"), NULL, &text);

    // Place in the group box

    HIViewAddSubview(group, text);
    HIViewPlaceInSuperviewAt(text, 16, 56);
    
    // Bounds of slider

    bounds.bottom = 16;
    bounds.right  = 168;

    // Create slider

    CreateSliderControl(window, &bounds, MAXVOL, 0, MAXVOL,
                        kControlSliderDoesNotPoint, 0, false, NULL, &slider);

    // Set command ID

    HIViewSetCommandID(slider, kCommandVolume); 

    // Place in the group box

    HIViewAddSubview(group, slider);
    HIViewPlaceInSuperviewAt(slider, 100, 58);

    // Bounds of check box

    bounds.bottom = 18;
    bounds.right = 121;

    // Create check box

    CreateCheckBoxControl(window, &bounds, CFSTR("Notes"),
                          false, true, &check);

    // Set the control ID and the command ID

    HIViewSetID(check, kHIViewIDNote);
    HIViewSetCommandID(check, kCommandNote); 

    // Place in the group box

    HIViewAddSubview(group, check);
    HIViewPlaceInSuperviewAt(check, 286, 56);

    // Bounds of push button

    bounds.bottom = 20;
    bounds.right  = 90;

    // Create push button

    CreatePushButtonControl(window, &bounds, CFSTR("Quit"), &quit);

    // Set command ID

    HIViewSetCommandID(quit, kHICommandQuit); 

    // Place in the group box

    HIViewAddSubview(group, quit);
    HIViewPlaceInSuperviewAt(quit, 440, 54);

    // Group box bounds

    bounds.bottom = 48;
    bounds.right  = 550;

    // Create group box

    CreateGroupBoxControl(window, &bounds, NULL, true, &group);

    // Place in the window

    HIViewAddSubview(content, group);
    HIViewPlaceInSuperviewAt(group, 20, 132);

    // Font style

    ControlFontStyleRec style;
    style.flags = kControlUseFontMask|kControlUseJustMask;
    style.font = kControlFontBigSystemFont;
    style.just = teCenter;

    // Bounds of text
    
    bounds.bottom = 16;
    bounds.right  = 550;

    // Create static text

    CreateStaticTextControl(window, &bounds, CFSTR("Accordion"),
                            &style, &text);

    // Place in the group box

    HIViewAddSubview(group, text);
    HIViewPlaceInSuperviewAt(text, 0, 8);

    // Bounds of text

    bounds.bottom = 16;
    bounds.right  = 550;

    // Create static text

    CreateStaticTextControl(window, &bounds,
                            CFSTR("Play accordion on your keyboard"),
                            &style, &text);

    // Place in the group box

    HIViewAddSubview(group, text);
    HIViewPlaceInSuperviewAt(text, 0, 24);

    // Group box bounds

    bounds.bottom = 196;
    bounds.right  = 550;

    // Create group box

    CreateGroupBoxControl(window, &bounds, NULL, true, &group);

    // Place in the window

    HIViewAddSubview(content, group);
    HIViewPlaceInSuperviewAt(group, 20, 200);

    // Button bounds

    bounds.bottom = SIZE;
    bounds.right  = SIZE;

    // Create row of bass buttons

    for (int i = 0; i < Length(bassdisplay); i++)
    {
	int x = 15 + 44 * i;
	int y = 15;

	// Create button

	CreateBevelButtonControl(window, &bounds, NULL,
				 kControlBevelButtonNormalBevel,
				 kControlBehaviorPushbutton,
				 NULL, 0, 0, 0, &bassdisplay[i]);

	// Place in the group box

	HIViewAddSubview(group, bassdisplay[i]);
	HIViewPlaceInSuperviewAt(bassdisplay[i], x, y);
    }

    // Create three rows of buttons

    for (int i = 0; i < Length(display); i++)
    {
	for (int j = 0; j < ((i == 1)? Length(display[i]):
			 Length(display[i]) - 1); j++)
	{
	    int x = (i == 1)? 37 + 44 * j: 59 + 44 * j;
	    int y = 59 + 44 * i;

	    // Create button

	    CreateBevelButtonControl(window, &bounds, NULL,
				     kControlBevelButtonNormalBevel,
				     kControlBehaviorPushbutton,
				     NULL, 0, 0, 0, &display[i][j]);

	    // Place in the group box

	    HIViewAddSubview(group, display[i][j]);
	    HIViewPlaceInSuperviewAt(display[i][j], x, y);
        }
    }

    // Create spacebar button

    CreateBevelButtonControl(window, &bounds, NULL,
			     kControlBevelButtonNormalBevel,
			     kControlBehaviorPushbutton,
			     NULL, 0, 0, 0, &spacebar);

    // Place in the group box

    HIViewAddSubview(group, spacebar);
    HIViewPlaceInSuperviewAt(spacebar, 16, 147);

    // Group box bounds, wider than the window to hide rounded corners

    bounds.bottom = 20;
    bounds.right = 598;

    // Create group box for fake status bar

    CreateGroupBoxControl(window, &bounds, NULL, false, &group);

    // Place in window at negative offset to hide rounded corners

    HIViewAddSubview(content, group);
    HIViewPlaceInSuperviewAt(group, -4, 416);

    // Text bounds

    bounds.bottom = 16;
    bounds.right  = 590;

    // Font style

    style.flags = kControlUseFontMask|kControlUseJustMask;
    style.font = kControlFontSmallSystemFont;
    style.just = teCenter;

    // Create static text

    CreateStaticTextControl(window, &bounds,
        CFSTR("Press the keyboard keys as accordion buttons "
              "and the space bar as the bellows. 3rd button start."),
                            &style, &text);

    // Place in group box

    HIViewAddSubview(group, text);
    HIViewPlaceInSuperviewAt(text, 0, 2);

    // Application events type spec

    EventTypeSpec applicationEvents[] =
        {{kEventClassApplication, kEventAppFrontSwitched}};

    // Install event handler

    InstallApplicationEventHandler(NewEventHandlerUPP(ApplicationHandler),
                                   Length(applicationEvents), applicationEvents,
                                   NULL, NULL);

    // Mouse events type spec

    EventTypeSpec mouseEvents[] =
	{{kEventClassMouse, kEventMouseDown}};

    // Install event handler on the event dispatcher, so that we can
    // see mouse events before the default handler gets them

    InstallEventHandler(GetEventDispatcherTarget(),
                        NewEventHandlerUPP(MouseHandler),
                        Length(mouseEvents), mouseEvents,
                        NULL, NULL);

    // Window events type spec

    EventTypeSpec windowEvents[] =
        {{kEventClassWindow, kEventWindowClose}};

    // Install event handler

    InstallWindowEventHandler(window, NewEventHandlerUPP(WindowHandler),
                              Length(windowEvents), windowEvents,
                              NULL, NULL);

    // Combo box events type spec

    EventTypeSpec comboBoxEvents[] =
        {{kEventClassHIComboBox, kEventComboBoxListItemSelected}};

    // Install event handler

    InstallApplicationEventHandler(NewEventHandlerUPP(ComboBoxHandler),
                                   Length(comboBoxEvents), comboBoxEvents,
                                   NULL, NULL);

    // Command events type spec

    EventTypeSpec commandEvents[] =
        {{kEventClassCommand, kEventCommandProcess}};

    // Install event handler

    InstallApplicationEventHandler(NewEventHandlerUPP(CommandHandler),
                                   Length(commandEvents), commandEvents,
                                   NULL, NULL);

    // Keyboard events type spec

    EventTypeSpec keyboardEvents[] =
        {{kEventClassKeyboard, kEventRawKeyDown},
         {kEventClassKeyboard, kEventRawKeyUp},
         {kEventClassKeyboard, kEventRawKeyModifiersChanged}};

    // Install event handler on the event dispatcher

    InstallEventHandler(GetEventDispatcherTarget(),
			NewEventHandlerUPP(KeyboardHandler),
			Length(keyboardEvents), keyboardEvents,
			NULL, NULL);

    // Audio Unit graph

    AUGraph graph;

    // Audio Unit synthesizer and output node

    AUNode synthNode;
    AUNode outNode;

    // Component description

    ComponentDescription cd;
    cd.componentManufacturer = kAudioUnitManufacturer_Apple;
    cd.componentFlags = 0;
    cd.componentFlagsMask = 0;

    do
    {
	// New AU graph

	OSStatus status = NewAUGraph(&graph);

	if (status != noErr)
	{
	    DisplayAlert(CFSTR("NewAUGraph"), 
			 CFSTR("Can't create a new AUGraph"),
			 status);
	    break;
	}

	// Synthesizer

	cd.componentType = kAudioUnitType_MusicDevice;
	cd.componentSubType = kAudioUnitSubType_DLSSynth;

	// New synthesizer node

	status = AUGraphNewNode(graph, &cd, 0, NULL, &synthNode);

	if (status != noErr)
	{
	    DisplayAlert(CFSTR("AUGraphNewNode"), 
			 CFSTR("Can't create a new  AUGraph node"),
			 status);
	    break;
	}

	// Output

	cd.componentType = kAudioUnitType_Output;
	cd.componentSubType = kAudioUnitSubType_DefaultOutput;
 
	// New output node

	status = AUGraphNewNode(graph, &cd, 0, NULL, &outNode);

	if (status != noErr)
	{
	    DisplayAlert(CFSTR("AUGraphNewNode"), 
			 CFSTR("Can't create a new  AUGraph node"),
			 status);
	    break;
	}

	// Open graph

	status = AUGraphOpen(graph);

	if (status != noErr)
	{
	    DisplayAlert(CFSTR("AUGraphOpen"), 
			 CFSTR("Can't open AUGraph"),
			 status);
	    break;
	}

	// Connect synthesizer node to output node

	status = AUGraphConnectNodeInput(graph, synthNode, 0, outNode, 0);

	if (status != noErr)
	{
	    DisplayAlert(CFSTR("AUGraphConnectNodeInput"), 
			 CFSTR("Can't connect AUGraph input node"),
			 status);
	    break;
	}

	// Get a synthesizer unit

	status =
	    AUGraphGetNodeInfo(graph, synthNode, NULL, 0, NULL, &synthUnit);

	if (status != noErr)
	{
	    DisplayAlert(CFSTR("AUGraphGetNodeInfo"), 
			 CFSTR("Can't get AUGraph node info"),
			 status);
	    break;
	}

	// Initialise

	status = AUGraphInitialize(graph);

	if (status != noErr)
	{
	    DisplayAlert(CFSTR("AUGraphInitialize"), 
			 CFSTR("Can't initialize AUGraph"),
			 status);
	    break;
	}

	// Start

	status = AUGraphStart(graph);

	if (status != noErr)
	{
	    DisplayAlert(CFSTR("AUGraphStart"), 
			 CFSTR("Can't start AUGraph"),
			 status);
	    break;
	}

	// Show the graph

	//     CAShow(graph);

    } while (false);

    // Change instrument

    ChangeInstrument(instrument);

    // Run the application event loop

    RunApplicationEventLoop();

    // Stop the graph

    AUGraphStop(graph);

    // Dispose of the graph

    DisposeAUGraph(graph);

    // Exit

    return 0;
}
Пример #17
0
int MidiDriver_CORE::open() {
	OSStatus err = 0;

	if (isOpen())
		return MERR_ALREADY_OPEN;

	// Open the Music Device.
	RequireNoErr(NewAUGraph(&_auGraph));

	AUNode outputNode, synthNode;
#if USE_DEPRECATED_COREAUDIO_API
	ComponentDescription desc;
#else
	AudioComponentDescription desc;
#endif

	// The default output device
	desc.componentType = kAudioUnitType_Output;
	desc.componentSubType = kAudioUnitSubType_DefaultOutput;
	desc.componentManufacturer = kAudioUnitManufacturer_Apple;
	desc.componentFlags = 0;
	desc.componentFlagsMask = 0;
#if USE_DEPRECATED_COREAUDIO_API
	RequireNoErr(AUGraphNewNode(_auGraph, &desc, 0, NULL, &outputNode));
#else
	RequireNoErr(AUGraphAddNode(_auGraph, &desc, &outputNode));
#endif

	// The built-in default (softsynth) music device
	desc.componentType = kAudioUnitType_MusicDevice;
	desc.componentSubType = kAudioUnitSubType_DLSSynth;
	desc.componentManufacturer = kAudioUnitManufacturer_Apple;
#if USE_DEPRECATED_COREAUDIO_API
	RequireNoErr(AUGraphNewNode(_auGraph, &desc, 0, NULL, &synthNode));
#else
	RequireNoErr(AUGraphAddNode(_auGraph, &desc, &synthNode));
#endif

	// Connect the softsynth to the default output
	RequireNoErr(AUGraphConnectNodeInput(_auGraph, synthNode, 0, outputNode, 0));

	// Open and initialize the whole graph
	RequireNoErr(AUGraphOpen(_auGraph));
	RequireNoErr(AUGraphInitialize(_auGraph));

	// Get the music device from the graph.
#if USE_DEPRECATED_COREAUDIO_API
	RequireNoErr(AUGraphGetNodeInfo(_auGraph, synthNode, NULL, NULL, NULL, &_synth));
#else
	RequireNoErr(AUGraphNodeInfo(_auGraph, synthNode, NULL, &_synth));
#endif

	// Load custom soundfont, if specified
	if (ConfMan.hasKey("soundfont")) {
		FSRef	fsref;
		FSSpec	fsSpec;
		const char *soundfont = ConfMan.get("soundfont").c_str();

		err = FSPathMakeRef ((const byte *)soundfont, &fsref, NULL);

		if (err == noErr) {
			err = FSGetCatalogInfo (&fsref, kFSCatInfoNone, NULL, NULL, &fsSpec, NULL);
		}

		if (err == noErr) {
			// TODO: We should really check here whether the file contains an
			// actual soundfont...
			err = AudioUnitSetProperty (
				_synth,
				kMusicDeviceProperty_SoundBankFSSpec, kAudioUnitScope_Global,
				0,
				&fsSpec, sizeof(fsSpec)
			);
		}

		if (err != noErr)
			warning("Failed loading custom sound font '%s' (error %ld)\n", soundfont, (long)err);
	}

#ifdef COREAUDIO_DISABLE_REVERB
	// Disable reverb mode, as that sucks up a lot of CPU power, which can
	// be painful on low end machines.
	// TODO: Make this customizable via a config key?
	UInt32 usesReverb = 0;
	AudioUnitSetProperty (_synth, kMusicDeviceProperty_UsesInternalReverb,
		kAudioUnitScope_Global, 0, &usesReverb, sizeof (usesReverb));
#endif


	// Finally: Start the graph!
	RequireNoErr(AUGraphStart(_auGraph));

	return 0;

bail:
	if (_auGraph) {
		AUGraphStop(_auGraph);
		DisposeAUGraph(_auGraph);
		_auGraph = 0;
	}
	return MERR_CANNOT_CONNECT;
}
Пример #18
0
MidiDevice *
openMidiDevice (int errorLevel, const char *device) {
  MidiDevice *midi;
  int result;
  AUNode synthNode, outNode;
  ComponentDescription cd;
  UInt32 propVal;

  if (!(midi = malloc(sizeof(*midi)))) {
    logMallocError();
    return NULL;
  }

  /* Create a graph with a software synth and a default output unit. */

  cd.componentManufacturer = kAudioUnitManufacturer_Apple;
  cd.componentFlags = 0;
  cd.componentFlagsMask = 0;

  if ((result = NewAUGraph(&midi->graph)) != noErr) {
    logMessage(errorLevel, "Can't create audio graph component: %d", result);
    goto err;
  }

  cd.componentType = kAudioUnitType_MusicDevice;
  cd.componentSubType = kAudioUnitSubType_DLSSynth;
  if ((result = AUGraphNewNode(midi->graph, &cd, 0, NULL, &synthNode))
      != noErr) {
    logMessage(errorLevel, "Can't create software synthersizer component: %d",
	       result);
    goto err;
  }

  cd.componentType = kAudioUnitType_Output;
  cd.componentSubType = kAudioUnitSubType_DefaultOutput;
  if ((result = AUGraphNewNode(midi->graph, &cd, 0, NULL, &outNode))
      != noErr) {
    logMessage(errorLevel, "Can't create default output audio component: %d",
	       result);
    goto err;
  }

  if ((result = AUGraphOpen(midi->graph)) != noErr) {
    logMessage(errorLevel, "Can't open audio graph component: %d", result);
    goto err;
  }

  if ((result = AUGraphConnectNodeInput(midi->graph, synthNode, 0, outNode, 0))
      != noErr) {
    logMessage(errorLevel, "Can't connect synth audio component to output: %d",
	       result);
    goto err;
  }

  if ((result = AUGraphGetNodeInfo(midi->graph, synthNode, 0, 0, 0,
				   &midi->synth)) != noErr) {
    logMessage(errorLevel, "Can't get audio component for software synth: %d",
	       result);
    goto err;
  }

  if ((result = AUGraphInitialize(midi->graph)) != noErr) {
    logMessage(errorLevel, "Can't initialize audio graph: %d", result);
    goto err;
  }

  /* Turn off the reverb.  The value range is -120 to 40 dB. */
  propVal = false;
  if ((result = AudioUnitSetProperty(midi->synth,
				     kMusicDeviceProperty_UsesInternalReverb,
				     kAudioUnitScope_Global, 0,
				     &propVal, sizeof(propVal)))
      != noErr) {
    /* So, having reverb isn't that critical, is it? */
    logMessage(LOG_DEBUG, "Can't turn of software synth reverb: %d",
	       result);
  }

  /* TODO: Maybe just start the graph when we are going to use it? */
  if ((result = AUGraphStart(midi->graph)) != noErr) {
    logMessage(errorLevel, "Can't start audio graph component: %d", result);
    goto err;
  }

  return midi;

 err:
  if (midi->graph)
    DisposeAUGraph(midi->graph);
  free(midi);
  return NULL;
}
void CreateMyAUGraph(MyAUGraphPlayer *player)
{
	
	// create a new AUGraph
	CheckError(NewAUGraph(&player->graph),
			   "NewAUGraph failed");
	
	// generate description that will match default output
	//	ComponentDescription outputcd = {0};
	//	outputcd.componentType = kAudioUnitType_Output;
	//	outputcd.componentSubType = kAudioUnitSubType_DefaultOutput;
	//	outputcd.componentManufacturer = kAudioUnitManufacturer_Apple;
	//	
	//	Component comp = FindNextComponent(NULL, &outputcd);
	//	if (comp == NULL) {
	//		printf ("can't get output unit"); exit (-1);
	//	}
	
	AudioComponentDescription outputcd = {0};
	outputcd.componentType = kAudioUnitType_Output;
	outputcd.componentSubType = kAudioUnitSubType_DefaultOutput;
	outputcd.componentManufacturer = kAudioUnitManufacturer_Apple;
	
	AudioComponent comp = AudioComponentFindNext(NULL, &outputcd);
	if (comp == NULL) {
		printf ("can't get output unit"); exit (-1);
	}
	
	
	// adds a node with above description to the graph
	AUNode outputNode;
	CheckError(AUGraphAddNode(player->graph, &outputcd, &outputNode),
			   "AUGraphAddNode[kAudioUnitSubType_DefaultOutput] failed");
	
#ifdef PART_II
	
	// add a mixer to the graph,
	AudioComponentDescription mixercd = {0};
	mixercd.componentType = kAudioUnitType_Mixer;
	mixercd.componentSubType = kAudioUnitSubType_StereoMixer; // doesn't work: kAudioUnitSubType_MatrixMixer
	mixercd.componentManufacturer = kAudioUnitManufacturer_Apple;
	AUNode mixerNode;
	CheckError(AUGraphAddNode(player->graph, &mixercd, &mixerNode),
			   "AUGraphAddNode[kAudioUnitSubType_StereoMixer] failed");
	
	// adds a node with above description to the graph
	AudioComponentDescription speechcd = {0};
	speechcd.componentType = kAudioUnitType_Generator;
	speechcd.componentSubType = kAudioUnitSubType_SpeechSynthesis;
	speechcd.componentManufacturer = kAudioUnitManufacturer_Apple;
	AUNode speechNode;
	CheckError(AUGraphAddNode(player->graph, &speechcd, &speechNode),
			   "AUGraphAddNode[kAudioUnitSubType_AudioFilePlayer] 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 objects for the various nodes
	CheckError(AUGraphNodeInfo(player->graph, outputNode, NULL, &player->outputUnit),
			   "AUGraphNodeInfo failed");
	CheckError(AUGraphNodeInfo(player->graph, speechNode, NULL, &player->speechUnit),
			   "AUGraphNodeInfo failed");
	AudioUnit mixerUnit;
	CheckError(AUGraphNodeInfo(player->graph, mixerNode, NULL, &mixerUnit),
			   "AUGraphNodeInfo failed");
	
	// set ASBDs here
	UInt32 propertySize = sizeof (AudioStreamBasicDescription);
	CheckError(AudioUnitSetProperty(player->outputUnit,
									kAudioUnitProperty_StreamFormat,
									kAudioUnitScope_Input,
									0,
									&player->streamFormat,
									propertySize),
			   "Couldn't set stream format on output unit");
	
	// problem: badComponentInstance (-2147450879)
	CheckError(AudioUnitSetProperty(mixerUnit,
									kAudioUnitProperty_StreamFormat,
									kAudioUnitScope_Input,
									0,
									&player->streamFormat,
									propertySize),
			   "Couldn't set stream format on mixer unit bus 0");
	CheckError(AudioUnitSetProperty(mixerUnit,
									kAudioUnitProperty_StreamFormat,
									kAudioUnitScope_Input,
									1,
									&player->streamFormat,
									propertySize),
			   "Couldn't set stream format on mixer unit bus 1");
	
	
	// connections
	// mixer output scope / bus 0 to outputUnit input scope / bus 0
	// mixer input scope / bus 0 to render callback (from ringbuffer, which in turn is from inputUnit)
	// mixer input scope / bus 1 to speech unit output scope / bus 0
	
	CheckError(AUGraphConnectNodeInput(player->graph, mixerNode, 0, outputNode, 0),
			   "Couldn't connect mixer output(0) to outputNode (0)");
	CheckError(AUGraphConnectNodeInput(player->graph, speechNode, 0, mixerNode, 1),
			   "Couldn't connect speech synth unit output (0) to mixer input (1)");
	AURenderCallbackStruct callbackStruct;
	callbackStruct.inputProc = GraphRenderProc; 
	callbackStruct.inputProcRefCon = player;
	CheckError(AudioUnitSetProperty(mixerUnit,
									kAudioUnitProperty_SetRenderCallback,
									kAudioUnitScope_Global,
									0,
									&callbackStruct,
									sizeof(callbackStruct)),
			   "Couldn't set render callback on mixer unit");
	
	
#else	
	
	// 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 output graph node
	CheckError(AUGraphNodeInfo(player->graph, outputNode, NULL, &player->outputUnit),
			   "AUGraphNodeInfo failed");
	
	// set the stream format on the output unit's input scope
	UInt32 propertySize = sizeof (AudioStreamBasicDescription);
	CheckError(AudioUnitSetProperty(player->outputUnit,
									kAudioUnitProperty_StreamFormat,
									kAudioUnitScope_Input,
									0,
									&player->streamFormat,
									propertySize),
			   "Couldn't set stream format on output unit");
	
	AURenderCallbackStruct callbackStruct;
	callbackStruct.inputProc = GraphRenderProc; 
	callbackStruct.inputProcRefCon = player;
	
	CheckError(AudioUnitSetProperty(player->outputUnit,
									kAudioUnitProperty_SetRenderCallback,
									kAudioUnitScope_Global,
									0,
									&callbackStruct,
									sizeof(callbackStruct)),
			   "Couldn't set render callback on output unit");
	
#endif
	
	
	// now initialize the graph (causes resources to be allocated)
	CheckError(AUGraphInitialize(player->graph),
			   "AUGraphInitialize failed");
	
	player->firstOutputSampleTime = -1;
	
	printf ("Bottom of CreateSimpleAUGraph()\n");
}
Пример #20
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);
}
Пример #21
0
OutputImplAudioUnit::OutputImplAudioUnit()
	: mAvailableBuses(), OutputImpl()
{

	OSStatus err = noErr;

	NewAUGraph( &mGraph );
	
	AudioComponentDescription cd;
	cd.componentManufacturer = kAudioUnitManufacturer_Apple;
	cd.componentFlags = 0;
	cd.componentFlagsMask = 0;
	
	//output node
	cd.componentType = kAudioUnitType_Output;
	cd.componentSubType = CINDER_AUDIOUNIT_OUTPUT_TYPE;
	
	//connect & setup
	AUGraphOpen( mGraph );
	
	//initialize component - todo add error checking
	if( AUGraphAddNode( mGraph, &cd, &mOutputNode ) != noErr ) {
		std::cout << "Error 1!" << std::endl;
	}
	
	if( AUGraphNodeInfo( mGraph, mOutputNode, NULL, &mOutputUnit ) != noErr ) {
		std::cout << "Error 2!" << std::endl;	
	}
	UInt32 dsize;
#if defined( CINDER_MAC )
	//get default output device id and set it as the outdevice for the output unit, unnessary on the iphone
	dsize = sizeof( AudioDeviceID );
	err = AudioHardwareGetProperty( kAudioHardwarePropertyDefaultOutputDevice, &dsize, &mOutputDeviceId );
	if( err != noErr ) {
		std::cout << "Error getting default output device" << std::endl;
	}
	
	err = AudioUnitSetProperty( mOutputUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &mOutputDeviceId, sizeof( mOutputDeviceId ) );
	if( err != noErr ) {
		std::cout << "Error setting current output device" << std::endl;
	}
#endif
	
	//Tell the output unit not to reset timestamps 
	//Otherwise sample rate changes will cause sync los
	UInt32 startAtZero = 0;
	err = AudioUnitSetProperty( mOutputUnit, kAudioOutputUnitProperty_StartTimestampsAtZero, kAudioUnitScope_Global, 0, &startAtZero, sizeof( startAtZero ) );
	if( err != noErr ) {
		std::cout << "Error telling output unit not to reset timestamps" << std::endl;
	}
	
	//stereo mixer node
	cd.componentType = kAudioUnitType_Mixer;
	cd.componentSubType = kAudioUnitSubType_MultiChannelMixer;//kAudioUnitSubType_StereoMixer;
	AUGraphAddNode( mGraph, &cd, &mMixerNode );
	
	//setup mixer AU
	err = AUGraphNodeInfo( mGraph, mMixerNode, NULL, &mMixerUnit );
	if( err ) {
		std::cout << "Error 4" << std::endl;
	}
	
	//TODO: cleanup error checking in all of this
	
	//check the element count, if it's less than our default element count, increase, or else just leave it alone
	err = AudioUnitGetProperty( mMixerUnit, kAudioUnitProperty_ElementCount, kAudioUnitScope_Input, 0, &mNumberBuses, &dsize );
	if( err ) {
		std::cout << "Error getting mixer unit input elements" << std::endl;
	}
	
	if( mNumberBuses < sDefaultNumberBuses ) {
		mNumberBuses = sDefaultNumberBuses;
		err = AudioUnitSetProperty( mMixerUnit, kAudioUnitProperty_ElementCount, kAudioUnitScope_Input, 0, &mNumberBuses, sizeof(mNumberBuses) );
		if( err ) {
			std::cout << "Error setting mixer unit input elements" << std::endl;
		}
	}
	
	for( uint32_t i = 1; i <= mNumberBuses; i++ ) {
		mAvailableBuses.push( mNumberBuses - i );
	}
	
	AUGraphConnectNodeInput( mGraph, mMixerNode, 0, mOutputNode, 0 );
	
	AudioStreamBasicDescription outDesc;
	UInt32 size = sizeof( outDesc );
	err = AudioUnitGetProperty( mOutputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &outDesc, &size );
	if( err ) {
		std::cout << "Error getting output unit stream format" << std::endl;
	}
	
	AUGraphInitialize( mGraph );
	
	//Do all StreamFormat getting/setting after initialization, 
	//since that's when the output unit is actually hooked up to the hardware
	
	dsize = sizeof( AudioStreamBasicDescription );
	mPlayerDescription = new AudioStreamBasicDescription;
	err = AudioUnitGetProperty( mOutputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, mPlayerDescription, &dsize );
	if( err ) {
		std::cout << "Error reading output unit stream format" << std::endl;
	}
	
	err = AudioUnitSetProperty( mMixerUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, mPlayerDescription, dsize );
	if( err ) {
		std::cout << "Error setting mixer unit output stream format" << std::endl;
	}
	
	err = AudioUnitSetProperty( mOutputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, mPlayerDescription, dsize );
	if( err ) {
		std::cout << "Error setting output unit input stream format" << std::endl;
	}
	
	//race condition work around??
	usleep( 10 * 1000 );
	
	//TODO: tell the output AU about the order of the channels if there are more than 2 

	// turn metering ON
	//UInt32 data = 1;
	//AudioUnitSetProperty( mMixerUnit, kAudioUnitProperty_MeteringMode, kAudioUnitScope_Global, 0, &data, sizeof(data) );
	
	err = AudioUnitSetParameter( mMixerUnit, kMultiChannelMixerParam_Volume, kAudioUnitScope_Output, 0, CINDER_DEFAULT_VOLUME, 0 );
	if( err ) {
		std::cout << "error setting default volume" << std::cout;
	}
	
	err = AUGraphStart( mGraph );
	if( err ) {
		//throw
	}
}