diff --git a/src/binary.cpp b/src/binary.cpp index 374f0f5..4ca18bf 100644 --- a/src/binary.cpp +++ b/src/binary.cpp @@ -7,11 +7,13 @@ #include #include #include +#include unsigned binary::process(std::ostream& dst, const char* path) { smf::MidiFile midifile; midifile.read(path); midifile.doTimeAnalysis(); + std::vector track_modes(midifile.getNumTracks(), packet::ToneType::tt_sine); midifile.joinTracks(); Scheduler scheduler(midifile.getTimeInSeconds(1)); @@ -22,12 +24,35 @@ unsigned binary::process(std::ostream& dst, const char* path) { for(int i = 0; i < track.size(); i++) { smf::MidiEvent& note = track[i]; + if(note.isTrackName()) { + std::string name = note.getMetaContent(); + + for(int i = 0; i < name.length(); i++) { + char c = name[i]; + if(c >= 'A' && c <= 'Z') { + name[i] = c + 32; + } + } + + if(name.find("saw") != std::string::npos) { + track_modes[note.track] = packet::ToneType::tt_saw; + } + + else if(name.find("square") != std::string::npos || name.find("distortion") != std::string::npos || name.find("overdrive") != std::string::npos) { + track_modes[note.track] = packet::ToneType::tt_square; + } + + else if(name.find("triangle") != std::string::npos) { + track_modes[note.track] = packet::ToneType::tt_triangle; + } + } + if(!note.isNote()) { continue; } smf::MidiEvent& note_end = *note.getLinkedEvent(); - scheduler.add_note(note.getKeyNumber(), note.tick, note.isNoteOn()); + scheduler.add_note(note.getKeyNumber(), note.tick, note.isNoteOn(), track_modes[note.track]); notes_added++; } diff --git a/src/device.cpp b/src/device.cpp index 373a602..a1c3441 100644 --- a/src/device.cpp +++ b/src/device.cpp @@ -21,7 +21,20 @@ Device::Device(const char* path) { char buff[8]; read(buff, sizeof(buff)); - fingerprint_valid = (std::memcmp(buff, "\x19\xc1\x6c\x19\x5b\x6f\xd2\x44", sizeof(buff)) == 0); + + for(;;) { + fingerprint_valid = (std::memcmp(buff, "\x19\xc1\x6c\x19\x5b\x6f\xd2\x44", sizeof(buff)) == 0); + + if(fingerprint_valid) { + break; + } + + for(int i = 1; i < sizeof(buff); i++) { + buff[i - 1] = buff[i]; + } + + read(&buff[7], 1); + } } Device::~Device() { diff --git a/src/packet.cpp b/src/packet.cpp index 423c2e3..5656dfc 100644 --- a/src/packet.cpp +++ b/src/packet.cpp @@ -19,8 +19,8 @@ void packet::Clear::finalise(std::ostream& dst) const { void packet::ClearTS::finalise(std::ostream& dst) const { uint64_t v = Type::clear_ts & bm(3); v = (v << 5) | (index & bm(5)); - v = (v << 20) | (ticks & bm(20)); - v <<= 4; + v = (v << 18) | (ticks & bm(18)); + v <<= 6; output(dst, v, 4); } @@ -28,15 +28,17 @@ void packet::Set::finalise(std::ostream& dst) const { uint64_t v = Type::set & bm(3); v = (v << 5) | (index & bm(5)); v = (v << 12) | (frequency & bm(12)); - v <<= 4; + v = (v << 2) | (mode & bm(2)); + v <<= 2; output(dst, v, 3); } void packet::SetTS::finalise(std::ostream& dst) const { uint64_t v = Type::set_ts & bm(3); v = (v << 5) | (index & bm(5)); - v = (v << 20) | (ticks & bm(20)); + v = (v << 18) | (ticks & bm(18)); v = (v << 12) | (frequency & bm(12)); + v = (v << 2) | (mode & bm(2)); output(dst, v, 5); } @@ -49,14 +51,6 @@ void packet::Config::finalise(std::ostream& dst) const { output(dst, v, 8); } -void packet::Tempo::finalise(std::ostream& dst) const { - uint64_t v = Type::tempo & bm(3); - v = (v << 29) | (us_per_tick & bm(29)); - v = (v << 20) | (ticks & bm(20)); - v <<= 4; - output(dst, v, 7); -} - void packet::Stop::finalise(std::ostream& dst) const { dst.put(Type::stop << 5); } @@ -81,9 +75,6 @@ void packet::Generic::finalise(std::ostream& dst) const { case Type::stop: stop.finalise(dst); break; - case Type::tempo: - tempo.finalise(dst); - break; } } diff --git a/src/packet.hpp b/src/packet.hpp index eaf51dc..332c711 100644 --- a/src/packet.hpp +++ b/src/packet.hpp @@ -13,7 +13,13 @@ namespace packet { set_ts = 3, clear = 4, clear_ts = 5, - tempo = 6, + }; + + enum ToneType : unsigned { + tt_sine = 0, + tt_saw = 1, + tt_square = 2, + tt_triangle = 3, }; struct Stop { @@ -23,6 +29,7 @@ namespace packet { struct Set { unsigned index; unsigned frequency; + ToneType mode; void finalise(std::ostream& dst) const; }; @@ -31,6 +38,7 @@ namespace packet { unsigned index; unsigned ticks; unsigned frequency; + ToneType mode; void finalise(std::ostream& dst) const; }; @@ -56,13 +64,6 @@ namespace packet { void finalise(std::ostream& dst) const; }; - struct Tempo { - unsigned us_per_tick; - unsigned ticks; - - void finalise(std::ostream& dst) const; - }; - constexpr std::size_t get_size(Type type) { switch(type) { case Type::clear: @@ -75,8 +76,6 @@ namespace packet { return 5; case Type::stop: return 1; - case Type::tempo: - return 7; case Type::config: return 8; } @@ -92,7 +91,6 @@ namespace packet { Clear clear; ClearTS clear_ts; Config config; - Tempo tempo; }; void finalise(std::ostream& dst) const; constexpr std::size_t size() const { diff --git a/src/scheduler.cpp b/src/scheduler.cpp index 00a0ba7..f934803 100644 --- a/src/scheduler.cpp +++ b/src/scheduler.cpp @@ -7,10 +7,13 @@ #include #include -Scheduler::Scheduler(double s_per_tick) : us_per_tick(s_per_tick * 1e6) { +Scheduler::Scheduler(double s_per_tick) + : us_per_tick(s_per_tick * 1e6) { } -bool Scheduler::add_note(unsigned id, unsigned ticks, bool state) { +bool Scheduler::add_note(unsigned key_id, unsigned ticks, bool state, packet::ToneType mode) { + + unsigned id = key_id * (mode + 1); if(id >= keys.size()) { keys.resize(id + 1); @@ -52,9 +55,9 @@ bool Scheduler::add_note(unsigned id, unsigned ticks, bool state) { } if(ticks_at >= ticks) { - packets.push_back({.type=packet::Type::set, .set={.index=channel_id, .frequency=key::get_freq(id)}}); + packets.push_back({.type=packet::Type::set, .set={.index=channel_id, .frequency=key::get_freq(key_id), .mode=mode}}); } else { - packets.push_back({.type=packet::Type::set_ts, .set_ts={.index=channel_id, .ticks=ticks, .frequency=key::get_freq(id)}}); + packets.push_back({.type=packet::Type::set_ts, .set_ts={.index=channel_id, .ticks=ticks, .frequency=key::get_freq(key_id), .mode=mode}}); ticks_at = ticks; } @@ -69,11 +72,6 @@ bool Scheduler::add_note(unsigned id, unsigned ticks, bool state) { return true; } -void Scheduler::add_tempo_change(uint32_t tempo, unsigned ticks) { - packets.push_back({.type=packet::Type::tempo, .tempo={.us_per_tick=tempo, .ticks=ticks}}); - std::cerr << "Tempo change! " << tempo << " : " << ticks << std::endl; -} - void Scheduler::finalise(std::ostream& dst) const { unsigned amplitude = std::round(std::max(1.f / channels_in_use_max, 1.f/8.f) * 255); @@ -95,7 +93,7 @@ void Scheduler::display(std::ostream& os) const { os << " + "; for(int i = 0; i < keys.size(); i++) { - os << (keys[i].active ? '|' : ' '); +// os << (keys[i].active ? '|' : ' '); } os << " + "; diff --git a/src/scheduler.hpp b/src/scheduler.hpp index 915b9aa..49954f0 100644 --- a/src/scheduler.hpp +++ b/src/scheduler.hpp @@ -3,7 +3,6 @@ #include "packet.hpp" #include -#include #include #include @@ -21,8 +20,7 @@ struct Scheduler { Scheduler(double s_per_tick); - bool add_note(unsigned key, unsigned ticks, bool active); - void add_tempo_change(std::uint32_t tempo, unsigned ticks); + bool add_note(unsigned key, unsigned ticks, bool active, packet::ToneType mode); void finalise(std::ostream& os) const; void display(std::ostream& os) const;