Exemplo n.º 1
0
void	AudioThruEngine::ApplyLoad(double load)
{
	double loadNanos = (load * mBufferSize / mSampleRate) /* seconds */ * 1000000000.;
	
	UInt64 now = AudioConvertHostTimeToNanos(AudioGetCurrentHostTime());
	UInt64 waitUntil = UInt64(now + loadNanos);
	
	while (now < waitUntil) {
		now = AudioConvertHostTimeToNanos(AudioGetCurrentHostTime());
	}
}
Exemplo n.º 2
0
static int chronos_nanotime(lua_State * L)
{
    //TODO All the apple stuff is untested because, like, I don't even got Apple.
    //If like, you have a mac, let me know whether this works.
    //see https://stackoverflow.com/questions/675626/coreaudio-audiotimestamp-mhosttime-clock-frequency
    //for info.
#ifdef CHRONOS_USE_COREAUDIO
    //Apparently this is just a wrapper around mach_absolute_time() anyway.
    lua_pushnumber(
        L,
        (lua_Number)AudioConvertHostTimeToNanos(AudioGetCurrentHostTime()) * 1.e9
    );
    return 1;
#else
    static int init = 1;
    static double resolution;
    static double multiplier;
    mach_timebase_info_data_t res_info;
    if(init){
        mach_timebase_info(&res_info);
        resolution = (double)res_info.numer / res_info.denom;
        multiplier = 1. / 1.e9;
        init = 0;
    }

    lua_pushnumber(L, (lua_Number)(mach_absolute_time() * resolution) * multiplier);
    return 1;
#endif
}
Exemplo n.º 3
0
void o2_clock_initialize()
{
	if (clock_initialized) {
		o2_clock_finish();
	}
#ifdef __APPLE__
	start_time = AudioGetCurrentHostTime();
#elif __linux__
	struct timeval tv;
	gettimeofday(&tv, NULL);
	start_time = tv.tv_sec;
#elif WIN32
	timeBeginPeriod(1); // get 1ms resolution on Windows
	start_time = timeGetTime();
#else
#error o2_clock has no implementation for this system
#endif
	// until local clock is synchronized, LOCAL_TO_GLOBAL will return -1:
	local_time_base = 0;
	global_time_base = -1;
	clock_rate = 0;

    is_master = FALSE;
    o2_clock_is_synchronized = FALSE;
    time_callback = NULL;
    time_callback_data = NULL;
    found_clock_service = FALSE;
    ping_reply_count = 0;
    time_offset = 0;
    o2_method_new("/_o2/ps", "", &o2_ping_send_handler, NULL, FALSE, TRUE);
    o2_method_new("/_o2/cu", "i", &catch_up_handler, NULL, FALSE, TRUE);
}
Exemplo n.º 4
0
PtTimestamp Pt_Time()
{
    UInt64 clock_time, nsec_time;
    clock_time = AudioGetCurrentHostTime() - start_time;
    nsec_time = AudioConvertHostTimeToNanos(clock_time);
    return (PtTimestamp)(nsec_time / NSEC_PER_MSEC);
}
Exemplo n.º 5
0
void PsychGetPrecisionTimerSeconds(double *secs)
{
    UInt64	ticks;
    
    ticks=AudioGetCurrentHostTime();
    *secs=(double)(AudioConvertHostTimeToNanos(ticks) / (double)1000000000.0);
}
double bootSeconds()
{
#ifdef SC_DARWIN
	return 1e-9 * (double)AudioConvertHostTimeToNanos(AudioGetCurrentHostTime());
#else
	return GetTimeOfDay();
#endif
}
double elapsedTime()
{
#ifdef SC_DARWIN
	return 1e-9 * (double)(AudioConvertHostTimeToNanos(AudioGetCurrentHostTime()) - gHostStartNanos);
#else
	return GetTimeOfDay();
#endif
}
Exemplo n.º 8
0
void OverlaodListenerProc(	void *				inRefCon,
								AudioUnit			ci,
								AudioUnitPropertyID	inID,
								AudioUnitScope		inScope,
								AudioUnitElement	inElement)
{
	didOverload++;
	overloadTime = AudioGetCurrentHostTime();
}
Exemplo n.º 9
0
static int64_t
audiotimestamp_to_latency(AudioTimeStamp const * tstamp, cubeb_stream * stream)
{
  if (!(tstamp->mFlags & kAudioTimeStampHostTimeValid)) {
    return 0;
  }

  uint64_t pres = AudioConvertHostTimeToNanos(tstamp->mHostTime);
  uint64_t now = AudioConvertHostTimeToNanos(AudioGetCurrentHostTime());

  return ((pres - now) * stream->sample_spec.mSampleRate) / 1000000000LL;
}
Exemplo n.º 10
0
SC_DLLEXPORT_C void schedInit()
{
	pthread_cond_init (&gSchedCond, NULL);
	pthread_mutex_init (&gLangMutex, NULL);

#ifdef SC_DARWIN
	syncOSCOffsetWithTimeOfDay();
	pthread_create (&gResyncThread, NULL, resyncThread, (void*)0);

	gHostStartNanos = AudioConvertHostTimeToNanos(AudioGetCurrentHostTime());
	gElapsedOSCoffset = (int64)(gHostStartNanos * kNanosToOSC) + gHostOSCoffset;
#else
	gElapsedOSCoffset = (int64)kSECONDS_FROM_1900_to_1970 << 32;
#endif
}
Exemplo n.º 11
0
void syncOSCOffsetWithTimeOfDay()
{
	// generate a value gHostOSCoffset such that
	// (gHostOSCoffset + systemTimeInOSCunits)
	// is equal to gettimeofday time in OSCunits.
	// Then if this machine is synced via NTP, we are synced with the world.
	// more accurate way to do this??

	struct timeval tv;

	int64 systemTimeBefore, systemTimeAfter, diff;
	int64 minDiff = 0x7fffFFFFffffFFFFLL;

	// take best of several tries
	const int numberOfTries = 8;
	int64 newOffset = gHostOSCoffset;
	for (int i=0; i<numberOfTries; ++i) {
		systemTimeBefore = AudioGetCurrentHostTime();
		gettimeofday(&tv, 0);
		systemTimeAfter = AudioGetCurrentHostTime();

		diff = systemTimeAfter - systemTimeBefore;
		if (diff < minDiff) {
			minDiff = diff;
			// assume that gettimeofday happens halfway between AudioGetCurrentHostTime calls
			int64 systemTimeBetween = systemTimeBefore + diff/2;
			int64 systemTimeInOSCunits = (int64)((double)AudioConvertHostTimeToNanos(systemTimeBetween) * kNanosToOSC);
			int64 timeOfDayInOSCunits  = ((int64)(tv.tv_sec + kSECONDS_FROM_1900_to_1970) << 32)
                                            + (int64)(tv.tv_usec * kMicrosToOSC);
			newOffset = timeOfDayInOSCunits - systemTimeInOSCunits;
		}
	}

	gHostOSCoffset = newOffset;
	//postfl("gHostOSCoffset %016llX\n", gHostOSCoffset);
}
Exemplo n.º 12
0
static void _macosx_send(struct midi_port *p, const unsigned char *data,
				unsigned int len, unsigned int delay)
{
	struct macosx_midi *m;

	m = (struct macosx_midi *)p->userdata;
	if (!m->x) {
		m->x = MIDIPacketListInit(m->pl);
	}

	/* msec to nsec? */
	m->x = MIDIPacketListAdd(m->pl, sizeof(m->packet),
			m->x, (MIDITimeStamp)AudioConvertNanosToHostTime(
			AudioConvertHostTimeToNanos(AudioGetCurrentHostTime()) + (1000000*delay)),
			len, data);
}
Exemplo n.º 13
0
/*----------------------------------------------------------------------
|    OsxAudioUnitsOutput_GetStatus
+---------------------------------------------------------------------*/
BLT_METHOD
OsxAudioUnitsOutput_GetStatus(BLT_OutputNode*       _self,
                              BLT_OutputNodeStatus* status)
{
    OsxAudioUnitsOutput* self = ATX_SELF(OsxAudioUnitsOutput, BLT_OutputNode);
    
    /* default values */
    status->flags = 0;
    
    pthread_mutex_lock(&self->lock);
    
    /* check if the queue is full */
    if (ATX_List_GetItemCount(self->packet_queue) >= self->max_packets_in_queue) {
        ATX_LOG_FINER("packet queue is full");
        status->flags |= BLT_OUTPUT_NODE_STATUS_QUEUE_FULL;
    }

    /* compute the media time */
    BLT_TimeStamp_Set(status->media_time, 0, 0);
    if (self->media_time_snapshot.rendered_host_time) {
        UInt64 host_time  = AudioConvertHostTimeToNanos(AudioGetCurrentHostTime());
        UInt64 media_time = BLT_TimeStamp_ToNanos(self->media_time_snapshot.rendered_packet_ts); 
        ATX_LOG_FINER_3("host time = %lld, last rendered packet = %lld, rendered ts = %lld", 
                        host_time, 
                        self->media_time_snapshot.rendered_host_time,
                        media_time);
        if (host_time > self->media_time_snapshot.rendered_host_time) {
            media_time += host_time-self->media_time_snapshot.rendered_host_time;
        } 
        UInt64 max_media_time;
        max_media_time = BLT_TimeStamp_ToNanos(self->media_time_snapshot.rendered_packet_ts) +
                         BLT_TimeStamp_ToNanos(self->media_time_snapshot.rendered_duration);
        ATX_LOG_FINER_2("computed media time = %lld, max media time = %lld",
                        media_time, max_media_time);
        if (media_time > max_media_time) {
            ATX_LOG_FINER("media time clamped to max");
            media_time = max_media_time;
        }
        status->media_time = BLT_TimeStamp_FromNanos(media_time);
        ATX_LOG_FINER_1("media time = %lld", media_time);
    }
    
    pthread_mutex_unlock(&self->lock);

    return BLT_SUCCESS;
}
Exemplo n.º 14
0
static void *Pt_CallbackProc(void *p)
{
    pt_callback_parameters *parameters = (pt_callback_parameters *) p;
    int mytime = 1;

    kern_return_t error;
    thread_extended_policy_data_t extendedPolicy;
    thread_precedence_policy_data_t precedencePolicy;

    extendedPolicy.timeshare = 0;
    error = thread_policy_set(mach_thread_self(), THREAD_EXTENDED_POLICY,
                              (thread_policy_t)&extendedPolicy,
                              THREAD_EXTENDED_POLICY_COUNT);
    if (error != KERN_SUCCESS) {
        mach_error("Couldn't set thread timeshare policy", error);
    }

    precedencePolicy.importance = THREAD_IMPORTANCE;
    error = thread_policy_set(mach_thread_self(), THREAD_PRECEDENCE_POLICY,
                              (thread_policy_t)&precedencePolicy,
                              THREAD_PRECEDENCE_POLICY_COUNT);
    if (error != KERN_SUCCESS) {
        mach_error("Couldn't set thread precedence policy", error);
    }
    
    
    /* to kill a process, just increment the pt_callback_proc_id */
    /* printf("pt_callback_proc_id %d, id %d\n", pt_callback_proc_id, parameters->id); */
    while (pt_callback_proc_id == parameters->id) {
        /* wait for a multiple of resolution ms */
        UInt64 wait_time;
        int delay = mytime++ * parameters->resolution - Pt_Time();
	PtTimestamp timestamp;
        if (delay < 0) delay = 0;
        wait_time = AudioConvertNanosToHostTime((UInt64)delay * NSEC_PER_MSEC);
        wait_time += AudioGetCurrentHostTime();
        error = mach_wait_until(wait_time);
	timestamp = Pt_Time();
        (*(parameters->callback))(timestamp, parameters->userData);
    }
    free(parameters);
    return NULL;
}
Exemplo n.º 15
0
void CoreMidiManager::SendMIDI(char actionType, int noteNum, int value)
{
  uint8_t buffer[PACKET_BUF_SIZE];
  uint8_t msg[3];
  
  MIDIPacketList *packetList = (MIDIPacketList*) buffer;
  MIDIPacket *curPacket = MIDIPacketListInit(packetList);
  
  curPacket = MIDIPacketListAdd(packetList,
				PACKET_BUF_SIZE,
				curPacket,
				AudioGetCurrentHostTime(),
				actionType == 'C' ? 2 : 3,
				msg);
  if (!curPacket)
    midimsg_die("packet list allocation failed");
  
  midimsg_attempt(MIDIReceived(m_midiendpoint, packetList), "error sending midi");
}
Exemplo n.º 16
0
o2_time o2_local_time()
{
    if (time_callback) {
        return (*time_callback)(time_callback_data) - time_offset;
    }
#ifdef __APPLE__
    uint64_t clock_time, nsec_time;
    clock_time = AudioGetCurrentHostTime() - start_time;
    nsec_time = AudioConvertHostTimeToNanos(clock_time);
    return ((o2_time) (nsec_time * 1.0E-9)) - time_offset;
#elif __linux__
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return ((tv.tv_sec - start_time) + (tv.tv_usec * 0.000001)) - time_offset;
#elif WIN32
	return ((timeGetTime() - start_time) * 0.001) - time_offset;
#else
#error o2_clock has no implementation for this system
#endif
}
Exemplo n.º 17
0
PtError Pt_Start(int resolution, PtCallback *callback, void *userData)
{
    if (time_started_flag) return ptAlreadyStarted;
    start_time = AudioGetCurrentHostTime();
    
    if (callback) {
        int res;
        pt_callback_parameters *parms;

        parms = (pt_callback_parameters *) malloc(sizeof(pt_callback_parameters));
        if (!parms) return ptInsufficientMemory;
        parms->id = pt_callback_proc_id;
        parms->resolution = resolution;
        parms->callback = callback;
        parms->userData = userData;
        res = pthread_create(&pt_thread_pid, NULL, Pt_CallbackProc, parms);
        if (res != 0) return ptHostError;
    }
    
    time_started_flag = TRUE;
    return ptNoError;
}
Exemplo n.º 18
0
void PsychGetPrecisionTimerTicks(psych_uint64 *ticks)
{
    *ticks=AudioGetCurrentHostTime();
}
// A simple utility which encapsulates CoreAudio's HostTime APIs.
// It returns the current host time in nanoseconds which when subtracted from
// a previous getCurrentTimeInNanos() result produces the delta in nanos.
static UInt64 getCurrentTimeInNanos() {
    UInt64 hostTime = AudioGetCurrentHostTime();
    UInt64 nanos = AudioConvertHostTimeToNanos(hostTime);
    return nanos;
}
Exemplo n.º 20
0
static MIDITimeStamp midiTime(float latencySeconds)
{
    // add the latency expressed in seconds, to the current host time base.
    UInt64 latencyNanos =  1000000000 * latencySeconds ; //secs to nano
    return (MIDITimeStamp)AudioGetCurrentHostTime() + AudioConvertNanosToHostTime(latencyNanos);
}
Exemplo n.º 21
0
/*----------------------------------------------------------------------
|    OsxAudioUnitsOutput_RenderCallback
+---------------------------------------------------------------------*/
static OSStatus     
OsxAudioUnitsOutput_RenderCallback(void*						inRefCon,
                                   AudioUnitRenderActionFlags*	ioActionFlags,
                                   const AudioTimeStamp*		inTimeStamp,
                                   UInt32						inBusNumber,
                                   UInt32						inNumberFrames,
                                   AudioBufferList*			    ioData)
{
    OsxAudioUnitsOutput* self = (OsxAudioUnitsOutput*)inRefCon;
    ATX_ListItem*        item;
    unsigned int         requested;
    unsigned char*       out;
    ATX_Boolean          timestamp_measured = ATX_FALSE;
    
    BLT_COMPILER_UNUSED(ioActionFlags);
    BLT_COMPILER_UNUSED(inTimeStamp);
    BLT_COMPILER_UNUSED(inBusNumber);
    BLT_COMPILER_UNUSED(inNumberFrames);
                
    /* sanity check on the parameters */
    if (ioData == NULL || ioData->mNumberBuffers == 0) return 0;
    
    /* in case we have a strange request with more than one buffer, just return silence */
    if (ioData->mNumberBuffers != 1) {
        unsigned int i;
        ATX_LOG_FINEST_1("strange request with %d buffers", 
                         (int)ioData->mNumberBuffers);
        for (i=0; i<ioData->mNumberBuffers; i++) {
            ATX_SetMemory(ioData->mBuffers[i].mData, 0, ioData->mBuffers[i].mDataByteSize);
        }
        return 0;
    }
        
    /* init local variables */
    requested = ioData->mBuffers[0].mDataByteSize;
    out = (unsigned char*)ioData->mBuffers[0].mData;
    ATX_LOG_FINEST_2("request for %d bytes, %d frames", (int)requested, (int)inNumberFrames);

    /* lock the packet queue */
    pthread_mutex_lock(&self->lock);
    
    /* return now if we're paused */
    //if (self->paused) goto end;
    
    /* abort early if we have no packets */
    if (ATX_List_GetItemCount(self->packet_queue) == 0) goto end;
        
    /* fill as much as we can */
    while (requested && (item = ATX_List_GetFirstItem(self->packet_queue))) {
        BLT_MediaPacket*        packet = ATX_ListItem_GetData(item);
        const BLT_PcmMediaType* media_type;
        BLT_Size                payload_size;
        BLT_Size                chunk_size;
        BLT_TimeStamp           chunk_duration;
        BLT_TimeStamp           packet_ts;
        unsigned int            bytes_per_frame;
        unsigned int            sample_rate;
        
        /* get the packet info */
        BLT_MediaPacket_GetMediaType(packet, (const BLT_MediaType**)&media_type);
        packet_ts = BLT_MediaPacket_GetTimeStamp(packet);
        bytes_per_frame = media_type->channel_count*media_type->bits_per_sample/8;
        sample_rate = media_type->sample_rate;
        
        /* record the timestamp if we have not already done so */
        if (!timestamp_measured) {
            self->media_time_snapshot.rendered_packet_ts = packet_ts;
            self->media_time_snapshot.rendered_host_time = 
                AudioConvertHostTimeToNanos(AudioGetCurrentHostTime());
            BLT_TimeStamp_Set(self->media_time_snapshot.rendered_duration, 0, 0);
            timestamp_measured = ATX_TRUE;
            
            ATX_LOG_FINEST_2("rendered TS: packet ts=%lld, host ts=%lld",
                             BLT_TimeStamp_ToNanos(packet_ts),
                             self->media_time_snapshot.rendered_host_time);
        }
         
        /* compute how much to copy from this packet */
        payload_size = BLT_MediaPacket_GetPayloadSize(packet);
        if (payload_size <= requested) {
            /* copy the entire payload and remove the packet from the queue */
            chunk_size = payload_size;
            ATX_CopyMemory(out, BLT_MediaPacket_GetPayloadBuffer(packet), chunk_size);
            ATX_List_RemoveItem(self->packet_queue, item);
            packet = NULL;
            media_type = NULL;
            ATX_LOG_FINER_1("media packet fully consumed, %d left in queue",
                            ATX_List_GetItemCount(self->packet_queue));
        } else {
            /* only copy a portion of the payload */
            chunk_size = requested;
            ATX_CopyMemory(out, BLT_MediaPacket_GetPayloadBuffer(packet), chunk_size);            
        }
        
        /* update the counters */
        requested -= chunk_size;
        out       += chunk_size;
        
        /* update the media time snapshot */
        if (bytes_per_frame) {
            unsigned int frames_in_chunk = chunk_size/bytes_per_frame;
            chunk_duration = BLT_TimeStamp_FromSamples(frames_in_chunk, sample_rate);
        } else {
            BLT_TimeStamp_Set(chunk_duration, 0, 0);
        }
        self->media_time_snapshot.rendered_duration = 
            BLT_TimeStamp_Add(self->media_time_snapshot.rendered_duration, chunk_duration);
        
        /* update the packet unless we're done with it */
        if (packet) {
            /* update the packet offset and timestamp */
            BLT_MediaPacket_SetPayloadOffset(packet, BLT_MediaPacket_GetPayloadOffset(packet)+chunk_size);
            BLT_MediaPacket_SetTimeStamp(packet, BLT_TimeStamp_Add(packet_ts, chunk_duration));
        }
    }
   
end:
    /* fill whatever is left with silence */    
    if (requested) {
        ATX_LOG_FINEST_1("filling with %d bytes of silence", requested);
        ATX_SetMemory(out, 0, requested);
    }
    
    pthread_mutex_unlock(&self->lock);
        
    return 0;
}
JNIEXPORT jlong JNICALL Java_com_apple_audio_util_HostTime_AudioGetCurrentHostTime
  (JNIEnv *, jclass)
{
	return (jlong)AudioGetCurrentHostTime();
}
Exemplo n.º 23
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;
}