Do notes_on math in integer instead of floating point to avoid denormal issues on some CPUs.
Avoid scanning notes_on for ports on which there are no notes playing.
This commit is contained in:
parent
fbe232fcfb
commit
c307a3443c
43
jack.C
43
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,20 +314,24 @@ 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 );
|
||||
|
||||
if ( port_notes_on[ i ] > 0 )
|
||||
{
|
||||
/* handle scheduled note offs */
|
||||
for ( uint j = 16; j-- ; )
|
||||
{
|
||||
register double *note = ¬es_on[ i ][ j ][ 0 ];
|
||||
register int *note = ¬es_on[ i ][ j ][ 0 ];
|
||||
|
||||
for ( register uint k = 0; k < 128; note++, k++ )
|
||||
for ( register uint k = 0; k < 128; ++note, ++k )
|
||||
if ( *note )
|
||||
if ( ( *note -= transport.ticks_per_period ) <= 0 )
|
||||
if ( ( *note -= subticks_per_period ) <= 0 )
|
||||
{
|
||||
static midievent e;
|
||||
|
||||
|
@ -327,14 +340,17 @@ schedule:
|
|||
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;
|
||||
--port_notes_on[ i ];
|
||||
|
||||
midi_output_event( i, &e );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static midievent e;
|
||||
/* first, write any immediate events from the UI thread */
|
||||
while ( jack_ringbuffer_read( output[ i ].ring_buf, (char *)&e, sizeof( midievent ) ) )
|
||||
|
@ -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 );
|
||||
|
|
Loading…
Reference in New Issue