saturn-examples/midi/iterator.cpp
Zack Buhman 86d12c37ed midi: add generator
This adds both a midi generator and a midi type 1 simulator.

While I would have preferred to use an existing tool for this, I found
that timidity++ does not emit pitch wheel events correctly, and I
don't know of another widely-distributed tool that does midi-to-midi
format conversion.

The c++ and python versions were co-developed. I wrote one to test the
other. There is more cleanup to do, but `roundtrip.cpp` produces a
valid type 0 midi file given a type 1 or type 0 midi file as input.
2023-07-01 00:15:53 +00:00

59 lines
1.2 KiB
C++

#include <iterator>
#include <tuple>
#include <cassert>
#include <type_traits>
#include "midi.hpp"
#include "parse.hpp"
struct mtrk_iterator {
using difference_type = int32_t;
using element_type = midi::mtrk_event_t;
using pointer = element_type *;
using reference = element_type &;
uint8_t const * track_start;
midi::track_t track;
uint8_t running_status;
uint8_t const * buf;
uint8_t const * next_buf;
midi::mtrk_event_t mtrk_event;
mtrk_iterator() = delete;
mtrk_iterator(const midi::track_t& track,
uint8_t const * const track_start)
: track_start(track_start)
, track(track)
, running_status(0)
, buf(track_start)
, next_buf(track_start)
{
}
mtrk_iterator& operator=(mtrk_iterator&&) = default;
constexpr mtrk_iterator(const mtrk_iterator&) = default;
reference operator*() {
auto mtrk_event_o = midi::parse::mtrk_event(buf, running_status);
std::tie(next_buf, mtrk_event) = *mtrk_event_o;
return mtrk_event;
}
mtrk_iterator operator++() {
assert(buf != next_buf);
buf = next_buf;
return *this;
}
mtrk_iterator operator++(int) {
mtrk_iterator tmp = *this;
++(*this);
return tmp;
}
bool at_end() {
return buf - track_start >= track.length;
}
};