Skip to content

Commit

Permalink
Work on issue #111 improving time-signature support, in progress.
Browse files Browse the repository at this point in the history
  • Loading branch information
ahlstromcj committed Jun 8, 2023
1 parent 223d74b commit ebcbc65
Show file tree
Hide file tree
Showing 19 changed files with 407 additions and 153 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# README for Seq66 0.99.6 2023-06-04
# README for Seq66 0.99.6 2023-06-08

__Seq66__: MIDI sequencer/live-looper with a hardware-sampler grid interface;
pattern banks, triggers, and playlists for song management; scale and chord
Expand Down Expand Up @@ -97,6 +97,8 @@ Windows, and using a conventional source tarball.
velocities in the pattern editor's data pane. Improved
velocity-change undo.
* Fixed an error preventing changing the "background" pattern.
* Issue #111: Adding support, as much as possible, for editing
storing, and displaying time signature.
* Enhanced port-mapping to prompt the user about issues and
allow for an immediate remap-and-restart. Lots of fixes!
* Added 'o' keystroke to seqroll to toggle recording ('r' already
Expand Down
22 changes: 21 additions & 1 deletion TODO
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
TO DO for Seq66 0.99.6 (Sequencer64 refactored for C++14 and Qt)
Chris Ahlstrom
2019-04-13 to 2023-06-04
2019-04-13 to 2023-06-07

Some of these issues will be pushed off for the distant Seq66v2.

Expand Down Expand Up @@ -85,6 +85,10 @@ Ongoing efforts:
- Verify setmapper/setmaster for odd set sizes.
- Perfect the "background recording" feature.

Ideas:

- Drag and drop MIDI files onto seq66 (see sequencer64 issue #137)

ISSUES:

#3 Open loop Pattern Editor window.
Expand Down Expand Up @@ -318,7 +322,23 @@ ISSUES:

STATUS: Undoing the change and commenting on it. Investigating the second
part.

#110 Windows build download

STATUS: works for 64-bit builds, but still working on 32-bit builds.

#111 Time signature changes does not get saved on .midi file

STATUS: In progress. Still need to:

1. Update the seqedit to somehow show a time-signature event.
Maybe show it in position in the data pane, such as "3/4".
2. Get the first load to store the default time-signature if
it is changed.
3. Cause an update to the pop-up event menu to indicate that
there is now a time signature.
4. Do we really need a separate button to log the time signature?

PATTERNS:

- Set pattern editor focus to grid at start unless it is a new one.
Expand Down
Binary file modified data/midi/FM/qufrency.mid
Binary file not shown.
31 changes: 29 additions & 2 deletions libseq66/include/midi/event.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
* \library seq66 application
* \author Chris Ahlstrom
* \date 2015-07-24
* \updates 2023-05-04
* \updates 2023-06-08
* \license GNU GPLv2 or above
*
* This module also declares/defines the various constants, status-byte
Expand Down Expand Up @@ -425,7 +425,13 @@ class event
public:

event ();
event (midipulse tstamp, midibyte status, midibyte d0, midibyte d1 = 0);
event
(
midipulse tstamp,
midibyte status,
midibyte d0 = 0,
midibyte d1 = 0
);
event (midipulse tstamp, midibpm tempo);
event
(
Expand Down Expand Up @@ -738,6 +744,11 @@ class event
return m == EVENT_META_SET_TEMPO;
}

static bool is_time_signature_status (midibyte m)
{
return m == EVENT_META_TIME_SIGNATURE;
}

static bool is_sysex_msg (midibyte m)
{
return m == EVENT_MIDI_SYSEX;
Expand Down Expand Up @@ -1034,6 +1045,11 @@ class event
return m_sysex;
}

midibyte get_sysex (size_t i) const
{
return m_sysex[i];
}

int sysex_size () const
{
return int(m_sysex.size());
Expand Down Expand Up @@ -1342,6 +1358,17 @@ class event
return is_program_change_msg(m_status);
}

/**
* Indicates an event that has a line-drawable data item, such as
* velocity. It is false for discrete data such as program/path number
* or Meta events.
*/

bool is_continuous_event () const
{
return ! is_program_change() && ! is_meta();
}

/**
* Indicates if the event is a System Exclusive event or not.
* We're overloading the SysEx support to handle Meta events as well.
Expand Down
14 changes: 13 additions & 1 deletion libseq66/include/midi/eventlist.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
* \library seq66 application
* \author Chris Ahlstrom
* \date 2015-09-19
* \updates 2023-05-22
* \updates 2023-06-07
* \license GNU GPLv2 or above
*
* This module extracts the event-list functionality from the sequencer
Expand All @@ -52,6 +52,18 @@
* we will now use std::vector for the event list.
*/

/**
* We made some fixes for sequencer64 issue #141 to disable saving the tempo
* into first track. But for Seq66, we do want to be able to save the
* time signature of each pattern with that pattern (especially if different
* from the global time signature). Note that we would support only one
* time-signature per pattern, but unlimited tempo changes. Also note that,
* unlike tempo, time-signature does not affect the playback of MIDI events.
* It changes how they are displayed.
*/

#undef SEQ66_USE_FILL_TIME_SIG_AND_TEMPO

#include <atomic> /* std::atomic<bool> usage */

#include "midi/event.hpp" /* seq66::event, event::buffer */
Expand Down
3 changes: 2 additions & 1 deletion libseq66/include/play/sequence.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
* \library seq66 application
* \author Chris Ahlstrom
* \date 2015-07-30
* \updates 2023-05-29
* \updates 2023-06-07
* \license GNU GPLv2 or above
*
* The functions add_list_var() and add_long_list() have been replaced by
Expand Down Expand Up @@ -1554,6 +1554,7 @@ class sequence
int velocity = sm_preserve_velocity
);
bool add_tempo (midipulse tick, midibpm tempo, bool repaint = false);
bool add_time_signature (midipulse tick, int beats, int width);
bool add_event (const event & er); /* another one declared below */
bool add_event
(
Expand Down
6 changes: 3 additions & 3 deletions libseq66/src/midi/event.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
* \library seq66 application
* \author Chris Ahlstrom
* \date 2015-07-24
* \updates 2023-05-22
* \updates 2023-06-07
* \license GNU GPLv2 or above
*
* A MIDI event (i.e. "track event") is encapsulated by the seq66::event
Expand Down Expand Up @@ -808,7 +808,7 @@ event::append_meta_data (midibyte metatype, const midibyte * data, int dsize)
}
else
{
errprint("event::append_meta_data(): null data");
errprint("event::append_meta_data(null data)");
}
return result;
}
Expand Down Expand Up @@ -841,7 +841,7 @@ event::append_meta_data (midibyte metatype, const midibytes & data)
}
else
{
errprint("event::append_meta_data(): no data");
errprint("event::append_meta_data(no data)");
}
return result;
}
Expand Down
8 changes: 5 additions & 3 deletions libseq66/src/midi/eventlist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
* \library seq66 application
* \author Chris Ahlstrom
* \date 2015-09-19
* \updates 2023-05-22
* \updates 2023-06-08
* \license GNU GPLv2 or above
*
* This container now can indicate if certain Meta events (time-signaure or
Expand Down Expand Up @@ -1782,7 +1782,7 @@ eventlist::unselect_all ()
* \param status
* The desired event in the selection. Now, as a new feature, tempo
* events are also selectable, in addition to events selected by this
* parameter.
* parameter. Oh, and now time-signature events.
*
* \param cc
* The desired control-change in the selection, if the event is a
Expand Down Expand Up @@ -2081,7 +2081,9 @@ eventlist::event_in_range
midipulse tick_s, midipulse tick_f
) const
{
bool result = e.match_status(status) || e.is_tempo();
bool result = e.match_status(status) || e.is_tempo() ||
e.is_time_signature();

if (result)
result = e.timestamp() >= tick_s && e.timestamp() <= tick_f;

Expand Down
2 changes: 1 addition & 1 deletion libseq66/src/midi/midi_vector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ midi_vector::song_fill_track (int track, bool standalone)
fill_seq_number(track);
fill_seq_name(seq().name());

#if defined USE_FILL_TIME_SIG_AND_TEMPO /* issue #141 */
#if defined SEQ66_USE_FILL_TIME_SIG_AND_TEMPO
if (track == rc().tempo_track_number)
{
seq().events().scan_meta_events();
Expand Down
4 changes: 3 additions & 1 deletion libseq66/src/play/performer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
* \library seq66 application
* \author Chris Ahlstrom and others
* \date 2018-11-12
* \updates 2023-06-01
* \updates 2023-06-08
* \license GNU GPLv2 or above
*
* Also read the comments in the Seq64 version of this module, perform.
Expand Down Expand Up @@ -968,6 +968,7 @@ performer::true_input_bus (bussbyte nominalbuss) const
msg += " '";
msg += busname;
msg += "'. Check MIDI inputs and control settings.";
m_port_map_error = true; /* mutable boolean */
append_error_message(msg);
}
}
Expand Down Expand Up @@ -1225,6 +1226,7 @@ performer::true_output_bus (bussbyte nominalbuss) const
msg += " '";
msg += busname;
msg += "'. Check song and MIDI output and display settings.";
m_port_map_error = true; /* mutable boolean */
append_error_message(msg);
}
}
Expand Down
58 changes: 50 additions & 8 deletions libseq66/src/play/sequence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
* \library seq66 application
* \author Chris Ahlstrom
* \date 2015-07-24
* \updates 2023-05-31
* \updates 2023-06-08
* \license GNU GPLv2 or above
*
* The functionality of this class also includes handling some of the
Expand Down Expand Up @@ -3203,6 +3203,42 @@ sequence::add_tempo (midipulse tick, midibpm tempo, bool repaint)
return result;
}

/**
* In setting the time signature here, all we want to do is change the
* beats and beat width. The clocks_per_metronome() and
* get_32nds_per_quarter() stay the same, as they would affect the whole tune.
*
* Data: FF 58 04 n d c b
*
* Warning: The following call actually calls the tempo version of the
* event constructor. Let append_meta_event() set the status to
* EVENT_MIDI_META.
*
* event e (tick, EVENT_MIDI_META);
*/

bool
sequence::add_time_signature (midipulse tick, int beats, int bw)
{
automutex locker(m_mutex);
bool result = beats > 0 && is_power_of_2(bw);
if (result)
{
event e (tick, EVENT_MIDI_META); /* see banner */
midibyte bt[4];
bw = beat_log2(bw); /* log2(bw) */
bt[0] = midibyte(beats); /* numerator */
bt[1] = midibyte(bw); /* denominator */
bt[2] = midibyte(clocks_per_metronome());
bt[3] = midibyte(get_32nds_per_quarter());

bool ok = e.append_meta_data(EVENT_META_TIME_SIGNATURE, bt, 4);
if (ok)
append_event(e);
}
return result;
}

/**
* Adds an event to the internal event list in a sorted manner. Then it
* resets the draw-marker and sets the dirty flag.
Expand Down Expand Up @@ -4825,7 +4861,7 @@ sequence::get_next_event
*
* \return
* Returns true if the current event was one of the desired ones, or was
* a Tempo event. In this case, the caller <i> must </i> increment the
* a Tempo or Time Signature event (the Meta events whose drawing in qseqdata * supported). In this case, the caller <i> must </i> increment the
* iterator.
*/

