diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/audiofile.h | 2 | ||||
-rw-r--r-- | src/audioinputenginemidi.cc | 51 | ||||
-rw-r--r-- | src/drumgizmo.cc | 37 | ||||
-rw-r--r-- | src/drumgizmo.h | 2 | ||||
-rw-r--r-- | src/drumkitloader.cc | 5 | ||||
-rw-r--r-- | src/events_ds.cc | 19 | ||||
-rw-r--r-- | src/events_ds.h | 9 | ||||
-rw-r--r-- | src/inputprocessor.cc | 29 | ||||
-rw-r--r-- | src/memory_heap.h | 8 | ||||
-rw-r--r-- | src/midimapparser.cc | 3 | ||||
-rw-r--r-- | src/midimapper.cc | 24 | ||||
-rw-r--r-- | src/midimapper.h | 16 | ||||
-rw-r--r-- | src/sample_selection.cc | 3 | ||||
-rw-r--r-- | src/settings.h | 1 | ||||
-rw-r--r-- | src/translation.h | 2 |
16 files changed, 156 insertions, 57 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index b656f48..85b10fa 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -32,7 +32,7 @@ libpugi_la_SOURCES = \ libdg_la_CPPFLAGS = \ $(DEBUG_FLAGS) \ -I$(top_srcdir)/hugin -I$(top_srcdir)/pugixml/src \ - $(SSEFLAGS) -I$(top_srcdir)/zita-resampler/libs + $(SSEFLAGS) -I$(top_srcdir)/zita-resampler/libs \ $(SNDFILE_CFLAGS) $(PTHREAD_CFLAGS) libdg_la_LIBADD = \ diff --git a/src/audiofile.h b/src/audiofile.h index e20d91f..504d0ae 100644 --- a/src/audiofile.h +++ b/src/audiofile.h @@ -32,8 +32,6 @@ #include <limits> #include <mutex> -#include <sndfile.h> - #include "audio.h" #include "channel.h" #include "logger.h" diff --git a/src/audioinputenginemidi.cc b/src/audioinputenginemidi.cc index ce3ce18..69aeeb6 100644 --- a/src/audioinputenginemidi.cc +++ b/src/audioinputenginemidi.cc @@ -117,32 +117,35 @@ void AudioInputEngineMidi::processNote(const std::uint8_t* midi_buffer, auto key = midi_buffer[1]; auto velocity = midi_buffer[2]; auto instrument_idx = mmap.lookup(key); - - switch(midi_buffer[0] & NoteMask) + auto instruments = mmap.lookup(key); + for(const auto& instrument_idx : instruments) { - 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}); - } - break; - - case NoteAftertouch: - if(velocity == 0 && instrument_idx != -1) + switch(midi_buffer[0] & NoteMask) { - events.push_back({EventType::Choke, (std::size_t)instrument_idx, - offset, .0f}); + case NoteOff: + // Ignore for now + break; + + case NoteOn: + if(velocity != 0) + { + // 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}); + } + break; + + case NoteAftertouch: + if(velocity > 0) + { + events.push_back({EventType::Choke, (std::size_t)instrument_idx, + offset, .0f}); + } + break; + + default: + break; } - break; - - default: - break; } } diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc index ca91c12..abe57be 100644 --- a/src/drumgizmo.cc +++ b/src/drumgizmo.cc @@ -119,6 +119,12 @@ void DrumGizmo::setRandomSeed(unsigned int seed) bool DrumGizmo::run(size_t pos, sample_t *samples, size_t nsamples) { + if(settings_getter.drumkit_file.hasChanged()) + { + // New kit loaded/loading - old events no longer makes sense. + events_ds.clear(); + } + if(settings_getter.enable_resampling.hasChanged()) { enable_resampling = settings_getter.enable_resampling.getValue(); @@ -191,6 +197,11 @@ bool DrumGizmo::run(size_t pos, sample_t *samples, size_t nsamples) for(size_t c = 0; c < kit.channels.size(); ++c) { + if(c >= NUM_CHANNELS) // kit may have more channels than the engine + { + break; + } + sample_t *buf = samples; bool internal = false; if(oe.getBuffer(c)) @@ -218,6 +229,11 @@ bool DrumGizmo::run(size_t pos, sample_t *samples, size_t nsamples) size_t kitpos = pos * ratio; for(size_t c = 0; c < kit.channels.size(); ++c) { + if(c >= NUM_CHANNELS) // kit may have more channels than the engine + { + break; + } + sample_t *buf = samples; bool internal = false; if(oe.getBuffer(c)) @@ -333,6 +349,8 @@ repeat: void DrumGizmo::getSamples(int ch, int pos, sample_t* s, size_t sz) { + assert(ch < NUM_CHANNELS); + // Store local values of settings to ensure they don't change intra-iteration const auto enable_bleed_control = settings.enable_bleed_control.load(); const auto master_bleed = settings.master_bleed.load(); @@ -346,8 +364,9 @@ void DrumGizmo::getSamples(int ch, int pos, sample_t* s, size_t sz) if(!af.isLoaded() || !af.isValid() || (s == nullptr)) { - removeevent = true; - break; + // This event cannot be played - schedule for deletion and continue. + to_remove.push_back(sample_event.id); + continue; } if(sample_event.offset > (pos + sz)) @@ -431,7 +450,7 @@ float DrumGizmo::samplerate() void DrumGizmo::setSamplerate(float samplerate, float resampling_quality) { - DEBUG(dgeditor, "%s samplerate: %f\n", __PRETTY_FUNCTION__, samplerate); + DEBUG(engine, "%s samplerate: %f\n", __PRETTY_FUNCTION__, samplerate); settings.samplerate.store(samplerate); // Notify input engine of the samplerate change. @@ -463,10 +482,14 @@ void DrumGizmo::setSamplerate(float samplerate, float resampling_quality) zita[c].set_inp_data(nullptr); zita[c].set_inp_count(null_size); - constexpr auto sz = 4096 * 16; - sample_t s[sz]; - zita[c].set_out_data(s); - zita[c].set_out_count(sz); + std::size_t scratch_buffer_size = (null_size / ratio); + + if(scratch_buffer.size() < scratch_buffer_size) + { + scratch_buffer.resize(scratch_buffer_size); + } + zita[c].set_out_data(scratch_buffer.data()); + zita[c].set_out_count(scratch_buffer_size); zita[c].process(); } diff --git a/src/drumgizmo.h b/src/drumgizmo.h index f08c9f7..89c2960 100644 --- a/src/drumgizmo.h +++ b/src/drumgizmo.h @@ -107,5 +107,5 @@ protected: std::array<ZRWrapper, NUM_CHANNELS> zita; std::array<std::unique_ptr<sample_t>, NUM_CHANNELS> resampler_input_buffer; double ratio = 1.0; - + std::vector<sample_t> scratch_buffer; }; diff --git a/src/drumkitloader.cc b/src/drumkitloader.cc index 6a4c9f4..9167201 100644 --- a/src/drumkitloader.cc +++ b/src/drumkitloader.cc @@ -138,7 +138,7 @@ bool DrumKitLoader::loadkit(const std::string& file) settings.drumkit_samplerate.store(44100); settings.load_status_text.store(""); - settings.drumkit_load_status.store(LoadStatus::Loading); + settings.drumkit_load_status.store(LoadStatus::Parsing); // Parse drumkit and instrument xml @@ -226,6 +226,9 @@ bool DrumKitLoader::loadkit(const std::string& file) settings.midimap_file = drumkit_path + "/" + drumkitdom.metadata.default_midimap_file; } + // Done parsing. Now start loading the audio + settings.midimap_load_status.store(LoadStatus::Loading); + loadKitAudio(kit); DEBUG(loadkit, "loadkit: Success\n"); diff --git a/src/events_ds.cc b/src/events_ds.cc index ee21f93..0195a89 100644 --- a/src/events_ds.cc +++ b/src/events_ds.cc @@ -99,6 +99,25 @@ void EventsDS::startAddingNewGroup(InstrumentID instrument_id) } } +void EventsDS::clear() +{ + // *this = EventsDS(); + + id_to_info.clear(); + id_to_group_data.clear(); + for (auto& channel_data: channel_data_array) + { + channel_data.sample_events.clear(); + } + for (auto& event_group_ids: instruments_sample_event_group_ids) + { + event_group_ids.clear(); + } + + current_group_id.invalidate(); + current_groups_instrument_id.invalidate(); +} + void EventsDS::removeGroup(EventGroupID group_id, InstrumentID instrument_id) { // if we remove the current group, then invalidate it diff --git a/src/events_ds.h b/src/events_ds.h index 5855711..41287d1 100644 --- a/src/events_ds.h +++ b/src/events_ds.h @@ -96,6 +96,9 @@ public: //! when startAddingNewGroup is again called. void startAddingNewGroup(InstrumentID instrument_id = InstrumentID()); + //! Clears the whole data structure to make it ready for a new drum kit. + void clear(); + private: struct ChannelData { @@ -146,6 +149,8 @@ private: template <typename T, typename... Args> T& EventsDS::emplace(channel_t ch, Args&&... args) { + assert(ch < NUM_CHANNELS); + // add new event types here static_assert(std::is_same<T, SampleEvent>::value, "Check event type"); @@ -177,6 +182,8 @@ T& EventsDS::get(EventID event_id) template <typename T> ContainerRange<std::vector<T>> EventsDS::iterateOver(channel_t ch) { + assert(ch < NUM_CHANNELS); + // add new event types here static_assert(std::is_same<T, SampleEvent>::value, "Check event type"); @@ -190,6 +197,8 @@ ContainerRange<std::vector<T>> EventsDS::iterateOver(channel_t ch) template <typename T> T& EventsDS::getSample(EventInfo const& info) { + assert(info.ch < NUM_CHANNELS); + // add new event types here static_assert(std::is_same<T, SampleEvent>::value, "Check event type"); diff --git a/src/inputprocessor.cc b/src/inputprocessor.cc index fd6e5b9..7d12bdd 100644 --- a/src/inputprocessor.cc +++ b/src/inputprocessor.cc @@ -163,6 +163,11 @@ static void applyChokeGroup(Settings& settings, DrumKit& kit, // Add event to ramp down all existing events with the same groupname. for(const auto& ch : kit.channels) { + if(ch.num >= NUM_CHANNELS) // kit may have more channels than the engine + { + continue; + } + for(auto& event_sample : events_ds.iterateOver<SampleEvent>(ch.num)) { if(event_sample.group == instr.getGroup() && @@ -186,13 +191,18 @@ static void applyDirectedChoke(Settings& settings, DrumKit& kit, // Add event to ramp down all existing events with the same groupname. for(const auto& ch : kit.channels) { + if(ch.num >= NUM_CHANNELS) // kit may have more channels than the engine + { + continue; + } + for(auto& event_sample : events_ds.iterateOver<SampleEvent>(ch.num)) { if(choke.instrument_id == event_sample.instrument_id && event_sample.rampdown_count == -1) // Only if not already ramping. { // choke.choketime is in ms - applyChoke(settings, event_sample, choke.choketime, event_sample.offset); + applyChoke(settings, event_sample, choke.choketime, event.offset); } } } @@ -264,6 +274,11 @@ bool InputProcessor::processOnset(event_t& event, std::size_t pos, bool new_group_added = false; for(Channel& ch: kit.channels) { + if(ch.num >= NUM_CHANNELS) // kit may have more channels than the engine + { + continue; + } + const auto af = sample->getAudioFile(ch); if(af == nullptr || !af->isValid()) { @@ -330,13 +345,18 @@ bool InputProcessor::processChoke(event_t& event, // Add event to ramp down all existing events with the same groupname. for(const auto& ch : kit.channels) { + if(ch.num >= NUM_CHANNELS) // kit may have more channels than the engine + { + continue; + } + for(auto& event_sample : events_ds.iterateOver<SampleEvent>(ch.num)) { if(event_sample.instrument_id == instrument_id && event_sample.rampdown_count == -1) // Only if not already ramping. { // Fixed group rampdown time of 68ms, independent of samplerate - applyChoke(settings, event_sample, 68, event_sample.offset); + applyChoke(settings, event_sample, 450, event.offset); } } } @@ -357,6 +377,11 @@ bool InputProcessor::processStop(event_t& event) int num_active_events = 0; for(auto& ch: kit.channels) { + if(ch.num >= NUM_CHANNELS) // kit may have more channels than the engine + { + continue; + } + num_active_events += events_ds.numberOfEvents(ch.num); } diff --git a/src/memory_heap.h b/src/memory_heap.h index 3f0105a..658598c 100644 --- a/src/memory_heap.h +++ b/src/memory_heap.h @@ -61,6 +61,7 @@ public: T& get(Index index); const T& get(Index index) const; void remove(Index index); + void clear(); private: std::vector<T> memory; @@ -119,3 +120,10 @@ void MemoryHeap<T>::remove(Index index) { free_indices.push_back(index); } + +template <typename T> +void MemoryHeap<T>::clear() +{ + memory.clear(); + free_indices.clear(); +} diff --git a/src/midimapparser.cc b/src/midimapparser.cc index 059dfec..363e1d5 100644 --- a/src/midimapparser.cc +++ b/src/midimapparser.cc @@ -50,7 +50,8 @@ bool MidiMapParser::parseFile(const std::string& filename) continue; } - midimap[note] = instr; + MidimapEntry entry{note, instr}; + midimap.push_back(entry); } return true; diff --git a/src/midimapper.cc b/src/midimapper.cc index 9593aae..b9316c5 100644 --- a/src/midimapper.cc +++ b/src/midimapper.cc @@ -26,23 +26,25 @@ */ #include "midimapper.h" -int MidiMapper::lookup(int note) +std::vector<int> MidiMapper::lookup(int note_id) { - std::lock_guard<std::mutex> guard(mutex); + std::vector<int> instruments; - auto midimap_it = midimap.find(note); - if(midimap_it == midimap.end()) - { - return -1; - } + std::lock_guard<std::mutex> guard(mutex); - auto instrmap_it = instrmap.find(midimap_it->second); - if(instrmap_it == instrmap.end()) + for(const auto& map_entry : midimap) { - return -1; + if(map_entry.note_id == note_id) + { + auto instrmap_it = instrmap.find(map_entry.instrument_name); + if(instrmap_it != instrmap.end()) + { + instruments.push_back(instrmap_it->second); + } + } } - return instrmap_it->second; + return instruments; } void MidiMapper::swap(instrmap_t& instrmap, midimap_t& midimap) diff --git a/src/midimapper.h b/src/midimapper.h index 4673e33..94781d4 100644 --- a/src/midimapper.h +++ b/src/midimapper.h @@ -29,16 +29,22 @@ #include <map> #include <string> #include <mutex> +#include <vector> -typedef std::map<int, std::string> midimap_t; -typedef std::map<std::string, int> instrmap_t; +struct MidimapEntry +{ + int note_id; + std::string instrument_name; +}; + +using midimap_t = std::vector<MidimapEntry>; +using instrmap_t = std::map<std::string, int>; class MidiMapper { public: - //! Lookup note in map and return its index. - //! \returns -1 if not found or the note index. - int lookup(int note); + //! Lookup note in map and returns the corresponding instrument index list. + std::vector<int> lookup(int note_id); //! Set new map sets. void swap(instrmap_t& instrmap, midimap_t& midimap); diff --git a/src/sample_selection.cc b/src/sample_selection.cc index 7267faf..31313bb 100644 --- a/src/sample_selection.cc +++ b/src/sample_selection.cc @@ -103,8 +103,7 @@ const Sample* SampleSelection::get(level_t level, std::size_t pos) { DEBUG(rand, "%d %d", (int)up_index, (int)down_index); - // at least avoid infinite loops in case of a bug... - if (up_index == samples.size()-1 && down_index == 0) { break; } + assert(down_index <= up_index); std::size_t current_index; if (up_value_lb < down_value_lb) diff --git a/src/settings.h b/src/settings.h index 7507827..fb93d79 100644 --- a/src/settings.h +++ b/src/settings.h @@ -38,6 +38,7 @@ enum class LoadStatus : unsigned int { Idle, + Parsing, Loading, Done, Error diff --git a/src/translation.h b/src/translation.h index 7f506a6..d8a6072 100644 --- a/src/translation.h +++ b/src/translation.h @@ -26,6 +26,8 @@ */ #pragma once +#include <cstdint> + #include <config.h> #ifdef WITH_NLS |