From a1c1199713df47da2a6df31f1499f9f20d77c97d Mon Sep 17 00:00:00 2001 From: Hans Baier Date: Mon, 1 Dec 2008 03:07:11 +0000 Subject: * Sending MIDI Clock while looping works now git-svn-id: svn://localhost/ardour2/branches/3.0@4275 d708f5d6-7413-0410-9779-e7cbd77b26cf --- libs/ardour/ticker.cc | 108 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 74 insertions(+), 34 deletions(-) (limited to 'libs/ardour/ticker.cc') diff --git a/libs/ardour/ticker.cc b/libs/ardour/ticker.cc index 587f6503df..588a49dca5 100644 --- a/libs/ardour/ticker.cc +++ b/libs/ardour/ticker.cc @@ -22,6 +22,8 @@ #include "ardour/session.h" #include "ardour/tempo.h" +#define DEBUG_TICKER 0 + namespace ARDOUR { @@ -58,14 +60,23 @@ void MidiClockTicker::transport_state_changed() { float speed = _session->transport_speed(); nframes_t position = _session->transport_frame(); - //cerr << "Transport state change, speed:" << speed << "position:" << position << endl; +#if DEBUG_TICKER + cerr << "Transport state change, speed:" << speed << "position:" << position<< " play loop " << _session->get_play_loop() << endl; +#endif if (speed == 1.0f) { _last_tick = position; if (!Config->get_send_midi_clock()) return; - if (position == 0) { + if (_session->get_play_loop()) { + assert(_session->locations()->auto_loop_location()); + if (position == _session->locations()->auto_loop_location()->start()) { + send_start_event(0); + } else { + send_continue_event(0); + } + } else if (position == 0) { send_start_event(0); } else { send_continue_event(0); @@ -79,11 +90,15 @@ void MidiClockTicker::transport_state_changed() send_stop_event(0); } + + tick(position, *((ARDOUR::BBT_Time *) 0), *((SMPTE::Time *)0)); } void MidiClockTicker::position_changed(nframes_t position) { +#if DEBUG_TICKER cerr << "Position changed:" << position << endl; +#endif _last_tick = position; } @@ -91,11 +106,67 @@ void MidiClockTicker::transport_looped() { nframes_t position = _session->transport_frame(); - cerr << "Transport looped, position:" << position << endl; + Location* loop_location = _session->locations()->auto_loop_location(); + assert(loop_location); + cerr << "Transport looped, position:" << position + << " loop start " << loop_location->start( ) + << " loop end " << loop_location->end( ) + << " play loop " << _session->get_play_loop() + << endl; + + // adjust _last_tick, so that the next MIDI clock message is sent + // in due time (and the tick interval is still constant) + nframes_t elapsed_since_last_tick = loop_location->end() - _last_tick; + _last_tick = loop_location->start() - elapsed_since_last_tick; +} + +void MidiClockTicker::tick(const nframes_t& transport_frames, const BBT_Time& transport_bbt, const SMPTE::Time& transport_smpt) +{ + if (!Config->get_send_midi_clock() || _session == 0 || _session->transport_speed() != 1.0f) + return; + + while (true) { + double next_tick = _last_tick + one_ppqn_in_frames(transport_frames); + nframes_t next_tick_offset = nframes_t(next_tick) - transport_frames; + +#if DEBUG_TICKER + cerr << "Transport:" << transport_frames + << ":Last tick time:" << _last_tick << ":" + << ":Next tick time:" << next_tick << ":" + << "Offset:" << next_tick_offset << ":" + << "cycle length:" << _jack_port->nframes_this_cycle() + << endl; +#endif + + if (next_tick_offset >= _jack_port->nframes_this_cycle()) + return; + + send_midi_clock_event(next_tick_offset); + + _last_tick = next_tick; + } +} + +double MidiClockTicker::one_ppqn_in_frames(nframes_t transport_position) +{ + const Tempo& current_tempo = _session->tempo_map().tempo_at(transport_position); + const Meter& current_meter = _session->tempo_map().meter_at(transport_position); + double frames_per_beat = + current_tempo.frames_per_beat(_session->nominal_frame_rate(), + current_meter); + + double quarter_notes_per_beat = 4.0 / current_tempo.note_type(); + double frames_per_quarter_note = frames_per_beat / quarter_notes_per_beat; + + return frames_per_quarter_note / double (_ppqn); } void MidiClockTicker::send_midi_clock_event(nframes_t offset) { + assert(_jack_port->is_process_thread()); +#if DEBUG_TICKER + cerr << "Tick with offset " << offset << endl; +#endif static uint8_t _midi_clock_tick[1] = { MIDI_CMD_COMMON_CLOCK }; _jack_port->write(_midi_clock_tick, 1, offset); } @@ -118,36 +189,5 @@ void MidiClockTicker::send_stop_event(nframes_t offset) _jack_port->write(_midi_clock_tick, 1, offset); } -void MidiClockTicker::tick(const nframes_t& transport_frames, const BBT_Time& transport_bbt, const SMPTE::Time& transport_smpt) -{ - if (!Config->get_send_midi_clock() || _session == 0 || _session->transport_speed() != 1.0f) - return; - - const Tempo& current_tempo = _session->tempo_map().tempo_at(transport_frames); - const Meter& current_meter = _session->tempo_map().meter_at(transport_frames); - double frames_per_beat = - current_tempo.frames_per_beat(_session->nominal_frame_rate(), - current_meter); - - double quarter_notes_per_beat = 4.0 / current_tempo.note_type(); - double frames_per_quarter_note = frames_per_beat / quarter_notes_per_beat; - - double one_ppqn_in_frames = frames_per_quarter_note / double (_ppqn); - - double next_tick = _last_tick + one_ppqn_in_frames; - nframes_t next_tick_offset = nframes_t(next_tick) - transport_frames; - - //cerr << "Transport:" << transport_frames << ":Next tick time:" << next_tick << ":" << "Offset:" << next_tick_offset << endl; - - if (next_tick_offset >= _jack_port->nframes_this_cycle()) - return; - - assert(_jack_port->is_process_thread()); - - send_midi_clock_event(next_tick_offset); - - _last_tick = next_tick; -} - } -- cgit v1.2.3