split into multiple components; switched amplitude to integer math
This commit is contained in:
parent
251ea220e3
commit
9e606ae532
|
@ -7,15 +7,19 @@ set(CMAKE_CXX_STANDARD 26)
|
||||||
set(CMAKE_CXX_FLAGS "-g")
|
set(CMAKE_CXX_FLAGS "-g")
|
||||||
|
|
||||||
set(SRCS
|
set(SRCS
|
||||||
src/main.cpp
|
|
||||||
src/header.cpp
|
|
||||||
src/packet.cpp
|
src/packet.cpp
|
||||||
|
src/binary.cpp
|
||||||
src/scheduler.cpp
|
src/scheduler.cpp
|
||||||
src/key.cpp
|
src/key.cpp
|
||||||
|
src/device.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_subdirectory(midifile)
|
add_subdirectory(midifile)
|
||||||
add_executable(midi-parser ${SRCS})
|
add_executable(parser src/parser.cpp ${SRCS})
|
||||||
|
add_executable(streamer src/streamer.cpp ${SRCS})
|
||||||
|
add_executable(header src/header.cpp ${SRCS})
|
||||||
|
|
||||||
target_link_libraries(midi-parser PRIVATE midifile PUBLIC stdc++)
|
target_link_libraries(parser PRIVATE midifile PUBLIC stdc++)
|
||||||
|
target_link_libraries(streamer PRIVATE midifile PUBLIC stdc++)
|
||||||
|
target_link_libraries(header PRIVATE midifile PUBLIC stdc++)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
|
||||||
|
#include "binary.hpp"
|
||||||
|
#include "packet.hpp"
|
||||||
|
#include "scheduler.hpp"
|
||||||
|
#include "../midifile/include/MidiFile.h"
|
||||||
|
#include <ostream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
unsigned binary::process(std::ostream& dst, const char* path) {
|
||||||
|
smf::MidiFile midifile;
|
||||||
|
midifile.read(path);
|
||||||
|
midifile.doTimeAnalysis();
|
||||||
|
midifile.joinTracks();
|
||||||
|
|
||||||
|
Scheduler scheduler(midifile.getTimeInSeconds(1));
|
||||||
|
auto& track = midifile[0];
|
||||||
|
unsigned ticks_last = 0;
|
||||||
|
unsigned notes_added = 0;
|
||||||
|
|
||||||
|
for(int i = 0; i < track.size(); i++) {
|
||||||
|
smf::MidiEvent& note = track[i];
|
||||||
|
|
||||||
|
if(!note.isNote()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
smf::MidiEvent& note_end = *note.getLinkedEvent();
|
||||||
|
scheduler.add_note(note.getKeyNumber(), note.tick, note.isNoteOn());
|
||||||
|
notes_added++;
|
||||||
|
}
|
||||||
|
|
||||||
|
scheduler.finalise(dst);
|
||||||
|
return notes_added;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool binary::process_all(std::string& dst, int argc, char **argv) {
|
||||||
|
if(argc > 2) {
|
||||||
|
std::stringstream ss;
|
||||||
|
for(int i = 2; i < argc; i++) {
|
||||||
|
binary::process(ss, argv[i]);
|
||||||
|
}
|
||||||
|
binary::finalize(ss);
|
||||||
|
dst = std::move(ss.str());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if(argc == 2) {
|
||||||
|
dst = std::string(std::istreambuf_iterator<char>(std::cin), std::istreambuf_iterator<char>());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void binary::finalize(std::ostream &dst) {
|
||||||
|
packet::Generic(packet::Type::stop).finalise(dst);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace binary {
|
||||||
|
unsigned process(std::ostream& dst, const char* path);
|
||||||
|
bool process_all(std::string& dst, int argc, char** argv);
|
||||||
|
void finalize(std::ostream& dst);
|
||||||
|
}
|
||||||
|
|
|
@ -1,12 +1,21 @@
|
||||||
|
|
||||||
#include "device.hpp"
|
#include "device.hpp"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
Device::Device(const char* path) {
|
Device::Device(const char* path) {
|
||||||
fd = ::open(path, O_RDWR);
|
fd = ::open(path, O_RDWR);
|
||||||
|
|
||||||
|
struct termios tio;
|
||||||
|
tcgetattr(fd, &tio);
|
||||||
|
|
||||||
|
cfsetspeed(&tio, B57600);
|
||||||
|
cfmakeraw(&tio);
|
||||||
|
|
||||||
|
assert(tcsetattr(fd, TCSANOW, &tio) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Device::~Device() {
|
Device::~Device() {
|
||||||
|
@ -31,6 +40,16 @@ void Device::read(char* data, size_t len) {
|
||||||
::read(fd, data, len);
|
::read(fd, data, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Device::put(char ch) {
|
||||||
|
write(&ch, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
char Device::get() {
|
||||||
|
char ch;
|
||||||
|
read(&ch, 1);
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
|
||||||
void Device::read_until(char target) {
|
void Device::read_until(char target) {
|
||||||
char ch;
|
char ch;
|
||||||
read(&ch, 1);
|
read(&ch, 1);
|
||||||
|
|
|
@ -5,6 +5,16 @@
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
struct Device {
|
struct Device {
|
||||||
|
|
||||||
|
enum Mode {
|
||||||
|
e_none,
|
||||||
|
e_ready,
|
||||||
|
e_local,
|
||||||
|
e_serial,
|
||||||
|
e_read,
|
||||||
|
e_jump,
|
||||||
|
};
|
||||||
|
|
||||||
Device(const char* path);
|
Device(const char* path);
|
||||||
~Device();
|
~Device();
|
||||||
operator int();
|
operator int();
|
||||||
|
@ -12,6 +22,8 @@ struct Device {
|
||||||
void write(const char* data, size_t len);
|
void write(const char* data, size_t len);
|
||||||
void read(char* data, size_t len);
|
void read(char* data, size_t len);
|
||||||
void read_until(char target = '\n');
|
void read_until(char target = '\n');
|
||||||
|
void put(char ch);
|
||||||
|
char get();
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
void printf(const char* format, Args... args) {
|
void printf(const char* format, Args... args) {
|
||||||
|
|
|
@ -1,15 +1,17 @@
|
||||||
|
|
||||||
#include "header.hpp"
|
#include "binary.hpp"
|
||||||
#include <ios>
|
#include <ios>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
const int COLS = 32;
|
const int COLS = 32;
|
||||||
|
|
||||||
void header::generate(std::ostream& dst, const std::vector<char>& src, const char* var_name) {
|
static void generate(std::ostream& dst, const std::string& src, const char* var_name) {
|
||||||
|
|
||||||
dst << "#include <avr/pgmspace.h>\n";
|
dst << "#include <avr/pgmspace.h>\n";
|
||||||
dst << "inline const PROGMEM unsigned char " << var_name << "[] = {\n";
|
dst << "inline const PROGMEM unsigned char " << var_name << "[] = {\n";
|
||||||
|
|
||||||
for(int i = 0; i < src.size(); i += COLS) {
|
for(int i = 0; i < src.length(); i += COLS) {
|
||||||
|
|
||||||
dst << '\t';
|
dst << '\t';
|
||||||
|
|
||||||
|
@ -23,3 +25,15 @@ void header::generate(std::ostream& dst, const std::vector<char>& src, const cha
|
||||||
dst << "};\n" << std::dec;
|
dst << "};\n" << std::dec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
|
||||||
|
std::string data;
|
||||||
|
|
||||||
|
if(!binary::process_all(data, argc, argv)) {
|
||||||
|
std::cerr << "Usage: " << argv[0] << " varname [midifile ...]?\n\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
generate(std::cout, data, argv[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <ostream>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace header {
|
|
||||||
|
|
||||||
void generate(std::ostream& dst, const std::vector<char>& src, const char* var_name);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
59
src/main.cpp
59
src/main.cpp
|
@ -1,59 +0,0 @@
|
||||||
|
|
||||||
#include "../midifile/include/MidiFile.h"
|
|
||||||
#include <cmath>
|
|
||||||
#include <csignal>
|
|
||||||
#include <cstring>
|
|
||||||
#include <fstream>
|
|
||||||
#include <ostream>
|
|
||||||
#include <iostream>
|
|
||||||
#include <vector>
|
|
||||||
#include "header.hpp"
|
|
||||||
#include "scheduler.hpp"
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
|
||||||
|
|
||||||
smf::MidiFile midifile;
|
|
||||||
midifile.read(argv[2]);
|
|
||||||
|
|
||||||
midifile.doTimeAnalysis();
|
|
||||||
midifile.joinTracks();
|
|
||||||
|
|
||||||
Scheduler scheduler(midifile.getTimeInSeconds(1));
|
|
||||||
auto& track = midifile[0];
|
|
||||||
unsigned ticks_last = 0;
|
|
||||||
unsigned notes_added = 0;
|
|
||||||
|
|
||||||
std::cout << "Seconds per tick: " << midifile.getTimeInSeconds(1) << std::endl;
|
|
||||||
|
|
||||||
for(int i = 0; i < track.size(); i++) {
|
|
||||||
smf::MidiEvent& note = track[i];
|
|
||||||
|
|
||||||
if(!note.isNote()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(note.tick > ticks_last) {
|
|
||||||
scheduler.display(std::cout);
|
|
||||||
}
|
|
||||||
|
|
||||||
smf::MidiEvent& note_end = *note.getLinkedEvent();
|
|
||||||
if(!scheduler.add_note(note.getKeyNumber(), note.tick, note.isNoteOn())) {
|
|
||||||
// std::cout << "Warning (" << i << "): Failed\n";
|
|
||||||
}
|
|
||||||
notes_added++;
|
|
||||||
}
|
|
||||||
|
|
||||||
scheduler.display(std::cout);
|
|
||||||
|
|
||||||
std::vector<char> bytes;
|
|
||||||
scheduler.finalise(bytes);
|
|
||||||
|
|
||||||
std::cout << "Added " << notes_added << " notes\n";
|
|
||||||
std::cout << "Generated " << bytes.size() << " bytes\n";
|
|
||||||
|
|
||||||
std::ofstream device(argv[1]);
|
|
||||||
header::generate(device, bytes, "MIDI");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,23 +1,22 @@
|
||||||
|
|
||||||
#include "packet.hpp"
|
#include "packet.hpp"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
constexpr auto bm(auto n) {
|
constexpr auto bm(auto n) {
|
||||||
return (1L << n) - 1;
|
return (1L << n) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void output(std::vector<char>& dst, uint64_t v, int size) {
|
static void output(std::ostream& dst, uint64_t v, int size) {
|
||||||
for(int i = size * 8 - 8; i >= 0; i -= 8) {
|
for(int i = size * 8 - 8; i >= 0; i -= 8) {
|
||||||
dst.push_back(v >> i);
|
dst.put(v >> i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void packet::Clear::finalise(std::vector<char>& dst) const {
|
void packet::Clear::finalise(std::ostream& dst) const {
|
||||||
dst.push_back((Type::clear << 5) | (index & bm(5)));
|
dst.put((Type::clear << 5) | (index & bm(5)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void packet::ClearTS::finalise(std::vector<char>& dst) const {
|
void packet::ClearTS::finalise(std::ostream& dst) const {
|
||||||
uint64_t v = Type::clear_ts & bm(3);
|
uint64_t v = Type::clear_ts & bm(3);
|
||||||
v = (v << 5) | (index & bm(5));
|
v = (v << 5) | (index & bm(5));
|
||||||
v = (v << 20) | (ticks & bm(20));
|
v = (v << 20) | (ticks & bm(20));
|
||||||
|
@ -25,7 +24,7 @@ void packet::ClearTS::finalise(std::vector<char>& dst) const {
|
||||||
output(dst, v, 4);
|
output(dst, v, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void packet::Set::finalise(std::vector<char>& dst) const {
|
void packet::Set::finalise(std::ostream& dst) const {
|
||||||
uint64_t v = Type::set & bm(3);
|
uint64_t v = Type::set & bm(3);
|
||||||
v = (v << 5) | (index & bm(5));
|
v = (v << 5) | (index & bm(5));
|
||||||
v = (v << 12) | (frequency & bm(12));
|
v = (v << 12) | (frequency & bm(12));
|
||||||
|
@ -33,7 +32,7 @@ void packet::Set::finalise(std::vector<char>& dst) const {
|
||||||
output(dst, v, 3);
|
output(dst, v, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void packet::SetTS::finalise(std::vector<char>& dst) const {
|
void packet::SetTS::finalise(std::ostream& dst) const {
|
||||||
uint64_t v = Type::set_ts & bm(3);
|
uint64_t v = Type::set_ts & bm(3);
|
||||||
v = (v << 5) | (index & bm(5));
|
v = (v << 5) | (index & bm(5));
|
||||||
v = (v << 20) | (ticks & bm(20));
|
v = (v << 20) | (ticks & bm(20));
|
||||||
|
@ -41,22 +40,19 @@ void packet::SetTS::finalise(std::vector<char>& dst) const {
|
||||||
output(dst, v, 5);
|
output(dst, v, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
void packet::Config::finalise(std::vector<char>& dst) const {
|
void packet::Config::finalise(std::ostream& dst) const {
|
||||||
uint64_t v = Type::config & bm(3);
|
uint64_t v = Type::config & bm(3);
|
||||||
uint8_t* a_data = (uint8_t*)&litude;
|
uint8_t* a_data = (uint8_t*)&litude;
|
||||||
v = (v << 29) | (us_per_tick & bm(29));
|
v = (v << 29) | (us_per_tick & bm(29));
|
||||||
output(dst, v, 4);
|
v = (v << 8) | (amplitude & bm(8));
|
||||||
|
output(dst, v, 5);
|
||||||
for(int i = 0; i < 4; i++) {
|
|
||||||
dst.push_back(a_data[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void packet::Stop::finalise(std::vector<char>& dst) const {
|
void packet::Stop::finalise(std::ostream& dst) const {
|
||||||
dst.push_back(Type::stop << 5);
|
dst.put(Type::stop << 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
void packet::Generic::finalise(std::vector<char>& dst) const {
|
void packet::Generic::finalise(std::ostream& dst) const {
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case Type::clear:
|
case Type::clear:
|
||||||
clear.finalise(dst);
|
clear.finalise(dst);
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <vector>
|
#include <ostream>
|
||||||
|
|
||||||
namespace packet {
|
namespace packet {
|
||||||
|
|
||||||
|
@ -16,14 +16,14 @@ namespace packet {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Stop {
|
struct Stop {
|
||||||
void finalise(std::vector<char>& dst) const;
|
void finalise(std::ostream& dst) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Set {
|
struct Set {
|
||||||
unsigned index;
|
unsigned index;
|
||||||
unsigned frequency;
|
unsigned frequency;
|
||||||
|
|
||||||
void finalise(std::vector<char>& dst) const;
|
void finalise(std::ostream& dst) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SetTS {
|
struct SetTS {
|
||||||
|
@ -31,27 +31,27 @@ namespace packet {
|
||||||
unsigned ticks;
|
unsigned ticks;
|
||||||
unsigned frequency;
|
unsigned frequency;
|
||||||
|
|
||||||
void finalise(std::vector<char>& dst) const;
|
void finalise(std::ostream& dst) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Clear {
|
struct Clear {
|
||||||
unsigned index;
|
unsigned index;
|
||||||
|
|
||||||
void finalise(std::vector<char>& dst) const;
|
void finalise(std::ostream& dst) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ClearTS {
|
struct ClearTS {
|
||||||
unsigned index;
|
unsigned index;
|
||||||
unsigned ticks;
|
unsigned ticks;
|
||||||
|
|
||||||
void finalise(std::vector<char>& dst) const;
|
void finalise(std::ostream& dst) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Config {
|
struct Config {
|
||||||
unsigned us_per_tick;
|
unsigned us_per_tick;
|
||||||
float amplitude;
|
unsigned amplitude;
|
||||||
|
|
||||||
void finalise(std::vector<char>& dst) const;
|
void finalise(std::ostream& dst) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr std::size_t get_size(Type type) {
|
constexpr std::size_t get_size(Type type) {
|
||||||
|
@ -67,7 +67,7 @@ namespace packet {
|
||||||
case Type::stop:
|
case Type::stop:
|
||||||
return 1;
|
return 1;
|
||||||
case Type::config:
|
case Type::config:
|
||||||
return 8;
|
return 5;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ namespace packet {
|
||||||
ClearTS clear_ts;
|
ClearTS clear_ts;
|
||||||
Config config;
|
Config config;
|
||||||
};
|
};
|
||||||
void finalise(std::vector<char>& dst) const;
|
void finalise(std::ostream& dst) const;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <csignal>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
#include "binary.hpp"
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
|
||||||
|
if(argc == 1) {
|
||||||
|
std::cerr << "Usage: " << argv[0] << " midifile ...\n\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 1; i < argc; i++) {
|
||||||
|
binary::process(std::cout, argv[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
binary::finalize(std::cout);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -3,12 +3,12 @@
|
||||||
#include "key.hpp"
|
#include "key.hpp"
|
||||||
#include "packet.hpp"
|
#include "packet.hpp"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
|
||||||
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) {
|
||||||
std::cout << "us_per_tick = " << us_per_tick << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Scheduler::add_note(unsigned id, unsigned ticks, bool state) {
|
bool Scheduler::add_note(unsigned id, unsigned ticks, bool state) {
|
||||||
|
@ -69,19 +69,18 @@ bool Scheduler::add_note(unsigned id, unsigned ticks, bool state) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scheduler::finalise(std::vector<char>& dst) const {
|
void Scheduler::finalise(std::ostream& dst) const {
|
||||||
|
|
||||||
float amplitude = std::max(1.f / channels_in_use_max, 1.f/8.f);
|
unsigned amplitude = std::round(std::max(1.f / channels_in_use_max, 1.f/8.f) * 255);
|
||||||
packet::Generic packet_start {.type=packet::Type::config, .config={.us_per_tick=us_per_tick, .amplitude=amplitude}};
|
packet::Generic packet_start {.type=packet::Type::config, .config={.us_per_tick=us_per_tick, .amplitude=amplitude}};
|
||||||
packet::Generic packet_end {.type=packet::Type::stop, .stop={}};
|
|
||||||
|
std::cerr << "amplitude = " << amplitude << std::endl;
|
||||||
|
|
||||||
packet_start.finalise(dst);
|
packet_start.finalise(dst);
|
||||||
|
|
||||||
for(const packet::Generic& packet : packets) {
|
for(const packet::Generic& packet : packets) {
|
||||||
packet.finalise(dst);
|
packet.finalise(dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
packet_end.finalise(dst);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scheduler::display(std::ostream& os) const {
|
void Scheduler::display(std::ostream& os) const {
|
||||||
|
@ -89,13 +88,13 @@ void Scheduler::display(std::ostream& os) const {
|
||||||
os << " + ";
|
os << " + ";
|
||||||
|
|
||||||
for(int i = 0; i < keys.size(); i++) {
|
for(int i = 0; i < keys.size(); i++) {
|
||||||
std::cout << (keys[i].active ? '|' : ' ');
|
os << (keys[i].active ? '|' : ' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
os << " + ";
|
os << " + ";
|
||||||
|
|
||||||
for(int i = 0; i < channels.size(); i++) {
|
for(int i = 0; i < channels.size(); i++) {
|
||||||
std::cout << (channels[i].active ? '.' : ' ');
|
os << (channels[i].active ? '.' : ' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
os << " + \n";
|
os << " + \n";
|
||||||
|
|
|
@ -21,7 +21,7 @@ struct Scheduler {
|
||||||
Scheduler(double s_per_tick);
|
Scheduler(double s_per_tick);
|
||||||
|
|
||||||
bool add_note(unsigned key, unsigned ticks, bool active);
|
bool add_note(unsigned key, unsigned ticks, bool active);
|
||||||
void finalise(std::vector<char>& dst) const;
|
void finalise(std::ostream& os) const;
|
||||||
void display(std::ostream& os) const;
|
void display(std::ostream& os) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
|
||||||
|
#include "binary.hpp"
|
||||||
|
#include "device.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <ostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
std::string data;
|
||||||
|
|
||||||
|
if(!binary::process_all(data, argc, argv)) {
|
||||||
|
std::cerr << "Usage: " << argv[0] << " device [midifile ...]?\n\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned at = 0;
|
||||||
|
Device device(argv[1]);
|
||||||
|
device.put(Device::Mode::e_serial);
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
Device::Mode mode = (Device::Mode)device.get();
|
||||||
|
switch(mode) {
|
||||||
|
default: {
|
||||||
|
std::cout << "device: unknown (" << mode << ")" << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Device::Mode::e_ready: {
|
||||||
|
device.put(Device::Mode::e_serial);
|
||||||
|
std::cout << "device: ready" << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Device::Mode::e_jump: {
|
||||||
|
at = (device.get() & 0xff);
|
||||||
|
at = (at << 8) | (device.get() & 0xff);
|
||||||
|
at = (at << 8) | (device.get() & 0xff);
|
||||||
|
at = (at << 8) | (device.get() & 0xff);
|
||||||
|
std::cout << "device: jump (" << at << ")" << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Device::Mode::e_read: {
|
||||||
|
unsigned len = (device.get() & 0xff);
|
||||||
|
if(len + at > data.length()) {
|
||||||
|
unsigned l = data.length() - at;
|
||||||
|
device.write(data.c_str() + at, l);
|
||||||
|
for(int i = 0; i < len - l; i++) {
|
||||||
|
device.put(0);
|
||||||
|
}
|
||||||
|
at += l;
|
||||||
|
} else {
|
||||||
|
device.write(data.c_str() + at, len);
|
||||||
|
at += len;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue