• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
MusicPlayer + MusicSequenceSetUserCallback
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

MusicPlayer + MusicSequenceSetUserCallback


  • Subject: MusicPlayer + MusicSequenceSetUserCallback
  • From: David Hicks <email@hidden>
  • Date: Tue, 12 Jul 2011 15:08:42 -0400

SkinnyTod,

> I'm using the 'MusicPlayer' class (MusicPlayer API) to make a little file
> midi player as a learning project. I've got it working but now I want to
> visualize the midi events (notes) as they play.

> I thought I could use 'MusicSequenceSetUserCallback' (MusicSequence API) to
> call the instance of my main class when events occur. 

I have an application with MIDI file playback functionality. It's possible what I do will be applicable to your app.

 I remember finding that MusicSequenceSetUserCallback didn't really work for chasing events and showing them in (more or less) real-time. The MusicSequenceSetUserCallback works for UserData added to a MusicSequence, if I recall correctly.

MusicSequenceSetUserCallback
@abstract Establish a user callback for a sequence
@discussion This call is used to register (or remove if inCallback is NULL) a callback
that the MusicSequence will call for ANY UserEvents that are added to any of the
tracks of the sequence.

What my app does is create a MusicSequence, using MusicSequenceFileLoadData, and associates an AUGraph with the Sequence; then, in AUGraphGetNodeCount I find the Synth AU:
if (desc.componentType == kAudioUnitType_MusicDevice)
{
result = AUGraphNodeInfo(theGraph, node, 0, &theSynth);

then I add a callback to that AU:
result = AudioUnitAddRenderNotify(theSynth, synthRenderCallback, self);

This callback is called on the AU thread, and for my purposes only needs to check the value of the current sample against the value of the previous sample. It updates a member variable of my controller this way:
if( This->mCurrentTime < inTimeStamp->mSampleTime )
{
fDiff = inTimeStamp->mSampleTime - This->mCurrentTime;

(I then adjust the sample difference based on current tempo relative to the sequence tempo.)

(Your code will probably want to be aware that the Callback gets called twice each cycle, PreRender and PostRender.)

The signature of these callbacks shows the input arg inTimeStamp, referred to above. You can find similar code in MixMash I believe.

OSStatus synthRenderCallback(
void * inRefCon,
AudioUnitRenderActionFlags * ioActionFlags,
const AudioTimeStamp * inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList * ioData)

You also need to set an NSTimer that gets called on the main thread while the Sequence is playing and which checks some Class member variable(s) to figure out where the sequence currently is. Based on the current time you chase to the current event in your sequence and do whatever is relevant.

HTH,
David
 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:

This email sent to email@hidden

  • Follow-Ups:
    • Re: MusicPlayer + MusicSequenceSetUserCallback
      • From: Skinny Tod <email@hidden>
  • Prev by Date: Re: Noise in audiostream app when use the tabbar or tableview
  • Next by Date: Re: Noise in audiostream app when use the tabbar or tableview
  • Previous by thread: Re: Noise in audiostream app when use the tabbar or tableview
  • Next by thread: Re: MusicPlayer + MusicSequenceSetUserCallback
  • Index(es):
    • Date
    • Thread