This helps dealing with fractional errors resulting in dropped notes when running with very small buffer sizes.tags/non-daw-v1.2.0
@@ -21,7 +21,7 @@ | |||||
// #pragma once | // #pragma once | ||||
typedef unsigned char byte_t; | typedef unsigned char byte_t; | ||||
typedef unsigned long tick_t; | |||||
typedef double tick_t; | |||||
typedef unsigned int uint; | typedef unsigned int uint; | ||||
@@ -260,8 +260,8 @@ Grid::prev_note_x ( int x ) const | |||||
void | void | ||||
Grid::_fix_length ( void ) | Grid::_fix_length ( void ) | ||||
{ | { | ||||
tick_t beats = (_rw->length / PPQN); | |||||
tick_t rem = _rw->length % PPQN; | |||||
tick_t beats = (unsigned long)(_rw->length / PPQN); | |||||
tick_t rem = (unsigned long)_rw->length % PPQN; | |||||
_rw->length = (rem ? (beats + 1) : beats) * PPQN; | _rw->length = (rem ? (beats + 1) : beats) * PPQN; | ||||
} | } | ||||
@@ -312,7 +312,7 @@ process ( jack_nframes_t nframes, void *arg ) | |||||
/* ph-nph is exclusive. It is important that in normal continuous playback each tick is covered exactly once! */ | /* ph-nph is exclusive. It is important that in normal continuous playback each tick is covered exactly once! */ | ||||
const tick_t ph = transport.ticks; | const tick_t ph = transport.ticks; | ||||
const tick_t nph = trunc( transport.ticks + transport.ticks_per_period ); | |||||
const tick_t nph = transport.ticks + transport.ticks_per_period; | |||||
if ( ! transport.valid ) | if ( ! transport.valid ) | ||||
goto schedule; | goto schedule; | ||||
@@ -320,15 +320,15 @@ process ( jack_nframes_t nframes, void *arg ) | |||||
if ( ( ! transport.rolling ) || ph == oph ) | if ( ( ! transport.rolling ) || ph == oph ) | ||||
goto schedule; | goto schedule; | ||||
if ( ph != onph ) | |||||
{ | |||||
if ( onph > ph ) | |||||
DWARNING( "duplicated %lu ticks (out of %d)", onph - ph, (int)(not_dropped * transport.ticks_per_period) ); | |||||
else | |||||
DWARNING( "dropped %lu ticks (out of %d)", ph - onph, (int)(not_dropped * transport.ticks_per_period) ); | |||||
/* if ( ph != onph ) */ | |||||
/* { */ | |||||
/* if ( onph > ph ) */ | |||||
/* DWARNING( "duplicated %lu ticks (out of %d)", onph - ph, (int)(not_dropped * transport.ticks_per_period) ); */ | |||||
/* else */ | |||||
/* DWARNING( "dropped %lu ticks (out of %d), ticks per period = %f", ph - onph, (int)(not_dropped * transport.ticks_per_period) ); */ | |||||
not_dropped = 0; | |||||
} | |||||
/* not_dropped = 0; */ | |||||
/* } */ | |||||
++not_dropped; | ++not_dropped; | ||||
@@ -398,7 +398,7 @@ process ( jack_nframes_t nframes, void *arg ) | |||||
{ | { | ||||
DMESSAGE( "Triggering pattern %i ph=%lu, ts=%lu", e.msb(), ph, e.timestamp() ); | DMESSAGE( "Triggering pattern %i ph=%lu, ts=%lu", e.msb(), ph, e.timestamp() ); | ||||
p->trigger( e.timestamp(), -1 ); | |||||
p->trigger( e.timestamp(), INFINITY ); | |||||
} | } | ||||
} | } | ||||
else | else | ||||
@@ -433,7 +433,7 @@ process ( jack_nframes_t nframes, void *arg ) | |||||
{ | { | ||||
pattern *p = pattern::pattern_by_number( i + 1 ); | pattern *p = pattern::pattern_by_number( i + 1 ); | ||||
p->trigger( 0, -1 ); | |||||
p->trigger( 0, INFINITY ); | |||||
p->play( ph, nph ); | p->play( ph, nph ); | ||||
} | } | ||||
@@ -24,6 +24,7 @@ | |||||
#include "jack.H" | #include "jack.H" | ||||
#include "transport.H" | #include "transport.H" | ||||
#include <math.h> | |||||
int pattern::note_shape = SQUARE; | int pattern::note_shape = SQUARE; | ||||
@@ -217,7 +218,8 @@ pattern::record_event ( const midievent *me ) | |||||
tick_t duration = off->timestamp() - on->timestamp(); | tick_t duration = off->timestamp() - on->timestamp(); | ||||
/* place within loop */ | /* place within loop */ | ||||
on->timestamp( ( on->timestamp() - p->_start ) % p->_rw->length ); | |||||
on->timestamp( | |||||
fmod( on->timestamp() - p->_start, p->_rw->length ) ); | |||||
on->link( off ); | on->link( off ); | ||||
on->note_duration( duration ); | on->note_duration( duration ); | ||||
@@ -234,7 +236,7 @@ pattern::record_event ( const midievent *me ) | |||||
// if ( ! filter ) | // if ( ! filter ) | ||||
e->timestamp( e->timestamp() % p->_rw->length ); | |||||
e->timestamp( fmod( e->timestamp(), p->_rw->length ) ); | |||||
el->unlink( e ); | el->unlink( e ); | ||||
p->_rw->events.insert( e ); | p->_rw->events.insert( e ); | ||||
@@ -314,7 +316,7 @@ pattern::draw_row_names ( Canvas *c ) const | |||||
void | void | ||||
pattern::trigger ( tick_t start, tick_t end ) | pattern::trigger ( tick_t start, tick_t end ) | ||||
{ | { | ||||
ASSERT( start <= end, "programming error: invalid loop trigger! (%lu-%lu)", start, end ); | |||||
/* ASSERT( end != -1 && start <= end, "programming error: invalid loop trigger! (%lu-%lu)", start, end ); */ | |||||
_start = start; | _start = start; | ||||
_end = end; | _end = end; | ||||
@@ -325,7 +327,7 @@ pattern::trigger ( tick_t start, tick_t end ) | |||||
void | void | ||||
pattern::trigger ( void ) | pattern::trigger ( void ) | ||||
{ | { | ||||
trigger( transport.frame / transport.frames_per_tick, -1 ); | |||||
trigger( transport.frame / transport.frames_per_tick, INFINITY ); | |||||
} | } | ||||
void | void | ||||
@@ -423,14 +425,14 @@ pattern::play ( tick_t start, tick_t end ) const | |||||
const event *e; | const event *e; | ||||
_index = tick % d->length; | |||||
_index = fmod( tick, d->length ); | |||||
bool reset_queued = false; | bool reset_queued = false; | ||||
if ( _index < end - start ) | if ( _index < end - start ) | ||||
{ | { | ||||
/* period covers the beginning of the loop */ | /* period covers the beginning of the loop */ | ||||
DMESSAGE( "%s pattern %d at tick %lu (ls: %lu, le: %lu, o: %lu)", _playing ? "Looped" : "Triggered", number(), start, _start, _end, offset ); | |||||
DMESSAGE( "%s pattern %d at tick %f (ls: %f, le: %f, o: %f)", _playing ? "Looped" : "Triggered", number(), start, _start, _end, offset ); | |||||
_cleared = false; | _cleared = false; | ||||
@@ -535,7 +537,7 @@ done: | |||||
if ( _end == end ) | if ( _end == end ) | ||||
{ | { | ||||
/* we're done playing this trigger */ | /* we're done playing this trigger */ | ||||
DMESSAGE( "Pattern %d ended at tick %lu (ls: %lu, le: %lu, o: %lu)", number(), end, _start, _end, offset ); | |||||
DMESSAGE( "Pattern %d ended at tick %f (ls: %f, le: %f, o: %f)", number(), end, _start, _end, offset ); | |||||
stop(); | stop(); | ||||
} | } | ||||
@@ -23,8 +23,7 @@ | |||||
#include "canvas.H" | #include "canvas.H" | ||||
#include "mapping.H" | #include "mapping.H" | ||||
// #include "event.H" | // #include "event.H" | ||||
typedef unsigned long tick_t; | |||||
#include "common.h" | |||||
#include <vector> | #include <vector> | ||||
using std::vector; | using std::vector; | ||||
@@ -22,6 +22,7 @@ | |||||
#include "pattern.H" | #include "pattern.H" | ||||
#include "smf.H" | #include "smf.H" | ||||
#include "common.h" | #include "common.h" | ||||
#include <math.h> | |||||
vector <phrase*> phrase::_phrases; | vector <phrase*> phrase::_phrases; | ||||
signal <void> phrase::signal_create_destroy; | signal <void> phrase::signal_create_destroy; | ||||
@@ -197,7 +198,7 @@ phrase::play ( tick_t start, tick_t end ) | |||||
int num_played = tick / d->length; | int num_played = tick / d->length; | ||||
tick_t offset = _start + (d->length * num_played); | tick_t offset = _start + (d->length * num_played); | ||||
_index = tick % d->length; | |||||
_index = fmod( tick, d->length ); | |||||
if ( _index < end - start ) | if ( _index < end - start ) | ||||
DMESSAGE( "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 ); | ||||
@@ -24,7 +24,7 @@ | |||||
#include <sigc++/sigc++.h> | #include <sigc++/sigc++.h> | ||||
typedef unsigned long tick_t; | |||||
#include "common.h" | |||||
using std::vector; | using std::vector; | ||||
using std::list; | using std::list; | ||||