diff options
author | Damien Zammit <damien@zamaudio.com> | 2017-02-16 01:17:00 +1100 |
---|---|---|
committer | Damien Zammit <damien@zamaudio.com> | 2017-02-16 01:17:00 +1100 |
commit | 317b19b0657fd9bc3bb0157dd504e1d7d27cde89 (patch) | |
tree | 4314d650389e5fa55f6684e2bf29b0b643574220 | |
parent | 6e9bf3af79bec6cf605cd52ae243c2035b40de52 (diff) |
Add preliminary MIDI support (1 track only)
Signed-off-by: Damien Zammit <damien@zamaudio.com>
-rw-r--r-- | ptfformat.cc | 125 | ||||
-rw-r--r-- | ptfformat.h | 12 | ||||
-rw-r--r-- | ptftool.cc | 103 |
3 files changed, 184 insertions, 56 deletions
diff --git a/ptfformat.cc b/ptfformat.cc index ac3a02f..9e6e505 100644 --- a/ptfformat.cc +++ b/ptfformat.cc @@ -248,6 +248,7 @@ PTFFormat::parse(void) { return -1; parseaudio5(); parserest5(); + parsemidi(); } else if (version == 7) { parse7header(); setrates(); @@ -255,6 +256,7 @@ PTFFormat::parse(void) { return -1; parseaudio(); parserest89(); + parsemidi(); } else if (version == 8) { parse8header(); setrates(); @@ -262,6 +264,7 @@ PTFFormat::parse(void) { return -1; parseaudio(); parserest89(); + parsemidi(); } else if (version == 9) { parse9header(); setrates(); @@ -269,6 +272,7 @@ PTFFormat::parse(void) { return -1; parseaudio(); parserest89(); + parsemidi(); } else if (version == 10 || version == 11 || version == 12) { parse10header(); setrates(); @@ -276,6 +280,7 @@ PTFFormat::parse(void) { return -1; parseaudio(); parserest10(); + parsemidi(); } else { // Should not occur return -1; @@ -530,6 +535,7 @@ PTFFormat::parserest5(void) { vector<wav_t>::iterator found; // Add file to lists if ((found = std::find(begin, finish, f)) != finish) { + std::vector<midi_ev_t> m; region_t r = { name, rindex, @@ -537,6 +543,7 @@ PTFFormat::parserest5(void) { (int64_t)(sampleoffset*ratefactor), (int64_t)(length*ratefactor), *found, + m }; regions.push_back(r); vector<track_t>::iterator ti; @@ -556,6 +563,7 @@ PTFFormat::parserest5(void) { }; tracks.push_back(t); } else { + std::vector<midi_ev_t> m; region_t r = { name, rindex, @@ -563,6 +571,7 @@ PTFFormat::parserest5(void) { (int64_t)(sampleoffset*ratefactor), (int64_t)(length*ratefactor), f, + m, }; regions.push_back(r); vector<track_t>::iterator ti; @@ -689,6 +698,106 @@ PTFFormat::parseaudio5(void) { resort(audiofiles); } +bool +PTFFormat::parsemidi(void) { + uint64_t i, k, n_midi_events, sample_time_zero; + uint64_t midi_pos, midi_len, max_pos = 0, min_pos = 0xffffffffffffffff; + uint8_t midi_velocity, midi_note; + uint16_t rsize; + std::vector<midi_ev_t> midi; + midi_ev_t m; + bool found = false; + + // Find MdNLB + k = 0; + while (k < len) { + if ( (ptfunxored[k ] == 'M') && + (ptfunxored[k+1] == 'd') && + (ptfunxored[k+2] == 'N') && + (ptfunxored[k+3] == 'L') && + (ptfunxored[k+4] == 'B')) { + found = true; + break; + } + k++; + } + + if (!found) { + return false; + } + + k += 11; + n_midi_events = ptfunxored[k] | ptfunxored[k+1] << 8 | + ptfunxored[k+2] << 16 | ptfunxored[k+3] << 24; + + k += 4; + sample_time_zero = 0xe8d4a51000; + for (i = 0; i < n_midi_events; i++, k += 35) { + midi_pos = (uint64_t)ptfunxored[k] | + (uint64_t)ptfunxored[k+1] << 8 | + (uint64_t)ptfunxored[k+2] << 16 | + (uint64_t)ptfunxored[k+3] << 24 | + (uint64_t)ptfunxored[k+4] << 32; + midi_pos -= sample_time_zero; + midi_pos /= 40; + midi_note = ptfunxored[k+8]; + midi_len = (uint64_t)ptfunxored[k+9] | + (uint64_t)ptfunxored[k+10] << 8 | + (uint64_t)ptfunxored[k+11] << 16 | + (uint64_t)ptfunxored[k+12] << 24 | + (uint64_t)ptfunxored[k+13] << 32; + midi_len /= 40; + midi_velocity = ptfunxored[k+17]; + + if (midi_pos + midi_len > max_pos) { + max_pos = midi_pos + midi_len; + } + if (midi_pos < min_pos) { + min_pos = midi_pos; + } + + m.pos = midi_pos; + m.length = midi_len; + m.note = midi_note; + m.velocity = midi_velocity; + midi.push_back(m); + + //fprintf(stderr, "MIDI: Note=%d Vel=%d Start=%d(samples) Len=%d(samples)\n", midi_note, midi_velocity, midi_pos, midi_len); + } + + rsize = (uint16_t)regions.size(); + wav_t w = { std::string(""), 0, 0, 0 }; + region_t r = { + "MIDI", + rsize, + (int64_t)(min_pos*ratefactor), + (int64_t)(0), + (int64_t)(max_pos*ratefactor), + w, + midi, + }; + regions.push_back(r); + + uint16_t trmax = 0; + for (vector<track_t>::iterator + a = tracks.begin(); + a != tracks.end(); ++a) { + if (a->index + 1 > trmax) { + trmax = a->index + 1; + } + } + + track_t tr = { + "MIDI", + trmax, + 0, + r + }; + tracks.push_back(tr); + + return true; +} + void PTFFormat::parseaudio(void) { uint64_t i,j,k,l; @@ -900,13 +1009,15 @@ PTFFormat::parserest89(void) { if ((found = std::find(begin, finish, f)) != finish) { audiofiles.push_back(f); // Also add plain wav as region + std::vector<midi_ev_t> m; region_t r = { name, rindex, (int64_t)(start*ratefactor), (int64_t)(sampleoffset*ratefactor), (int64_t)(length*ratefactor), - f + f, + m }; regions.push_back(r); // Region only @@ -914,13 +1025,15 @@ PTFFormat::parserest89(void) { if (foundin(filename, string(".grp"))) { continue; } + std::vector<midi_ev_t> m; region_t r = { name, rindex, (int64_t)(start*ratefactor), (int64_t)(sampleoffset*ratefactor), (int64_t)(length*ratefactor), - f + f, + m }; regions.push_back(r); } @@ -1174,13 +1287,15 @@ PTFFormat::parserest10(void) { if ((found = std::find(begin, finish, f)) != finish) { audiofiles.push_back(f); // Also add plain wav as region + std::vector<midi_ev_t> m; region_t r = { name, rindex, (int64_t)(start*ratefactor), (int64_t)(sampleoffset*ratefactor), (int64_t)(length*ratefactor), - f + f, + m }; regions.push_back(r); // Region only @@ -1188,13 +1303,15 @@ PTFFormat::parserest10(void) { if (foundin(filename, string(".grp"))) { continue; } + std::vector<midi_ev_t> m; region_t r = { name, rindex, (int64_t)(start*ratefactor), (int64_t)(sampleoffset*ratefactor), (int64_t)(length*ratefactor), - f + f, + m }; regions.push_back(r); } diff --git a/ptfformat.h b/ptfformat.h index e6c121d..17977c8 100644 --- a/ptfformat.h +++ b/ptfformat.h @@ -51,6 +51,13 @@ public: }; + struct midi_ev_t { + uint64_t pos; + uint64_t length; + uint8_t note; + uint8_t velocity; + }; + typedef struct region { std::string name; uint16_t index; @@ -58,6 +65,7 @@ public: int64_t sampleoffset; int64_t length; wav_t wave; + std::vector<midi_ev_t> midi; bool operator ==(const struct region& other) { return (this->index == other.index); @@ -85,7 +93,8 @@ public: std::vector<region_t>::iterator found; wav_t w = { std::string(""), 0, 0, 0 }; - region_t r = { std::string(""), index, 0, 0, 0, w }; + std::vector<midi_ev_t> m; + region_t r = { std::string(""), index, 0, 0, 0, w, m}; if ((found = std::find(begin, finish, r)) != finish) { return true; @@ -133,6 +142,7 @@ private: void parserest10(void); void parseaudio5(void); void parseaudio(void); + bool parsemidi(void); void resort(std::vector<wav_t>& ws); std::vector<wav_t> actualwavs; float ratefactor; @@ -38,29 +38,35 @@ int main (int argc, char **argv) { break; case 0: printf("ProTools %d Session: Samplerate = %ldHz\nTarget samplerate = 48000\n\n", ptf.version, ptf.sessionrate); - if (ptf.audiofiles.size() > 0) { - printf("%lu wavs, %lu regions, %lu active regions\n\n", - ptf.audiofiles.size(), - ptf.regions.size(), - ptf.tracks.size() - ); - printf("Audio file (WAV#) @ offset, length:\n"); - for (vector<PTFFormat::wav_t>::iterator - a = ptf.audiofiles.begin(); - a != ptf.audiofiles.end(); ++a) { - //printf("%s @ %lu, %lu\n", a->filename.c_str(), - printf("`%s` w(%d) @ %lu, %lu\n", - a->filename.c_str(), - a->index, - a->posabsolute, - a->length); - } - - printf("\nRegion (Region#) (WAV#) @ into-sample, length:\n"); - for (vector<PTFFormat::region_t>::iterator - a = ptf.regions.begin(); - a != ptf.regions.end(); ++a) { - //printf("%s (%s) @ %lu + %lu, %lu\n", a->name.c_str(), + printf("%lu wavs, %lu regions, %lu active regions\n\n", + ptf.audiofiles.size(), + ptf.regions.size(), + ptf.tracks.size() + ); + printf("Audio file (WAV#) @ offset, length:\n"); + for (vector<PTFFormat::wav_t>::iterator + a = ptf.audiofiles.begin(); + a != ptf.audiofiles.end(); ++a) { + printf("`%s` w(%d) @ %lu, %lu\n", + a->filename.c_str(), + a->index, + a->posabsolute, + a->length); + } + + printf("\nRegion (Region#) (WAV#) @ into-sample, length:\n"); + for (vector<PTFFormat::region_t>::iterator + a = ptf.regions.begin(); + a != ptf.regions.end(); ++a) { + if (!strcmp(a->name.c_str(), "MIDI")) { + for (vector<PTFFormat::midi_ev_t>::iterator + b = a->midi.begin(); + b != a->midi.end(); ++b) { + printf(" MIDI: n(%d) v(%d) @ %lu, %lu\n", + b->note, b->velocity, + b->pos, b->length); + } + } else { printf("`%s` r(%d) w(%d) @ %lu, %lu\n", a->name.c_str(), a->index, @@ -68,36 +74,31 @@ int main (int argc, char **argv) { a->sampleoffset, a->length); } + } - printf("\nTrack name (Track#) (Region#) @ Absolute:\n"); - for (vector<PTFFormat::track_t>::iterator - a = ptf.tracks.begin(); - a != ptf.tracks.end(); ++a) { - //printf("%s (%s) @ %lu + %lu, %lu\n", a->name.c_str(), - printf("`%s` t(%d) r(%d) @ %lu\n", - a->name.c_str(), - a->index, - a->reg.index, - a->reg.startpos); - } - - printf("\nTrack name (Track#) (WAV filename) @ Absolute + Into-sample, Length:\n"); - for (vector<PTFFormat::track_t>::iterator - a = ptf.tracks.begin(); - a != ptf.tracks.end(); ++a) { - //printf("%s (%s) @ %lu + %lu, %lu\n", a->name.c_str(), - printf("`%s` t(%d) (%s) @ %lu + %lu, %lu\n", - a->name.c_str(), - a->index, - a->reg.wave.filename.c_str(), - a->reg.startpos, - a->reg.sampleoffset, - a->reg.length - ); - } + printf("\nTrack name (Track#) (Region#) @ Absolute:\n"); + for (vector<PTFFormat::track_t>::iterator + a = ptf.tracks.begin(); + a != ptf.tracks.end(); ++a) { + printf("`%s` t(%d) r(%d) @ %lu\n", + a->name.c_str(), + a->index, + a->reg.index, + a->reg.startpos); + } - } else { - printf("No audio files in session, quit\n"); + printf("\nTrack name (Track#) (WAV filename) @ Absolute + Into-sample, Length:\n"); + for (vector<PTFFormat::track_t>::iterator + a = ptf.tracks.begin(); + a != ptf.tracks.end(); ++a) { + printf("`%s` t(%d) (%s) @ %lu + %lu, %lu\n", + a->name.c_str(), + a->index, + a->reg.wave.filename.c_str(), + a->reg.startpos, + a->reg.sampleoffset, + a->reg.length + ); } break; } |