improved build process
This commit is contained in:
parent
dff58483e6
commit
3bf8d3b91b
|
@ -1,3 +1,4 @@
|
||||||
|
|
||||||
/midi-parser
|
/midi-parser
|
||||||
|
/build
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.30)
|
||||||
|
|
||||||
|
project(midi-parser)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 26)
|
||||||
|
set(CMAKE_CXX_FLAGS "-g")
|
||||||
|
|
||||||
|
set(SRCS
|
||||||
|
src/main.cpp
|
||||||
|
src/device.cpp
|
||||||
|
src/key.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_subdirectory(midifile)
|
||||||
|
add_executable(midi-parser ${SRCS})
|
||||||
|
|
||||||
|
target_link_libraries(midi-parser PRIVATE midifile PUBLIC stdc++)
|
||||||
|
|
6
build.sh
6
build.sh
|
@ -1,6 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
cd midifile && cmake . && make && cd ..
|
|
||||||
|
|
||||||
g++ src/main.cpp ./midifile/libmidifile.a -o midi-parser -g -O3
|
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
|
||||||
|
#include "device.hpp"
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
Device::Device(const char* path) {
|
||||||
|
fd = ::open(path, O_RDWR);
|
||||||
|
}
|
||||||
|
|
||||||
|
Device::~Device() {
|
||||||
|
::close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
Device::operator int() {
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Device::print(const char* data) {
|
||||||
|
for(size_t i = 0; data[i] != '\0'; i++) {
|
||||||
|
::write(fd, &data[i], 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Device::write(const char* data, size_t len) {
|
||||||
|
::write(fd, data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Device::read(char* data, size_t len) {
|
||||||
|
::read(fd, data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Device::read_until(char target) {
|
||||||
|
char ch;
|
||||||
|
read(&ch, 1);
|
||||||
|
while(ch != target) {
|
||||||
|
read(&ch, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
struct Device {
|
||||||
|
Device(const char* path);
|
||||||
|
~Device();
|
||||||
|
operator int();
|
||||||
|
void print(const char* data);
|
||||||
|
void write(const char* data, size_t len);
|
||||||
|
void read(char* data, size_t len);
|
||||||
|
void read_until(char target = '\n');
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
void printf(const char* format, Args... args) {
|
||||||
|
char buff[1024];
|
||||||
|
size_t len = std::snprintf(buff, sizeof(buff), format, args...);
|
||||||
|
write(buff, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int fd;
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
|
||||||
|
#include "key.hpp"
|
||||||
|
#include <cmath>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
|
const double KEYS[] = {16.35, 17.32, 18.35, 19.45, 20.6, 21.83, 23.12, 24.5, 25.96, 27.5, 29.14, 30.87};
|
||||||
|
|
||||||
|
int key::get_freq(int key) {
|
||||||
|
int octave = key / std::size(KEYS);
|
||||||
|
return (int)std::round(KEYS[key % std::size(KEYS)] * std::pow(2, octave));
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace key {
|
||||||
|
|
||||||
|
int get_freq(int key);
|
||||||
|
};
|
||||||
|
|
62
src/main.cpp
62
src/main.cpp
|
@ -3,34 +3,14 @@
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <fstream>
|
|
||||||
#include <iterator>
|
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <thread>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <chrono>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <fcntl.h>
|
#include "device.hpp"
|
||||||
#include <termios.h>
|
#include "key.hpp"
|
||||||
|
|
||||||
const double KEYS[] = {16.35, 17.32, 18.35, 19.45, 20.6, 21.83, 23.12, 24.5, 25.96, 27.5, 29.14, 30.87};
|
|
||||||
|
|
||||||
double get_key_freq(int key) {
|
|
||||||
int octave = key / std::size(KEYS);
|
|
||||||
return KEYS[key % std::size(KEYS)] * std::pow(2, octave);
|
|
||||||
}
|
|
||||||
|
|
||||||
volatile std::sig_atomic_t running = true;
|
|
||||||
|
|
||||||
void signal_handler(int id) {
|
|
||||||
std::cout << "Quitting\n";
|
|
||||||
running = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
|
|
||||||
std::signal(SIGINT, signal_handler);
|
|
||||||
|
|
||||||
smf::MidiFile midifile;
|
smf::MidiFile midifile;
|
||||||
midifile.read(argv[2]);
|
midifile.read(argv[2]);
|
||||||
|
|
||||||
|
@ -54,16 +34,14 @@ int main(int argc, char** argv) {
|
||||||
midifile.doTimeAnalysis();
|
midifile.doTimeAnalysis();
|
||||||
midifile.joinTracks();
|
midifile.joinTracks();
|
||||||
|
|
||||||
std::ofstream device {argv[1], std::ios::binary};
|
Device device(argv[1]);
|
||||||
device << ":c,";
|
|
||||||
device.flush();
|
|
||||||
|
|
||||||
auto& track = midifile[0];
|
auto& track = midifile[0];
|
||||||
int current_pressed_keys = 0;
|
int current_pressed_keys = 0;
|
||||||
int max_pressed_keys = 0;
|
int max_pressed_keys = 0;
|
||||||
double time_end = 0;
|
double time_end = 0;
|
||||||
|
|
||||||
for(int i = 0; i < track.size() && running; i++) {
|
for(int i = 0; i < track.size(); i++) {
|
||||||
smf::MidiEvent& event = track[i];
|
smf::MidiEvent& event = track[i];
|
||||||
|
|
||||||
if(!event.isNote()) {
|
if(!event.isNote()) {
|
||||||
|
@ -89,11 +67,15 @@ int main(int argc, char** argv) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double amplitude = 1.0 / max_pressed_keys;
|
int tones_total = 0;
|
||||||
|
double amplitude = std::max(1.0 / max_pressed_keys, 1.0/16.0);
|
||||||
std::vector<int> channel_key_nums(max_pressed_keys, -1);
|
std::vector<int> channel_key_nums(max_pressed_keys, -1);
|
||||||
auto now = std::chrono::high_resolution_clock::now();
|
|
||||||
|
|
||||||
for(int i = 0; i < track.size() && running; i++) {
|
std::cout << "Seconds per tick: " << midifile.getTimeInSeconds(1) << std::endl;
|
||||||
|
|
||||||
|
device.printf(":w,o,%f,%d,", amplitude, (int)(midifile.getTimeInSeconds(1) * 1000000));
|
||||||
|
|
||||||
|
for(int i = 0; i < track.size(); i++) {
|
||||||
smf::MidiEvent& event = track[i];
|
smf::MidiEvent& event = track[i];
|
||||||
|
|
||||||
if(!event.isNote()) {
|
if(!event.isNote()) {
|
||||||
|
@ -134,18 +116,14 @@ int main(int argc, char** argv) {
|
||||||
}
|
}
|
||||||
end:
|
end:
|
||||||
|
|
||||||
double key_freq = get_key_freq(key);
|
int key_freq = key::get_freq(key);
|
||||||
|
|
||||||
std::this_thread::sleep_until(now + std::chrono::duration<double>(event.seconds));
|
|
||||||
device << ":s," << channel << "," << key_freq << ',';
|
|
||||||
|
|
||||||
|
device.read_until();
|
||||||
if(event.isNoteOn()) {
|
if(event.isNoteOn()) {
|
||||||
device << std::max(amplitude, 1.0/16.0);
|
device.printf("s,%d,%d,%d,", event.tick, channel, key_freq);
|
||||||
} else {
|
} else {
|
||||||
device << '0';
|
device.printf("c,%d,%d,", event.tick, channel);
|
||||||
}
|
}
|
||||||
device << ',';
|
|
||||||
device.flush();
|
|
||||||
|
|
||||||
if(i < track.size() - 1 && event.seconds == track[i + 1].seconds) {
|
if(i < track.size() - 1 && event.seconds == track[i + 1].seconds) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -169,13 +147,15 @@ end:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << " + " << event.seconds << "s / " << time_end << "s" << std::endl;
|
std::cout << " + " << event.seconds << "s / " << time_end << 's' << std::endl;
|
||||||
|
tones_total++;
|
||||||
}
|
}
|
||||||
|
|
||||||
device << ":c,";
|
device.read_until();
|
||||||
device.flush();
|
device.printf(";,:p,");
|
||||||
|
|
||||||
|
std::cout << "Sent " << tones_total << " tones\n";
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue