From a095aef4f9d2fe0584eeadca85039dbc838355ed 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 | 80 +++++++++++++++++++++++++++++---------------- src/audioinputenginemidi.h | 2 ++ src/dgxmlparser.cc | 16 +++++++-- src/domloader.cc | 1 + src/engineevent.h | 9 ++--- src/sample.cc | 9 ++++- src/sample.h | 5 ++- 8 files changed, 86 insertions(+), 37 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 2e794f4..240acc3 100644 --- a/src/audioinputenginemidi.cc +++ b/src/audioinputenginemidi.cc @@ -94,6 +94,7 @@ bool AudioInputEngineMidi::isValid() const constexpr std::uint8_t NoteOff{0x80}; constexpr std::uint8_t NoteOn{0x90}; constexpr std::uint8_t NoteAftertouch{0xA0}; +constexpr std::uint8_t ControlChange{0xB0}; // Note type mask: constexpr std::uint8_t NoteMask{0xF0}; @@ -108,42 +109,65 @@ void AudioInputEngineMidi::processNote(const std::uint8_t* midi_buffer, return; } - auto key = midi_buffer[1]; // NOLINT - span - auto velocity = midi_buffer[2]; // NOLINT - span - auto instrument_idx = mmap.lookup(key); - auto instruments = mmap.lookup(key); - for(const auto& instrument_idx : instruments) + switch(midi_buffer[0] & NoteMask) // NOLINT - span { - switch(midi_buffer[0] & NoteMask) // NOLINT - span - { - case NoteOff: - // Ignore for now - break; + case NoteOff: + // Ignore for now + break; - case NoteOn: - if(velocity != 0) + case NoteOn: + { + auto key = midi_buffer[1]; // NOLINT - span + auto velocity = midi_buffer[2]; // NOLINT - span + auto instruments = mmap.lookup(key); + for(const auto& instrument_idx : instruments) { - constexpr float lower_offset{0.5f}; - constexpr float midi_velocity_max{127.0f}; - // maps velocities to [.5/127, 126.5/127] - assert(velocity <= 127); // MIDI only support up to 127 - auto centered_velocity = - (static_cast(velocity) - lower_offset) / midi_velocity_max; - events.push_back({EventType::OnSet, (std::size_t)instrument_idx, - offset, centered_velocity}); + if(velocity != 0) + { + constexpr float lower_offset{0.5f}; + constexpr float midi_velocity_max{127.0f}; + // maps velocities to [.5/127, 126.5/127] + assert(velocity <= 127); // MIDI only support up to 127 + auto centered_velocity = + (static_cast(velocity) - lower_offset) / midi_velocity_max; + events.push_back({EventType::OnSet, (std::size_t)instrument_idx, + offset, centered_velocity, positional_information}); + } } - break; + } + break; - case NoteAftertouch: - if(velocity > 0) + case NoteAftertouch: + { + auto key = midi_buffer[1]; // NOLINT - span + auto velocity = midi_buffer[2]; // NOLINT - span + auto instruments = mmap.lookup(key); + for(const auto& instrument_idx : instruments) { - events.push_back({EventType::Choke, (std::size_t)instrument_idx, - offset, .0f}); + if(velocity > 0) + { + events.push_back({EventType::Choke, (std::size_t)instrument_idx, + offset, .0f, .0f}); + } } - break; + } + break; - default: - break; + case ControlChange: + { + auto controller_number = midi_buffer[1]; // NOLINT - span + auto value = midi_buffer[2]; // NOLINT - span + 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; + } } } + + // Clear cached positional information. + positional_information = 0.0f; } diff --git a/src/audioinputenginemidi.h b/src/audioinputenginemidi.h index 386a055..28da538 100644 --- a/src/audioinputenginemidi.h +++ b/src/audioinputenginemidi.h @@ -71,4 +71,6 @@ private: bool is_valid{false}; ConfigFile refs{REFSFILE}; + + 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/engineevent.h b/src/engineevent.h index 9c60a4a..bf2b712 100644 --- a/src/engineevent.h +++ b/src/engineevent.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