From a90ae034154b10bb81c74940504a1edca541db7a Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Tue, 26 Jan 2021 20:31:31 +0100 Subject: Add positional information to drumkit xml and sample class. --- src/DGDOM.h | 1 + src/audioinputenginemidi.cc | 56 +++++++++++++++++++++++++++++++++------------ src/audioinputenginemidi.h | 2 ++ src/dgxmlparser.cc | 16 ++++++++++--- src/domloader.cc | 1 + src/event.h | 9 ++++---- src/sample.cc | 9 +++++++- src/sample.h | 5 +++- 8 files changed, 76 insertions(+), 23 deletions(-) diff --git a/src/DGDOM.h b/src/DGDOM.h index 474b29c..a03f0ef 100644 --- a/src/DGDOM.h +++ b/src/DGDOM.h @@ -59,6 +59,7 @@ struct SampleDOM { std::string name; double power; // >= v2.0 only + double position; // >=v2.0 only bool normalized; // >= v2.0 only std::vector audiofiles; }; diff --git a/src/audioinputenginemidi.cc b/src/audioinputenginemidi.cc index ce3ce18..f6fedd6 100644 --- a/src/audioinputenginemidi.cc +++ b/src/audioinputenginemidi.cc @@ -100,9 +100,13 @@ bool AudioInputEngineMidi::isValid() const static const std::uint8_t NoteOff = 0x80; static const std::uint8_t NoteOn = 0x90; static const std::uint8_t NoteAftertouch = 0xA0; +static const std::uint8_t ControlChange = 0xB0; // Note type mask: -static int const NoteMask = 0xF0; +static const std::uint8_t TypeMask = 0xF0; + +// See: +// https://www.midi.org/specifications-old/item/table-1-summary-of-midi-message void AudioInputEngineMidi::processNote(const std::uint8_t* midi_buffer, std::size_t midi_buffer_length, @@ -114,35 +118,59 @@ void AudioInputEngineMidi::processNote(const std::uint8_t* midi_buffer, return; } - auto key = midi_buffer[1]; - auto velocity = midi_buffer[2]; - auto instrument_idx = mmap.lookup(key); - - switch(midi_buffer[0] & NoteMask) + switch(midi_buffer[0] & TypeMask) { case NoteOff: // Ignore for now break; case NoteOn: - if(velocity != 0 && instrument_idx != -1) { - // maps velocities to [.5/127, 126.5/127] - auto centered_velocity = (velocity-.5f)/127.0f; - events.push_back({EventType::OnSet, (std::size_t)instrument_idx, - offset, centered_velocity}); + auto key = midi_buffer[1]; + auto velocity = midi_buffer[2]; + auto instrument_idx = mmap.lookup(key); + if(velocity != 0 && instrument_idx != -1) + { + // maps velocities to [.5/127, 126.5/127] + auto centered_velocity = (velocity-.5f)/127.0f; + events.push_back({ EventType::OnSet, (std::size_t)instrument_idx, + offset, centered_velocity, positional_information }); + } } break; case NoteAftertouch: - if(velocity == 0 && instrument_idx != -1) { - events.push_back({EventType::Choke, (std::size_t)instrument_idx, - offset, .0f}); + auto key = midi_buffer[1]; + auto velocity = midi_buffer[2]; + auto instrument_idx = mmap.lookup(key); + if(velocity == 0 && instrument_idx != -1) + { + events.push_back({ EventType::Choke, (std::size_t)instrument_idx, + offset, .0f, .0f }); + } + } + break; + + case ControlChange: + { + auto controller_number = midi_buffer[1]; + auto value = midi_buffer[2]; + if(controller_number == 16) // positional information + { + // Store value for use in next NoteOn event. + positional_information = value / 127.0f; + + // Return here to prevent reset of cached positional information. + return; + } } break; default: break; } + + // Clear cached positional information. + positional_information = 0.0f; } diff --git a/src/audioinputenginemidi.h b/src/audioinputenginemidi.h index 8da7bd2..12efd66 100644 --- a/src/audioinputenginemidi.h +++ b/src/audioinputenginemidi.h @@ -70,4 +70,6 @@ private: bool is_valid; ConfigFile refs; + + float positional_information{0.0f}; }; diff --git a/src/dgxmlparser.cc b/src/dgxmlparser.cc index 0d3cdcd..bd9af66 100644 --- a/src/dgxmlparser.cc +++ b/src/dgxmlparser.cc @@ -358,9 +358,19 @@ bool parseInstrumentFile(const std::string& filename, InstrumentDOM& dom, LogFun } else { - res &= attrcpy(dom.samples.back().power, sample, "power", logger, filename); - dom.samples.back().normalized = false; - res &= attrcpy(dom.samples.back().normalized, sample, "normalized", logger, filename, true); + res &= attrcpy(dom.samples.back().power, sample, "power", + logger, filename); + + dom.samples.back().position = 0.0; // optional - defaults to 0 + res &= attrcpy(dom.samples.back().position, sample, "position", + logger, filename, true); + // Clamp to [0; 1] range. + dom.samples.back().position = + std::min(1.0, std::max(dom.samples.back().position, 0.0)); + + dom.samples.back().normalized = false; // optional - defaults to false + res &= attrcpy(dom.samples.back().normalized, sample, "normalized", + logger, filename, true); } for(pugi::xml_node audiofile: sample.children("audiofile")) diff --git a/src/domloader.cc b/src/domloader.cc index c78ed75..5d411bd 100644 --- a/src/domloader.cc +++ b/src/domloader.cc @@ -99,6 +99,7 @@ bool DOMLoader::loadDom(const std::string& basepath, for(const auto& sampledom : instrumentdom.samples) { auto sample = new Sample(sampledom.name, sampledom.power, + sampledom.position, sampledom.normalized); for(const auto& audiofiledom : sampledom.audiofiles) { diff --git a/src/event.h b/src/event.h index 737fb18..5780cc9 100644 --- a/src/event.h +++ b/src/event.h @@ -39,8 +39,9 @@ enum class EventType //! POD datatype for input event transport. struct event_t { - EventType type; //!< The type of the event. - std::size_t instrument; //!< The instrument number. - std::size_t offset; //!< The offset position in the input buffer - float velocity; //!< The velocity if the type is a note on [0; 1] + EventType type; //!< The type of the event. + std::size_t instrument; //!< The instrument number. + std::size_t offset; //!< The offset position in the input buffer + float velocity; //!< The velocity if the type is a note on [0; 1] + float position; //!< The position of the note. 0 := center, 1 := rim }; diff --git a/src/sample.cc b/src/sample.cc index 9af2c08..2c59f5e 100644 --- a/src/sample.cc +++ b/src/sample.cc @@ -28,9 +28,11 @@ #include -Sample::Sample(const std::string& name, double power, bool normalized) +Sample::Sample(const std::string& name, double power, double position, + bool normalized) : name{name} , power{power} + , position{position} , normalized(normalized) , audiofiles{} { @@ -69,6 +71,11 @@ double Sample::getPower() const return power; } +double Sample::getPosition() const +{ + return position; +} + bool Sample::getNormalized() const { return normalized; diff --git a/src/sample.h b/src/sample.h index 6c31b6b..b13f624 100644 --- a/src/sample.h +++ b/src/sample.h @@ -37,12 +37,14 @@ using AudioFiles = std::map; class Sample { public: - Sample(const std::string& name, double power, bool normalized = false); + Sample(const std::string& name, double power, double position, + bool normalized = false); ~Sample(); AudioFile* getAudioFile(const Channel& channel) const; double getPower() const; + double getPosition() const; bool getNormalized() const; private: @@ -55,6 +57,7 @@ private: std::string name; double power; + double position{0.0}; bool normalized; AudioFiles audiofiles; }; -- cgit v1.2.3