improved build process

This commit is contained in:
Jay Robson 2024-08-24 00:34:26 +10:00
parent dff58483e6
commit 3bf8d3b91b
8 changed files with 128 additions and 47 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
/midi-parser
/build

19
CMakeLists.txt Normal file
View File

@ -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++)

View File

@ -1,6 +0,0 @@
#!/bin/sh
cd midifile && cmake . && make && cd ..
g++ src/main.cpp ./midifile/libmidifile.a -o midi-parser -g -O3

41
src/device.cpp Normal file
View File

@ -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);
}
}

26
src/device.hpp Normal file
View File

@ -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;
};

12
src/key.cpp Normal file
View File

@ -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));
}

8
src/key.hpp Normal file
View File

@ -0,0 +1,8 @@
#pragma once
namespace key {
int get_freq(int key);
};

View File

@ -3,34 +3,14 @@
#include <cmath>
#include <csignal>
#include <cstring>
#include <fstream>
#include <iterator>
#include <ostream>
#include <thread>
#include <iostream>
#include <chrono>
#include <vector>
#include <fcntl.h>
#include <termios.h>
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;
}
#include "device.hpp"
#include "key.hpp"
int main(int argc, char** argv) {
std::signal(SIGINT, signal_handler);
smf::MidiFile midifile;
midifile.read(argv[2]);
@ -54,16 +34,14 @@ int main(int argc, char** argv) {
midifile.doTimeAnalysis();
midifile.joinTracks();
std::ofstream device {argv[1], std::ios::binary};
device << ":c,";
device.flush();
Device device(argv[1]);
auto& track = midifile[0];
int current_pressed_keys = 0;
int max_pressed_keys = 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];
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);
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];
if(!event.isNote()) {
@ -134,18 +116,14 @@ int main(int argc, char** argv) {
}
end:
double key_freq = get_key_freq(key);
std::this_thread::sleep_until(now + std::chrono::duration<double>(event.seconds));
device << ":s," << channel << "," << key_freq << ',';
int key_freq = key::get_freq(key);
device.read_until();
if(event.isNoteOn()) {
device << std::max(amplitude, 1.0/16.0);
device.printf("s,%d,%d,%d,", event.tick, channel, key_freq);
} 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) {
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.flush();
device.read_until();
device.printf(";,:p,");
std::cout << "Sent " << tones_total << " tones\n";
return 0;
}