Skip to content

Commit 714ea0c

Browse files
committed
Merge branch 'pr43/swesterfeld-midi-events-uint-offset' - closes #26
* pr43/swesterfeld-midi-events-uint-offset: devices/liquidsfz/liquidsfz.cc: avoid using printf (use printerr instead) ASE: midievent.hh: fix clang tidy problem (add typename) devices/saturation/saturation.cc: midi event frame offsets are now unsigned devices/liquidsfz/liquidsfz.cc: midi event frame offsets are now unsigned devices/blepsynth/blepsynth.cc: midi event frame offsets are now unsigned ASE: midilib.cc: midi event frame offsets are now always positive (#26) ASE: clapplugin.cc: midi event frame offsets are now always positive (#26) ASE: midievent: avoid negative frame offsets in midi events Use unsigned data type for midi event offset, see issue #26. ase/memory.cc: avoid constexpr std::string use that needs clang++-17 Signed-off-by: Tim Janik <timj@gnu.org>
2 parents 02e6083 + 25c0f8a commit 714ea0c

8 files changed

Lines changed: 38 additions & 41 deletions

File tree

ase/clapplugin.cc

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -555,55 +555,55 @@ ClapAudioProcessor::convert_clap_events (const clap_process_t &process, const bo
555555
case MidiMessage::NOTE_OFF:
556556
case MidiMessage::AFTERTOUCH:
557557
if (as_clapnotes && ev.type == MidiEvent::AFTERTOUCH) {
558-
expr = setup_expression (&input_events_[j++], MAX (ev.frame, 0), 0);
558+
expr = setup_expression (&input_events_[j++], ev.frame, 0);
559559
expr->expression_id = CLAP_NOTE_EXPRESSION_PRESSURE;
560560
expr->note_id = ev.noteid;
561561
expr->channel = ev.channel;
562562
expr->key = ev.key;
563563
expr->value = ev.velocity;
564564
} else if (as_clapnotes) {
565-
evnote = setup_evnote (&input_events_[j++], MAX (ev.frame, 0), 0);
565+
evnote = setup_evnote (&input_events_[j++], ev.frame, 0);
566566
evnote->header.type = ev.type == MidiEvent::NOTE_ON ? CLAP_EVENT_NOTE_ON : CLAP_EVENT_NOTE_OFF;
567567
evnote->note_id = ev.noteid;
568568
evnote->channel = ev.channel;
569569
evnote->key = ev.key;
570570
evnote->velocity = ev.velocity;
571571
} else {
572-
midi1 = setup_midi1 (&input_events_[j++], MAX (ev.frame, 0), 0);
572+
midi1 = setup_midi1 (&input_events_[j++], ev.frame, 0);
573573
midi1->data[0] = uint8_t (ev.type) | (ev.channel & 0xf);
574574
midi1->data[1] = ev.key;
575575
midi1->data[2] = std::min (uint8_t (ev.velocity * 127), uint8_t (127));
576576
}
577577
break;
578578
case MidiMessage::ALL_NOTES_OFF:
579579
if (as_clapnotes) {
580-
evnote = setup_evnote (&input_events_[j++], MAX (ev.frame, 0), 0);
580+
evnote = setup_evnote (&input_events_[j++], ev.frame, 0);
581581
evnote->header.type = CLAP_EVENT_NOTE_CHOKE;
582582
evnote->note_id = -1;
583583
evnote->channel = -1;
584584
evnote->key = -1;
585585
evnote->velocity = 0;
586586
} else {
587-
midi1 = setup_midi1 (&input_events_[j++], MAX (ev.frame, 0), 0);
587+
midi1 = setup_midi1 (&input_events_[j++], ev.frame, 0);
588588
midi1->data[0] = 0xB0 | (ev.channel & 0xf);
589589
midi1->data[1] = 123;
590590
midi1->data[2] = 0;
591591
}
592592
break;
593593
case MidiMessage::CONTROL_CHANGE:
594-
midi1 = setup_midi1 (&input_events_[j++], MAX (ev.frame, 0), 0);
594+
midi1 = setup_midi1 (&input_events_[j++], ev.frame, 0);
595595
midi1->data[0] = 0xB0 | (ev.channel & 0xf);
596596
midi1->data[1] = ev.param;
597597
midi1->data[2] = ev.cval;
598598
break;
599599
case MidiMessage::CHANNEL_PRESSURE:
600-
midi1 = setup_midi1 (&input_events_[j++], MAX (ev.frame, 0), 0);
600+
midi1 = setup_midi1 (&input_events_[j++], ev.frame, 0);
601601
midi1->data[0] = 0xD0 | (ev.channel & 0xf);
602602
midi1->data[1] = std::min (uint8_t (ev.velocity * 127), uint8_t (127));
603603
midi1->data[2] = 0;
604604
break;
605605
case MidiMessage::PITCH_BEND:
606-
midi1 = setup_midi1 (&input_events_[j++], MAX (ev.frame, 0), 0);
606+
midi1 = setup_midi1 (&input_events_[j++], ev.frame, 0);
607607
midi1->data[0] = 0xE0 | (ev.channel & 0xf);
608608
midi1->data[1] = std::min (uint8_t (ev.velocity * 127), uint8_t (127));
609609
midi1->data[2] = 0;

ase/memory.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -567,9 +567,9 @@ class CStringTable {
567567
StrPtrMap quarks_;
568568
std::vector<const String*> strings_;
569569
std::shared_mutex mutex_;
570-
static constexpr String empty_string;
571570
CStringTable()
572571
{
572+
static String empty_string;
573573
strings_ = { &empty_string }; // ID==0
574574
quarks_[&empty_string] = 0;
575575
}
@@ -608,7 +608,7 @@ CStringTable::lookup (uint quark) noexcept
608608
const std::unique_lock ulock (mutex_);
609609
if (quark < strings_.size()) [[likely]]
610610
return *strings_[quark];
611-
return empty_string;
611+
return *strings_[0]; // empty_string;
612612
}
613613

614614
/// Assign a std::string to a CString, after deduplication, its memory is never released.

ase/midievent.cc

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -50,32 +50,32 @@ MidiEvent::to_string () const
5050
switch (type)
5151
{
5252
case PARAM_VALUE:
53-
return string_format ("%+4d ch=%-2u %s param=%d pvalue=%.5f",
53+
return string_format ("%4u ch=%-2u %s param=%d pvalue=%.5f",
5454
frame, channel, "PARAM_VALUE", param, pvalue);
5555
case NOTE_OFF: if (!et) et = "NOTE_OFF";
5656
/* fall-through */
5757
case NOTE_ON: if (!et) et = "NOTE_ON";
5858
/* fall-through */
5959
case AFTERTOUCH: if (!et) et = "AFTERTOUCH";
60-
return string_format ("%+4d ch=%-2u %-10s pitch=%d vel=%f tune=%f id=%x",
60+
return string_format ("%4u ch=%-2u %-10s pitch=%d vel=%f tune=%f id=%x",
6161
frame, channel, et, key, velocity, tuning, noteid);
6262
case CONTROL_CHANGE: if (!et) et = "CONTROL_CHANGE";
63-
return string_format ("%+4d ch=%-2u %s control=%d value=%f (%02x) {%u}",
63+
return string_format ("%4u ch=%-2u %s control=%d value=%f (%02x) {%u}",
6464
frame, channel, et, param, value, cval, fragment);
6565
case PROGRAM_CHANGE: if (!et) et = "PROGRAM_CHANGE";
66-
return string_format ("%+4d ch=%-2u %s program=%d",
66+
return string_format ("%4u ch=%-2u %s program=%d",
6767
frame, channel, et, param);
6868
case CHANNEL_PRESSURE: if (!et) et = "CHANNEL_PRESSURE";
6969
/* fall-through */
7070
case PITCH_BEND: if (!et) et = "PITCH_BEND";
71-
return string_format ("%+4d ch=%-2u %s value=%+f",
71+
return string_format ("%4u ch=%-2u %s value=%+f",
7272
frame, channel, et, value);
7373
case SYSEX: if (!et) et = "SYSEX";
74-
return string_format ("%+4d %s (unhandled)", frame, et);
74+
return string_format ("%4u %s (unhandled)", frame, et);
7575
}
7676
static_assert (sizeof (MidiEvent) >= 2 * sizeof (uint64_t));
7777
const uint64_t *uu = reinterpret_cast<const uint64_t*> (this);
78-
return string_format ("%+4d MidiEvent-%u (%08x %08x)", frame, type, uu[0], uu[1]);
78+
return string_format ("%4u MidiEvent-%u (%08x %08x)", frame, type, uu[0], uu[1]);
7979
}
8080

8181
MidiEvent
@@ -190,7 +190,10 @@ MidiEventOutput::append (int16_t frame, const MidiEvent &event)
190190
bool
191191
MidiEventOutput::append_unsorted (int16_t frame, const MidiEvent &event)
192192
{
193-
const int64_t last_event_stamp = !events_.empty() ? events_.back().frame : -2048;
193+
// we discard timing information by ignoring negative frame offsets here (#26)
194+
// when we implement recording, we might want to preserve the exact timestamp
195+
frame = std::max<int16_t> (frame, 0);
196+
const int64_t last_event_stamp = !events_.empty() ? events_.back().frame : 0;
194197
events_.push_back (event);
195198
events_.back().frame = frame;
196199
return frame < last_event_stamp;
@@ -209,7 +212,7 @@ MidiEventOutput::ensure_order ()
209212
int64_t
210213
MidiEventOutput::last_frame () const
211214
{
212-
return !events_.empty() ? events_.back().frame : -2048;
215+
return !events_.empty() ? events_.back().frame : 0;
213216
}
214217

215218
} // Ase

ase/midievent.hh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ enum class MidiMessage : int32_t {
4949
/// MidiEvent data structure.
5050
struct MidiEvent {
5151
using enum MidiEventType;
52-
static_assert (AUDIO_BLOCK_MAX_RENDER_SIZE <= 2048); // -2048…+2047 fits frame
53-
int frame : 12; ///< Offset into current block, delayed if negative
52+
static_assert (AUDIO_BLOCK_MAX_RENDER_SIZE <= 4096); // 0…+4095 fits frame
53+
uint frame : 12; ///< Offset into current block, delayed if negative
5454
uint channel : 4; ///< 0…15 for standard events
5555
MidiEventType type; ///< MidiEvent type, one of the MidiEventType members
5656
union {
@@ -118,7 +118,7 @@ class MidiEventReader : QueueMultiplexer<MAXQUEUES,std::vector<MidiEvent>::const
118118
using Base = QueueMultiplexer<MAXQUEUES,std::vector<MidiEvent>::const_iterator>;
119119
ASE_CLASS_NON_COPYABLE (MidiEventReader);
120120
public:
121-
using iterator = Base::iterator;
121+
using iterator = typename Base::iterator;
122122
using Base::assign;
123123
size_t events_pending () const { return this->count_pending(); }
124124
iterator begin () { return this->Base::begin(); }

ase/midilib.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ class MidiProducerImpl : public MidiProducerIface {
146146
TickEvent tnote = future_stack.back();
147147
future_stack.pop_back();
148148
const int64 frame = transport.sample_from_tick (tnote.tick - begin_tick);
149-
assert_paranoid (frame >= -2048 && frame <= 2047);
149+
assert_paranoid (frame >= 0 && frame <= 4095);
150150
MDEBUG ("POP: t=%d ev=%s f=%d\n", tnote.tick, tnote.event.to_string(), frame);
151151
evout.append_unsorted (frame, tnote.event);
152152
}
@@ -171,7 +171,7 @@ class MidiProducerImpl : public MidiProducerIface {
171171
if (etick < end_tick)
172172
{
173173
const int64 frame = transport.sample_from_tick (etick - begin_tick);
174-
assert_paranoid (frame >= -2048 && frame <= 2047);
174+
assert_paranoid (frame >= 0 && frame <= 4095);
175175
// interleave with earlier MIDI through events
176176
evout.append_unsorted (frame, event);
177177
MDEBUG ("NOW: t=%d ev=%s f=%d\n", etick, event.to_string(), frame);

devices/blepsynth/blepsynth.cc

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -996,11 +996,9 @@ class BlepSynth : public AudioProcessor {
996996
MidiEventInput evinput = midi_event_input();
997997
for (const auto &ev : evinput)
998998
{
999-
uint frame = std::max<int> (ev.frame, 0); // TODO: should be unsigned anyway, issue #26
1000-
1001999
// process any audio that is before the event
1002-
render_audio (left_out + offset, right_out + offset, frame - offset);
1003-
offset = frame;
1000+
render_audio (left_out + offset, right_out + offset, ev.frame - offset);
1001+
offset = ev.frame;
10041002

10051003
switch (ev.message())
10061004
{

devices/liquidsfz/liquidsfz.cc

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,9 @@ class LiquidSFZLoader
3535
{
3636
if (want_sfz_ != have_sfz_)
3737
{
38-
printf ("LiquidSFZ: loading %s...", want_sfz_.c_str());
39-
fflush (stdout);
38+
printerr ("LiquidSFZ: loading %s...", want_sfz_.c_str());
4039
bool result = synth_.load (want_sfz_);
41-
printf ("%s\n", result ? "OK" : "FAIL");
40+
printerr ("%s\n", result ? "OK" : "FAIL");
4241
// TODO: handle load error
4342

4443
have_sfz_ = want_sfz_;
@@ -51,22 +50,22 @@ class LiquidSFZLoader
5150
state_.store (STATE_IDLE);
5251
}
5352
}
54-
printf ("run() done\n");
53+
printerr ("LiquidSFZ: run() done\n");
5554
}
5655
public:
5756
LiquidSFZLoader (Synth &synth) :
5857
synth_ (synth)
5958
{
6059
thread_ = std::thread (&LiquidSFZLoader::run, this);
6160
want_sfz_.reserve (4096); // avoid allocations in audio thread
62-
printf ("LiquidSFZLoader()\n");
61+
printerr ("LiquidSFZLoader()\n");
6362
}
6463
~LiquidSFZLoader()
6564
{
6665
quit_.store (1);
6766
sem_.post();
6867
thread_.join();
69-
printf ("~LiquidSFZLoader()\n");
68+
printerr ("~LiquidSFZLoader()\n");
7069
}
7170
// called from audio thread
7271
bool
@@ -182,14 +181,13 @@ class LiquidSFZ : public AudioProcessor {
182181
MidiEventInput evinput = midi_event_input();
183182
for (const auto &ev : evinput)
184183
{
185-
const int time_stamp = std::max<int> (ev.frame, 0);
186184
switch (ev.message())
187185
{
188186
case MidiMessage::NOTE_OFF:
189-
synth_.add_event_note_off (time_stamp, ev.channel, ev.key);
187+
synth_.add_event_note_off (ev.frame, ev.channel, ev.key);
190188
break;
191189
case MidiMessage::NOTE_ON:
192-
synth_.add_event_note_on (time_stamp, ev.channel, ev.key, std::clamp (irintf (ev.velocity * 127), 0, 127));
190+
synth_.add_event_note_on (ev.frame, ev.channel, ev.key, std::clamp (irintf (ev.velocity * 127), 0, 127));
193191
break;
194192
case MidiMessage::ALL_NOTES_OFF:
195193
case MidiMessage::ALL_SOUND_OFF:

devices/saturation/saturation.cc

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,9 @@ class Saturation : public AudioProcessor {
9191
MidiEventInput evinput = midi_event_input();
9292
for (const auto &ev : evinput)
9393
{
94-
uint frame = std::max<int> (ev.frame, 0); // TODO: should be unsigned anyway, issue #26
95-
9694
// process any audio that is before the event
97-
render_audio (left_in + offset, right_in + offset, left_out + offset, right_out + offset, frame - offset);
98-
offset = frame;
95+
render_audio (left_in + offset, right_in + offset, left_out + offset, right_out + offset, ev.frame - offset);
96+
offset = ev.frame;
9997

10098
switch (ev.message())
10199
{

0 commit comments

Comments
 (0)