|
- /* Copyright 2013-2019 Matt Tytel
- *
- * vital is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * vital is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with vital. If not, see <http://www.gnu.org/licenses/>.
- */
-
- #pragma once
-
- #include "JuceHeader.h"
- #include "common.h"
-
- #include <string>
- #include <map>
-
- #if !defined(JUCE_AUDIO_DEVICES_H_INCLUDED)
-
- class MidiInput { };
-
- class MidiInputCallback {
- public:
- virtual ~MidiInputCallback() { }
- virtual void handleIncomingMidiMessage(MidiInput *source, const MidiMessage &midi_message) { }
- };
-
- class MidiMessageCollector {
- public:
- void reset(int sample_rate) { }
- void removeNextBlockOfMessages(MidiBuffer& buffer, int num_samples) { }
- void addMessageToQueue(const MidiMessage &midi_message) { }
- };
-
- #endif
-
- class SynthBase;
-
- namespace vital {
- class SoundEngine;
- struct ValueDetails;
- } // namespace vital
-
- class MidiManager : public MidiInputCallback {
- public:
- typedef std::map<int, std::map<std::string, const vital::ValueDetails*>> midi_map;
-
- enum MidiMainType {
- kNoteOff = 0x80,
- kNoteOn = 0x90,
- kAftertouch = 0xa0,
- kController = 0xb0,
- kProgramChange = 0xc0,
- kChannelPressure = 0xd0,
- kPitchWheel = 0xe0,
- };
-
- enum MidiSecondaryType {
- kBankSelect = 0x00,
- kModWheel = 0x01,
- kFolderSelect = 0x20,
- kSustainPedal = 0x40,
- kSostenutoPedal = 0x42,
- kSoftPedalOn = 0x43,
- kSlide = 0x4a,
- kLsbPressure = 0x66,
- kLsbSlide = 0x6a,
- kAllSoundsOff = 0x78,
- kAllControllersOff = 0x79,
- kAllNotesOff = 0x7b,
- };
-
- class Listener {
- public:
- virtual ~Listener() { }
- virtual void valueChangedThroughMidi(const std::string& name, vital::mono_float value) = 0;
- virtual void pitchWheelMidiChanged(vital::mono_float value) = 0;
- virtual void modWheelMidiChanged(vital::mono_float value) = 0;
- virtual void presetChangedThroughMidi(File preset) = 0;
- };
-
- MidiManager(SynthBase* synth, MidiKeyboardState* keyboard_state,
- std::map<std::string, String>* gui_state, Listener* listener = nullptr);
- virtual ~MidiManager();
-
- void armMidiLearn(std::string name);
- void cancelMidiLearn();
- void clearMidiLearn(const std::string& name);
- void midiInput(int control, vital::mono_float value);
- void processMidiMessage(const MidiMessage &midi_message, int sample_position = 0);
- bool isMidiMapped(const std::string& name) const;
-
- void setSampleRate(double sample_rate);
- void removeNextBlockOfMessages(MidiBuffer& buffer, int num_samples);
- void replaceKeyboardMessages(MidiBuffer& buffer, int num_samples);
-
- void processAllNotesOff(const MidiMessage& midi_message, int sample_position, int channel);
- void processAllSoundsOff();
- void processSustain(const MidiMessage& midi_message, int sample_position, int channel);
- void processSostenuto(const MidiMessage& midi_message, int sample_position, int channel);
- void processPitchBend(const MidiMessage& midi_message, int sample_position, int channel);
- void processPressure(const MidiMessage& midi_message, int sample_position, int channel);
- void processSlide(const MidiMessage& midi_message, int sample_position, int channel);
-
- bool isMpeChannelMasterLowerZone(int channel);
- bool isMpeChannelMasterUpperZone(int channel);
-
- force_inline int lowerZoneStartChannel() { return mpe_zone_layout_.getLowerZone().getFirstMemberChannel() - 1; }
- force_inline int upperZoneStartChannel() { return mpe_zone_layout_.getUpperZone().getLastMemberChannel() - 1; }
- force_inline int lowerZoneEndChannel() { return mpe_zone_layout_.getLowerZone().getLastMemberChannel() - 1; }
- force_inline int upperZoneEndChannel() { return mpe_zone_layout_.getUpperZone().getFirstMemberChannel() - 1; }
- force_inline int lowerMasterChannel() { return mpe_zone_layout_.getLowerZone().getMasterChannel() - 1; }
- force_inline int upperMasterChannel() { return mpe_zone_layout_.getUpperZone().getMasterChannel() - 1; }
-
- void setMpeEnabled(bool enabled) { mpe_enabled_ = enabled; }
-
- midi_map getMidiLearnMap() { return midi_learn_map_; }
- void setMidiLearnMap(const midi_map& midi_learn_map) { midi_learn_map_ = midi_learn_map; }
-
- // MidiInputCallback
- void handleIncomingMidiMessage(MidiInput *source, const MidiMessage &midi_message) override;
-
- struct PresetLoadedCallback : public CallbackMessage {
- PresetLoadedCallback(Listener* lis, File pre) : listener(lis), preset(std::move(pre)) { }
-
- void messageCallback() override {
- if (listener)
- listener->presetChangedThroughMidi(preset);
- }
-
- Listener* listener;
- File preset;
- };
-
- protected:
- void readMpeMessage(const MidiMessage& message);
-
- SynthBase* synth_;
- vital::SoundEngine* engine_;
- MidiKeyboardState* keyboard_state_;
- MidiMessageCollector midi_collector_;
- std::map<std::string, String>* gui_state_;
- Listener* listener_;
- int current_bank_;
- int current_folder_;
- int current_preset_;
-
- const vital::ValueDetails* armed_value_;
- midi_map midi_learn_map_;
-
- int msb_pressure_values_[vital::kNumMidiChannels];
- int lsb_pressure_values_[vital::kNumMidiChannels];
- int msb_slide_values_[vital::kNumMidiChannels];
- int lsb_slide_values_[vital::kNumMidiChannels];
-
- bool mpe_enabled_;
- MPEZoneLayout mpe_zone_layout_;
- MidiRPNDetector rpn_detector_;
-
- JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MidiManager)
- };
|