Skip to content

Commit

Permalink
Update MIDI loading and parsing
Browse files Browse the repository at this point in the history
portsmf fixes:
* Fix allegro warnings as errors
* Fix msvc missing max. Use MAX macro instead
  • Loading branch information
Veratil committed Sep 12, 2020
1 parent 87b9495 commit 737f652
Show file tree
Hide file tree
Showing 8 changed files with 123 additions and 99 deletions.
49 changes: 26 additions & 23 deletions plugins/MidiImport/MidiImport.cpp
Expand Up @@ -31,6 +31,7 @@
#include <QProgressDialog>

#include <sstream>
#include <unordered_map>

#include "MidiImport.h"
#include "TrackContainer.h"
Expand Down Expand Up @@ -305,7 +306,7 @@ class smfMidiChannel

bool MidiImport::readSMF( TrackContainer* tc )
{

const int MIDI_CC_COUNT = 128 + 1; // 0-127 (128) + pitch bend
const int preTrackSteps = 2;
QProgressDialog pd( TrackContainer::tr( "Importing MIDI-file..." ),
TrackContainer::tr( "Cancel" ), 0, preTrackSteps, gui->mainWindow() );
Expand All @@ -315,19 +316,20 @@ bool MidiImport::readSMF( TrackContainer* tc )

pd.setValue( 0 );

std::stringstream stream;
QByteArray arr = readAllData();
stream.str(std::string(arr.constData(), arr.size()));

std::istringstream stream(readAllData().toStdString());
Alg_seq_ptr seq = new Alg_seq(stream, true);
seq->convert_to_beats();

pd.setMaximum( seq->tracks() + preTrackSteps );
pd.setValue( 1 );

// 128 CC + Pitch Bend
smfMidiCC ccs[129];
smfMidiChannel chs[256];
smfMidiCC ccs[MIDI_CC_COUNT];

// channels can be set out of 256 range
// using unordered_map should fix most invalid loads and crashes while loading
std::unordered_map<long, smfMidiChannel> chs;
// NOTE: unordered_map::operator[] creates a new element if none exists

MeterModel & timeSigMM = Engine::getSong()->getTimeSigModel();
AutomationTrack * nt = dynamic_cast<AutomationTrack*>(
Expand Down Expand Up @@ -407,7 +409,7 @@ bool MidiImport::readSMF( TrackContainer* tc )
Alg_track_ptr trk = seq->track( t );
pd.setValue( t + preTrackSteps );

for( int c = 0; c < 129; c++ )
for( int c = 0; c < MIDI_CC_COUNT; c++ )
{
ccs[c].clear();
}
Expand All @@ -423,7 +425,10 @@ bool MidiImport::readSMF( TrackContainer* tc )
if( evt->is_update() )
{
QString attr = evt->get_attribute();
if( attr == "tracknames" && evt->get_update_type() == 's' ) {
// seqnames is a track0 identifier (see allegro code)
if (attr == (t == 0 ? "seqnames" : "tracknames")
&& evt->get_update_type() == 's')
{
trackName = evt->get_string_value();
handled = true;
}
Expand All @@ -444,7 +449,7 @@ bool MidiImport::readSMF( TrackContainer* tc )
printf( "\n" );
}
}
else if( evt->is_note() && evt->chan < 256 )
else if (evt->is_note())
{
smfMidiChannel * ch = chs[evt->chan].create( tc, trackName );
Alg_note_ptr noteEvt = dynamic_cast<Alg_note_ptr>( evt );
Expand Down Expand Up @@ -558,28 +563,26 @@ bool MidiImport::readSMF( TrackContainer* tc )
delete seq;


for( int c=0; c < 256; ++c )
for( auto& c: chs )
{
if (chs[c].hasNotes)
if (c.second.hasNotes)
{
chs[c].splitPatterns();
c.second.splitPatterns();
}
else if (chs[c].it)
else if (c.second.it)
{
printf(" Should remove empty track\n");
// must delete trackView first - but where is it?
//tc->removeTrack( chs[c].it );
//it->deleteLater();
}
}

// Set channel 10 to drums as per General MIDI's orders
if( chs[9].hasNotes && chs[9].it_inst && chs[9].isSF2 )
{
// AFAIK, 128 should be the standard bank for drums in SF2.
// If not, this has to be made configurable.
chs[9].it_inst->childModel( "bank" )->setValue( 128 );
chs[9].it_inst->childModel( "patch" )->setValue( 0 );
// Set channel 10 to drums as per General MIDI's orders
if (c.first % 16l == 9 /* channel 10 */
&& c.second.hasNotes && c.second.it_inst && c.second.isSF2)
{
c.second.it_inst->childModel("bank")->setValue(128);
c.second.it_inst->childModel("patch")->setValue(0);
}
}

return true;
Expand Down
40 changes: 21 additions & 19 deletions plugins/MidiImport/portsmf/allegro.cpp
Expand Up @@ -30,7 +30,7 @@ using namespace std;
// 4311 is type cast ponter to long warning
// 4996 is warning against strcpy
// 4267 is size_t to long warning
#pragma warning(disable: 4311 4996 4267)
//#pragma warning(disable: 4311 4996 4267)
Alg_atoms symbol_table;
Serial_read_buffer Alg_track::ser_read_buf; // declare the static variables
Serial_write_buffer Alg_track::ser_write_buf;
Expand Down Expand Up @@ -720,7 +720,7 @@ Alg_event_list::Alg_event_list(Alg_track *owner)
}


Alg_event_ptr &Alg_event_list::operator [](int i)
Alg_event_ptr const &Alg_event_list::operator [](int i)
{
assert(i >= 0 && i < len);
return events[i];
Expand All @@ -739,8 +739,8 @@ void Alg_event_list::set_start_time(Alg_event *event, double t)
// For Alg_track, change the time and move the event to the right place
// For Alg_seq, find the track and do the update there

long index, i;
Alg_track_ptr track_ptr;
long index = 0, i;
Alg_track_ptr track_ptr = nullptr;
if (type == 'e') { // this is an Alg_event_list
// make sure the owner has not changed its event set
assert(events_owner &&
Expand Down Expand Up @@ -1522,7 +1522,7 @@ Alg_track *Alg_track::unserialize(void *buffer, long len)
bool alg = ser_read_buf.get_char() == 'A' &&
ser_read_buf.get_char() == 'L' &&
ser_read_buf.get_char() == 'G';
assert(alg);
assert(alg); (void)alg; // unused variable
char c = ser_read_buf.get_char();
if (c == 'S') {
Alg_seq *seq = new Alg_seq;
Expand All @@ -1539,7 +1539,7 @@ Alg_track *Alg_track::unserialize(void *buffer, long len)
}


#pragma warning(disable: 4800) // long to bool performance warning
//#pragma warning(disable: 4800) // long to bool performance warning

/* Note: this Alg_seq must have a default initialized Alg_time_map.
* It will be filled in with data from the ser_read_buf buffer.
Expand All @@ -1551,9 +1551,9 @@ void Alg_seq::unserialize_seq()
(ser_read_buf.get_char() == 'L') &&
(ser_read_buf.get_char() == 'G') &&
(ser_read_buf.get_char() == 'S');
assert(algs);
assert(algs); (void)algs; // unused variable
long len = ser_read_buf.get_int32();
assert(ser_read_buf.get_len() >= len);
assert(ser_read_buf.get_len() >= len); (void)len; // unused variable
channel_offset_per_track = ser_read_buf.get_int32();
units_are_seconds = ser_read_buf.get_int32() != 0;
beat_dur = ser_read_buf.get_double();
Expand Down Expand Up @@ -1599,10 +1599,10 @@ void Alg_track::unserialize_track()
(ser_read_buf.get_char() == 'L') &&
(ser_read_buf.get_char() == 'G') &&
(ser_read_buf.get_char() == 'T');
assert(algt);
assert(algt); (void)algt; // unused variable
long offset = ser_read_buf.get_posn(); // stored length does not include 'ALGT'
long bytes = ser_read_buf.get_int32();
assert(bytes <= ser_read_buf.get_len() - offset);
assert(bytes <= ser_read_buf.get_len() - offset); (void)offset; (void)bytes; // unused variable
units_are_seconds = (bool) ser_read_buf.get_int32();
beat_dur = ser_read_buf.get_double();
real_dur = ser_read_buf.get_double();
Expand Down Expand Up @@ -1672,7 +1672,7 @@ void Alg_track::unserialize_parameter(Alg_parameter_ptr parm_ptr)
}
}

#pragma warning(default: 4800)
//#pragma warning(default: 4800)

void Alg_track::set_time_map(Alg_time_map *map)
{
Expand Down Expand Up @@ -1840,6 +1840,7 @@ void Alg_track::paste(double t, Alg_event_list *seq)
bool prev_units_are_seconds;
if (seq->get_type() == 'e') {
assert(seq->get_owner()->get_units_are_seconds() == units_are_seconds);
prev_units_are_seconds = seq->get_owner()->get_units_are_seconds();
} else { // make it match
Alg_track_ptr tr = (Alg_track_ptr) seq;
prev_units_are_seconds = tr->get_units_are_seconds();
Expand Down Expand Up @@ -2381,14 +2382,14 @@ void Alg_time_sigs::paste(double start, Alg_seq *seq)
double num_of_insert = 4.0;
double den_of_insert = 4.0;
double beat_of_insert = 0.0;
int first_from_index = 0; // where to start copying from
/* int first_from_index = 0; // where to start copying from TODO: LMMS commented out unused variable */
if (from.length() > 0 && from[0].beat < ALG_EPS) {
// there is an initial time signature in "from"
num_of_insert = from[0].num;
den_of_insert = from[0].den;
// since we are handling the first time signature in from,
// we can start copying at index == 1:
first_from_index = 1;
/* first_from_index = 1; TODO: LMMS commented out unused variable */
}
// compare time signatures to see if we need a change at start:
if (num_before_splice != num_of_insert ||
Expand Down Expand Up @@ -2431,14 +2432,14 @@ void Alg_time_sigs::paste(double start, Alg_seq *seq)
double measures = (start - beat_after_splice) / beats_per_measure;
// Measures might be slightly negative due to rounding. Use max()
// to eliminate any negative rounding error:
int imeasures = int(max(measures, 0.0));
int imeasures = int(MAX(measures, 0.0));
double old_bar_loc = beat_after_splice + (imeasures * beats_per_measure);
if (old_bar_loc < start) old_bar_loc += beats_per_measure;
// now old_bar_loc is the original first bar position after start
// Do similar calculation for position after end after the insertion:
// beats_per_measure already calculated because signatures match
measures = (start + dur - beat_of_insert) / beats_per_measure;
imeasures = int(max(measures, 0.0));
imeasures = int(MAX(measures, 0.0));
double new_bar_loc = beat_of_insert + (imeasures * beats_per_measure);
if (new_bar_loc < start + dur) new_bar_loc += beats_per_measure;
// old_bar_loc should be shifted by dur:
Expand Down Expand Up @@ -2864,9 +2865,9 @@ Alg_track_ptr Alg_seq::track(int i)
return &(track_list[i]);
}

#pragma warning(disable: 4715) // ok not to return a value here
//#pragma warning(disable: 4715) // ok not to return a value here

Alg_event_ptr &Alg_seq::operator[](int i)
Alg_event_ptr const &Alg_seq::operator[](int i)
{
int ntracks = track_list.length();
int tr = 0;
Expand All @@ -2880,8 +2881,9 @@ Alg_event_ptr &Alg_seq::operator[](int i)
tr++;
}
assert(false); // out of bounds
return NULL;
}
#pragma warning(default: 4715)
//#pragma warning(default: 4715)


void Alg_seq::convert_to_beats()
Expand Down Expand Up @@ -3044,7 +3046,7 @@ void Alg_seq::insert_silence(double t, double len)
// Final duration is defined to be t + len + whatever was
// in the sequence after t (if any). This translates to
// t + len + max(dur - t, 0)
set_dur(t + len + max(get_dur() - t, 0.0));
set_dur(t + len + MAX(get_dur() - t, 0.0));
}


Expand Down
33 changes: 17 additions & 16 deletions plugins/MidiImport/portsmf/allegro.h
Expand Up @@ -391,7 +391,7 @@ typedef class Alg_event_list : public Alg_events {
// When applied to an Alg_seq, events are enumerated track
// by track with increasing indices. This operation is not
// particularly fast on an Alg_seq.
virtual Alg_event_ptr &operator[](int i);
virtual Alg_event_ptr const &operator[](int i);
Alg_event_list() { sequence_number = 0;
beat_dur = 0.0; real_dur = 0.0; events_owner = NULL; type = 'e'; }
Alg_event_list(Alg_track *owner);
Expand Down Expand Up @@ -549,12 +549,12 @@ typedef class Serial_read_buffer : public Serial_buffer {
// does nothing.
virtual ~Serial_read_buffer() { }
#if defined(_WIN32)
#pragma warning(disable: 546) // cast to int is OK, we only want low 7 bits
#pragma warning(disable: 4311) // type cast pointer to long warning
//#pragma warning(disable: 546) // cast to int is OK, we only want low 7 bits
//#pragma warning(disable: 4311) // type cast pointer to long warning
#endif
void get_pad() { while (((long) ptr) & 7) ptr++; }
void get_pad() { while ((intptr_t) ptr & 7) ptr++; }
#if defined(_WIN32)
#pragma warning(default: 4311 546)
//#pragma warning(default: 4311 546)
#endif
// Prepare to read n bytes from buf. The caller must manage buf: it is
// valid until reading is finished, and it is caller's responsibility
Expand All @@ -571,7 +571,7 @@ typedef class Serial_read_buffer : public Serial_buffer {
double get_double() { double d = *((double *) ptr); ptr += sizeof(double);
return d; }
const char *get_string() { char *s = ptr; char *fence = buffer + len;
assert(ptr < fence);
assert(ptr < fence); (void)fence; // unused variable
while (*ptr++) assert(ptr < fence);
get_pad();
return s; }
Expand Down Expand Up @@ -600,31 +600,31 @@ typedef class Serial_write_buffer: public Serial_buffer {
void check_buffer(long needed);
void set_string(const char *s) {
char *fence = buffer + len;
assert(ptr < fence);
assert(ptr < fence); (void)fence; // unused variable
// two brackets surpress a g++ warning, because this is an
// assignment operator inside a test.
while ((*ptr++ = *s++)) assert(ptr < fence);
// 4311 is type cast pointer to long warning
// 4312 is type cast long to pointer warning
#if defined(_WIN32)
#pragma warning(disable: 4311 4312)
//#pragma warning(disable: 4311 4312)
#endif
assert((char *)(((long) (ptr + 7)) & ~7) <= fence);
#if defined(_WIN32)
#pragma warning(default: 4311 4312)
//#pragma warning(default: 4311 4312)
#endif
pad(); }
void set_int32(long v) { *((long *) ptr) = v; ptr += 4; }
void set_double(double v) { *((double *) ptr) = v; ptr += 8; }
void set_float(float v) { *((float *) ptr) = v; ptr += 4; }
void set_char(char v) { *ptr++ = v; }
#if defined(_WIN32)
#pragma warning(disable: 546) // cast to int is OK, we only want low 7 bits
#pragma warning(disable: 4311) // type cast pointer to long warning
//#pragma warning(disable: 546) // cast to int is OK, we only want low 7 bits
//#pragma warning(disable: 4311) // type cast pointer to long warning
#endif
void pad() { while (((long) ptr) & 7) set_char(0); }
void pad() { while ((intptr_t) ptr & 7) set_char(0); }
#if defined(_WIN32)
#pragma warning(default: 4311 546)
//#pragma warning(default: 4311 546)
#endif
void *to_heap(long *len) {
*len = get_posn();
Expand Down Expand Up @@ -653,7 +653,7 @@ typedef class Alg_track : public Alg_event_list {
public:
void serialize_track();
void unserialize_track();
virtual Alg_event_ptr &operator[](int i) {
virtual Alg_event_ptr const &operator[](int i) {
assert(i >= 0 && i < len);
return events[i];
}
Expand All @@ -669,7 +669,8 @@ typedef class Alg_track : public Alg_event_list {
Alg_track(Alg_event_list_ref event_list, Alg_time_map_ptr map,
bool units_are_seconds);
virtual ~Alg_track() { // note: do not call set_time_map(NULL)!
if (time_map) time_map->dereference(); time_map = NULL; }
if (time_map) time_map->dereference();
time_map = NULL; }

// Returns a buffer containing a serialization of the
// file. It will be an ASCII representation unless text is true.
Expand Down Expand Up @@ -1058,7 +1059,7 @@ typedef class Alg_seq : public Alg_track {
// caller must not delete the result.
Alg_track_ptr track(int);

virtual Alg_event_ptr &operator[](int i);
virtual Alg_event_ptr const &operator[](int i);

virtual void convert_to_seconds();
virtual void convert_to_beats();
Expand Down

0 comments on commit 737f652

Please sign in to comment.