Expand All @@ -4843,8 +4879,10 @@ sequence::get_next_event_match
return false; /* bug out immediately */

const event & drawevent = eventlist::cdref(evi);
bool istempo = drawevent.is_tempo();
bool ok = drawevent.match_status(status) || istempo;
bool isdrawablemeta = drawevent.is_tempo() ||
drawevent.is_time_signature();

bool ok = drawevent.match_status(status) || isdrawablemeta;
if (! ok)
ok = status == EVENT_ANY;

Expand All @@ -4857,7 +4895,9 @@ sequence::get_next_event_match
* Broken for this purpose: ok = drawevent.is_desired(status, cc);
*/

ok = istempo || event::is_desired_cc_or_not_cc(status, cc, d0);
ok = isdrawablemeta ||
event::is_desired_cc_or_not_cc(status, cc, d0);

if (ok)
return true; /* must ++evi after call */
}
Expand All @@ -4880,9 +4920,11 @@ sequence::get_next_meta_match
return false; /* bug out immediately */

const event & drawevent = eventlist::cdref(evi);
if (drawevent.is_meta() && drawevent.channel() == metamsg)
return true;

if (drawevent.is_meta())
{
if (drawevent.channel() == metamsg)
return true;
}
++evi; /* keep going here */
}
return false;
Expand Down
Loading

0 comments on commit ebcbc65

Please sign in to comment.