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: Richard Shann
Subject: Re: MIDI (was Re: [Denemo-devel] Anacrusis script needed)
Date: Mon, 14 Sep 2009 14:39:28 +0100

I think your only major problem is that you are passing 44100 ms as the
duration, if you cut that down to 100 (and cut the volume down to 64
while you are about it, unless you like jumping out of your skin) then
it seems to work fine.
There is some investigating still to do - why does it repeat noteon
madly if no noteoff is given etc, but it seems usable. I don't
understand all the stuff about nframes etc there is a loop which is is
going thru
  for(n=0;n<nframes;n++){
in send_midi_event which can only fire once - also i is just a synonym
for 0 here...

Richard


On Mon, 2009-09-14 at 05:53 -0500, Jeremiah Benham wrote:
> 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]