denemo-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: MIDI (was Re: [Denemo-devel] Anacrusis script needed)


From: Jeremiah Benham
Subject: Re: MIDI (was Re: [Denemo-devel] Anacrusis script needed)
Date: Mon, 14 Sep 2009 05:53:01 -0500

On Mon, 14 Sep 2009 05:37:57 -0500
Jeremiah Benham <address@hidden> wrote:

> On Mon, 14 Sep 2009 09:36:01 +0100
> Richard Shann <address@hidden> wrote:
> 
> I seem to be a bit stuck. I am attaching a diff. Let me now if it
> appears I am overlooking something.


I failed to mention that the buffer is continously being written to.
It is like BufferEmpty gets stuck being FALSE.

I have static volatile gboolean BufferEmpty = TRUE;


static void
send_midi_event(jack_nframes_t nframes){
  unsigned char *buffer;
  gint i=0;
  gint n;
  void *port_buffers[MAX_NUMBER_OF_TRACKS];
  for(n=0;n<nframes;n++){
  if (BufferEmpty==FALSE){
   if (output_ports[i]){
     port_buffers[i] = jack_port_get_buffer(output_ports[i], nframes);
     jack_midi_clear_buffer(port_buffers[i]);
     buffer = jack_midi_event_reserve(port_buffers[i], n, 3);
     buffer[0] = global_midi_buffer[0];
     buffer[1] = global_midi_buffer[1];
     buffer[2] = global_midi_buffer[2];
     BufferEmpty=TRUE;
   }
  }
 }
}






> 
> Jeremiah
> 
> 
> 
> > One important aspect not covered here is calling the jack_playpitch
> > from a script - it depends on the gtk_main_loop running to fire the
> > timer and so schedule the note off event.
> > So if you are calling from a script you won't get a note off until
> > you call d-Getxxx and friends.
> > Some thought needed about how scripts interact with the gtk main
> > loop. Richard
> > 
> > 
> > On Sat, 2009-09-12 at 16:14 +0100, Richard Shann wrote:
> > > On Sat, 2009-09-12 at 07:45 -0500, Jeremiah Benham wrote:
> > > > Here is an attempt to implement what you were suggesting
> > > > Richard. I am having troubles with it. I repeatedly gives note
> > > > on events and then crashes denemo for some reason. 
> > > 
> > > You don't give the declaration of BufferReady, it must be
> > > volatile I think.
> > > You don't set up a timer, (I think you are relying on the timing
> > > of the jack interrupts instead), set one up and remember to return
> > > TRUE (or is it FALSE?) to make it a once-only timer, pass in the
> > > off-message to correspond with the on message.
> > > 
> > > Here is the same ideas in detail:
> > > 
> > > static volatile gboolean BufferReady=TRUE;//Switch the logic of
> > > the name around, ie call it BufferNotReady - depends who for -
> > > ready for what! perhaps BufferEmpty would be best name.
> > > > 
> > > > void
> > > > jack_playpitch(gint key, gint duration, gint volume, gint
> > > > channel){ if (!BufferReady){
> > > >    AllSoundOff=TRUE;
> > > >  }
> > > >  if (BufferReady){
> > > >     loop_index = 0;
> > > >     global_midi_buffer[0] = NOTE_ON;
> > > >     global_midi_buffer[1] = key; //freq
> > > >     global_midi_buffer[2] = volume;
> > > >     global_duration = duration;
> > > >     BufferReady=FALSE;
> > > >   }
> > > Here set up the timer to go off after duration with data the
> > > NOTEOFF message
> > > > }
> > > > 
> > > > static void
> > > > send_midi_event(jack_nframes_t nframes){
> > > >   unsigned char *buffer;
> > > >   gint i=0;
> > > >   gint channel;
> > > >   void *port_buffers[MAX_NUMBER_OF_TRACKS];
> > > >   if (AllSoundOff){
> > > >     for (channel=0;channel<16;channel++){
> > > >       buffer = jack_midi_event_reserve(port_buffers[i], 0, 3);
> > > >       buffer[0] = MIDI_CONTROLLER | channel;
> > > >       buffer[1] = MIDI_ALL_NOTE_OFF;
> > > >       buffer[2] = 0;
> > > >       global_duration = loop_index = 0;
> > > >       AllSoundOff=FALSE;
> > > >     }
> > > >   }
> > > > 
> > > >   if (!BufferReady)
> > > >    if (output_ports[i]){
> > > >      port_buffers[i] = jack_port_get_buffer(output_ports[i],
> > > > nframes); jack_midi_clear_buffer(port_buffers[i]);
> > > >      buffer = jack_midi_event_reserve(port_buffers[i], 0, 3);
> > > >      buffer[0] = global_midi_buffer[0];
> > > >      buffer[1] = global_midi_buffer[1];
> > > >      buffer[2] = global_midi_buffer[2];
> > > >      BufferReady=TRUE;
> > > >    }
> > > > }
> > > > 
> > > > static void
> > > static gboolean a g_timer call back (or is it gtk_timer??)
> > > > timer_callback(jack_nframes_t nframes){
> > > in this timer callback put the message into global_buffer in the
> > > same way as the original ON message, ie testing BufferReady.
> > > and return making it a once only timer.
> > > 
> > > >   gint i;
> > > >   for (i=0;i<nframes;i++)
> > > >     if (global_duration != 0){
> > > >       if ((loop_index++ >= global_duration) && BufferReady){
> > > >        global_midi_buffer[0] = NOTE_OFF;
> > > >        /*global_midi_buffer[1] = same*/
> > > >        global_midi_buffer[2] = 0;
> > > >        BufferReady=FALSE;
> > > >        global_duration = loop_index = 0;
> > > >       }   
> > > >       if ((loop_index > global_duration) && !BufferReady){
> > > >         global_duration = loop_index = 0;
> > > >         AllSoundOff=TRUE;
> > > >       }
> > > >     }
> > > > }
> > > > 
> > > > Also in process_callback I put this:
> > > > if (Denemo.gui->si && output_ports &&
> > > > Denemo.prefs.immediateplayback){ send_midi_event(nframes);
> > > it might be better to put the code for send_midi_event directly
> > > here and put a warning at the start about it being called under
> > > interrupt, so no printf's mallocs, g_list_appends or anything
> > > function calls really, unless you are quite sure.
> > > >           timer_callback(nframes);
> > > don't do this timer_callback
> > > 
> > > >         }
> > > > 
> > > > 
> > > > Thanks for your help,
> > > > Jeremiah
> > > > 
> > > 
> > > 
> > > 
> > > _______________________________________________
> > > Denemo-devel mailing list
> > > address@hidden
> > > http://lists.gnu.org/mailman/listinfo/denemo-devel
> > 
> > 
> > 
> > _______________________________________________
> > Denemo-devel mailing list
> > address@hidden
> > http://lists.gnu.org/mailman/listinfo/denemo-devel
> 





reply via email to

[Prev in Thread] Current Thread [Next in Thread]