Change the way patterns are triggered in sequence mode.

Now patterns should be triggered properly even if we come in in the
middle of a phrase, as happens when randomly relocating the transport.
pull/3/head
Jonathan Moore Liles 2008-06-15 12:19:26 -05:00
parent 81f504f88b
commit d70dd3a517
4 changed files with 69 additions and 48 deletions

View File

@ -5,7 +5,6 @@
; General
* TODO: {3} fix transport seeking to the middle of a phrase/pattern in Sequence Mode.
* TODO: {3} deal with dropped ticks from timebase master better when running as slave.
* TODO: {2} move keybindings into menus for discoverability (like in Non-DAW)
* TODO: {2} improve or get rid of the transport.valid test at initialization time.

View File

@ -202,6 +202,48 @@ midi_all_sound_off ( void )
}
}
static void
stop_all_patterns ( void )
{
for ( uint i = pattern::patterns(); i--; )
{
pattern *p = pattern::pattern_by_number( i + 1 );
p->stop();
}
}
static int
sync ( jack_transport_state_t state, jack_position_t *pos, void * )
{
static bool seeking = false;
switch ( state )
{
case JackTransportStopped: /* new position requested */
/* JACK docs lie. This is only called when the transport
is *really* stopped, not when starting a slow-sync
cycle */
stop_all_patterns();
return 1;
case JackTransportStarting: /* this means JACK is polling slow-sync clients */
{
stop_all_patterns();
return 1;
}
case JackTransportRolling: /* JACK's timeout has expired */
/* FIXME: what's the right thing to do here? */
// request_locate( pos->frame );
return 1;
break;
default:
WARNING( "unknown transport state" );
}
return 0;
}
static int
process ( jack_nframes_t nframes, void *arg )
{
@ -246,29 +288,12 @@ process ( jack_nframes_t nframes, void *arg )
{
case PATTERN:
case TRIGGER:
{
// stop all patterns.
for ( uint i = pattern::patterns(); i--; )
{
pattern *p = pattern::pattern_by_number( i + 1 );
p->stop();
}
stop_all_patterns();
break;
}
}
switch ( song.play_mode )
{
case SEQUENCE:
// first handle patterns already playing
for ( uint i = pattern::patterns(); i--; )
{
pattern *p = pattern::pattern_by_number( i + 1 );
if ( p && p->playing() )
p->play( ph, nph );
}
playlist->play( ph, nph );
break;
case PATTERN:
@ -435,7 +460,7 @@ midi_init ( void )
//1 jack_set_buffer_size_callback( client, bufsize, 0 );
jack_set_process_callback( client, process, 0 );
jack_set_sync_callback( client, sync, 0 );
/* /\* initialize buffer size *\/ */
/* transport_poll(); */

View File

@ -300,8 +300,7 @@ pattern::draw_row_names ( Canvas *c ) const
void
pattern::trigger ( tick_t start, tick_t end )
{
if ( start > end )
ASSERTION( "programming error: invalid loop trigger! (%lu-%lu)", start, end );
ASSERT( start <= end, "programming error: invalid loop trigger! (%lu-%lu)", start, end );
_start = start;
_end = end;
@ -402,8 +401,6 @@ pattern::play ( tick_t start, tick_t end ) const
if ( end > _end )
end = _end;
_playing = true;
// where we are in the absolute time
tick_t tick = start - _start;
int num_played = tick / d->length;
@ -415,13 +412,15 @@ pattern::play ( tick_t start, tick_t end ) const
if ( _index < end - start )
{
DMESSAGE( "Triggered pattern %d at tick %lu (ls: %lu, le: %lu, o: %lu)", number(), start, _start, _end, offset );
DMESSAGE( "%s pattern %d at tick %lu (ls: %lu, le: %lu, o: %lu)", _playing ? "Looped" : "Triggered", number(), start, _start, _end, offset );
_cleared = false;
}
_playing = true;
if ( mode() == MUTE )
return;
goto done;
try_again:
@ -475,7 +474,15 @@ try_again:
DMESSAGE( "out of events, resetting to satisfy loop" );
done: ;
done:
if ( _end == end )
{
/* we're doing playing this trigger */
DMESSAGE( "Pattern %d ended at tick %lu (ls: %lu, le: %lu, o: %lu)", number(), end, _start, _end, offset );
stop();
}
}

View File

@ -186,7 +186,6 @@ phrase::play ( tick_t start, tick_t end )
// not ready yet
return;
if ( start < _start )
start = _start;
@ -203,7 +202,7 @@ phrase::play ( tick_t start, tick_t end )
_index = tick % d->length;
if ( _index < end - start )
MESSAGE( "Triggered phrase %d at tick %lu (ls: %lu, le: %lu, o: %lu)", number(), start, _start, _end, offset );
DMESSAGE( "Triggered phrase %d at tick %lu (ls: %lu, le: %lu, o: %lu)", number(), start, _start, _end, offset );
try_again:
@ -215,36 +214,27 @@ try_again:
{
// MESSAGE( "s[%ld] -> t[%ld] : %ld, len %ld", start, end, e->timestamp(), _length ); // (*e).print();
tick_t ts = e->timestamp() + offset;
const tick_t ts = e->timestamp() + offset;
if ( ts >= end )
goto done;
if ( ts >= start )
if ( e->is_note_on() )
{
event ne = *e;
if ( ne.is_note_on() || ne.is_note_off() )
const tick_t tse = offset + e->link()->timestamp();
if ( tse > start )
{
int ev_note = e->note();
pattern *p = pattern::pattern_by_number( 1 + note_to_y( e->note() ) );
// d->mapping.translate( &ne );
if ( ! p->playing() )
p->trigger( ts, offset + e->link()->timestamp() );
pattern *p = pattern::pattern_by_number( 1 + note_to_y( ev_note ) );
if ( p )
{
if ( e->is_note_on() )
{
p->trigger( ts, offset + e->link()->timestamp() );
p->play( ts, end );
}
else
if ( e->is_note_off() )
p->stop();
}
p->play( start, end );
}
}
}
// ran out of events, but there's still some loop left to play.
offset += d->length;
goto try_again;