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: Sat, 12 Sep 2009 16:14:17 +0100

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
> 





reply via email to

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