diff --git a/jack.C b/jack.C index 0a1c3c4..a94afe6 100644 --- a/jack.C +++ b/jack.C @@ -48,12 +48,18 @@ int sample_rate; const int MAX_PORT = 16; +const int subticks_per_tick = 2048; + /* timers for notes on all channels and ports. When a note is played, * the respective value in this array is set to the note duraction in - * ticks. Decremented in each process cycle, when this value reaches - * zero, a note off is generated--regardless of the state of the - * transport */ -double notes_on[MAX_PORT][16][128]; + * subticks (an arbitrary division of the tick used only for this + * purpose). Decremented in each process cycle, when this value + * reaches zero, a note off is generated--regardless of the state of + * the transport */ +int notes_on[MAX_PORT][16][128]; + +/* number of notes currently playing on each port */ +int port_notes_on[MAX_PORT]; typedef unsigned char byte_t; @@ -114,11 +120,13 @@ midi_output_event ( int port, const midievent *e, tick_t duration ) { if ( duration ) { - if ( notes_on[ port ][ e->channel() ][ e->note() ] > transport.ticks_per_period ) + if ( notes_on[ port ][ e->channel() ][ e->note() ] > transport.ticks_per_period * subticks_per_tick ) WARNING( "duplicate note on?" ); else { - notes_on[ port ][ e->channel() ][ e->note() ] = (duration + 0.0001f) + (e->timestamp()); + notes_on[ port ][ e->channel() ][ e->note() ] = (duration + e->timestamp()) * subticks_per_tick; + + ++port_notes_on[ port ]; midi_output_event( port, e ); } @@ -168,7 +176,8 @@ midi_output_immediate_event ( int port, const midievent *e ) if ( e->is_note_on() ) { /* use timestamp as duration */ - notes_on[ port ][ e->channel() ][ e->note() ] = e->timestamp(); + notes_on[ port ][ e->channel() ][ e->note() ] = e->timestamp() * subticks_per_tick; + ++port_notes_on[ port ]; } } @@ -305,34 +314,41 @@ process ( jack_nframes_t nframes, void *arg ) schedule: - for ( int i = MAX_PORT; i-- ; ) + const int subticks_per_period = transport.ticks_per_period * subticks_per_tick; + + for ( uint i = MAX_PORT; i-- ; ) { /* reserve and clear buffers */ output[ i ].buf = jack_port_get_buffer( output[ i ].port, nframes ); jack_midi_clear_buffer( output[ i ].buf ); - /* handle scheduled note offs */ - for ( uint j = 16; j-- ; ) + if ( port_notes_on[ i ] > 0 ) { - register double *note = ¬es_on[ i ][ j ][ 0 ]; + /* handle scheduled note offs */ + for ( uint j = 16; j-- ; ) + { + register int *note = ¬es_on[ i ][ j ][ 0 ]; - for ( register uint k = 0; k < 128; note++, k++ ) - if ( *note ) - if ( ( *note -= transport.ticks_per_period ) <= 0 ) - { - static midievent e; + for ( register uint k = 0; k < 128; ++note, ++k ) + if ( *note ) + if ( ( *note -= subticks_per_period ) <= 0 ) + { + static midievent e; - e.status( midievent::NOTE_OFF ); - e.channel( j ); - e.note( k ); - e.note_velocity( 64 ); + e.status( midievent::NOTE_OFF ); + e.channel( j ); + e.note( k ); + e.note_velocity( 64 ); - e.timestamp( ((tick_t)transport.ticks_per_period) + *note ); + e.timestamp( (subticks_per_period + *note) / subticks_per_tick ); - *note = 0; + *note = 0; + --port_notes_on[ i ]; + + midi_output_event( i, &e ); + } + } - midi_output_event( i, &e ); - } } static midievent e; @@ -402,9 +418,12 @@ midi_init ( void ) /* clear notes */ for ( int p = MAX_PORT; p--; ) + { + port_notes_on[ p ] = 0; for ( int c = 16; c-- ; ) for ( int n = 128; n-- ; ) notes_on[ p ][ c ][ n ] = 0; + } //1 jack_set_buffer_size_callback( client, bufsize, 0 ); jack_set_process_callback( client, process, 0 );