You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

212 lines
8.4KB

  1. /* Copyright 2013-2019 Matt Tytel
  2. *
  3. * vital is free software: you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation, either version 3 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * vital is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with vital. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #pragma once
  17. #include "JuceHeader.h"
  18. #include "concurrentqueue/concurrentqueue.h"
  19. #include "line_generator.h"
  20. #include "synth_constants.h"
  21. #include "synth_types.h"
  22. #include "midi_manager.h"
  23. #include "tuning.h"
  24. #include "wavetable_creator.h"
  25. #include <set>
  26. #include <string>
  27. namespace vital {
  28. class SoundEngine;
  29. struct Output;
  30. class StatusOutput;
  31. class StereoMemory;
  32. class Sample;
  33. class WaveFrame;
  34. class Wavetable;
  35. }
  36. class SynthGuiInterface;
  37. class SynthBase : public MidiManager::Listener {
  38. public:
  39. static constexpr float kOutputWindowMinNote = 16.0f;
  40. static constexpr float kOutputWindowMaxNote = 128.0f;
  41. SynthBase();
  42. virtual ~SynthBase();
  43. void valueChanged(const std::string& name, vital::mono_float value);
  44. void valueChangedThroughMidi(const std::string& name, vital::mono_float value) override;
  45. void pitchWheelMidiChanged(vital::mono_float value) override;
  46. void modWheelMidiChanged(vital::mono_float value) override;
  47. void pitchWheelGuiChanged(vital::mono_float value);
  48. void modWheelGuiChanged(vital::mono_float value);
  49. void presetChangedThroughMidi(File preset) override;
  50. void valueChangedExternal(const std::string& name, vital::mono_float value);
  51. void valueChangedInternal(const std::string& name, vital::mono_float value);
  52. bool connectModulation(const std::string& source, const std::string& destination);
  53. void connectModulation(vital::ModulationConnection* connection);
  54. void disconnectModulation(const std::string& source, const std::string& destination);
  55. void disconnectModulation(vital::ModulationConnection* connection);
  56. void clearModulations();
  57. void forceShowModulation(const std::string& source, bool force);
  58. bool isModSourceEnabled(const std::string& source);
  59. int getNumModulations(const std::string& destination);
  60. int getConnectionIndex(const std::string& source, const std::string& destination);
  61. vital::CircularQueue<vital::ModulationConnection*> getModulationConnections() { return mod_connections_; }
  62. std::vector<vital::ModulationConnection*> getSourceConnections(const std::string& source);
  63. bool isSourceConnected(const std::string& source);
  64. std::vector<vital::ModulationConnection*> getDestinationConnections(const std::string& destination);
  65. const vital::StatusOutput* getStatusOutput(const std::string& name);
  66. vital::Wavetable* getWavetable(int index);
  67. WavetableCreator* getWavetableCreator(int index);
  68. vital::Sample* getSample();
  69. LineGenerator* getLfoSource(int index);
  70. int getSampleRate();
  71. void initEngine();
  72. void loadTuningFile(const File& file);
  73. void loadInitPreset();
  74. bool loadFromFile(File preset, std::string& error);
  75. void renderAudioToFile(File file, float seconds, float bpm, std::vector<int> notes, bool render_images);
  76. void renderAudioForResynthesis(float* data, int samples, int note);
  77. bool saveToFile(File preset);
  78. bool saveToActiveFile();
  79. void clearActiveFile() { active_file_ = File(); }
  80. File getActiveFile() { return active_file_; }
  81. void setMpeEnabled(bool enabled);
  82. virtual void beginChangeGesture(const std::string& name) { }
  83. virtual void endChangeGesture(const std::string& name) { }
  84. virtual void setValueNotifyHost(const std::string& name, vital::mono_float value) { }
  85. void armMidiLearn(const std::string& name);
  86. void cancelMidiLearn();
  87. void clearMidiLearn(const std::string& name);
  88. bool isMidiMapped(const std::string& name);
  89. void setAuthor(const String& author);
  90. void setComments(const String& comments);
  91. void setStyle(const String& comments);
  92. void setPresetName(const String& preset_name);
  93. void setMacroName(int index, const String& macro_name);
  94. String getAuthor();
  95. String getComments();
  96. String getStyle();
  97. String getPresetName();
  98. String getMacroName(int index);
  99. vital::control_map& getControls() { return controls_; }
  100. vital::SoundEngine* getEngine() { return engine_.get(); }
  101. MidiKeyboardState* getKeyboardState() { return keyboard_state_.get(); }
  102. const vital::poly_float* getOscilloscopeMemory() { return oscilloscope_memory_; }
  103. const vital::StereoMemory* getAudioMemory() { return audio_memory_.get(); }
  104. const vital::StereoMemory* getEqualizerMemory();
  105. vital::ModulationConnectionBank& getModulationBank();
  106. void notifyOversamplingChanged();
  107. void checkOversampling();
  108. virtual const CriticalSection& getCriticalSection() = 0;
  109. virtual void pauseProcessing(bool pause) = 0;
  110. Tuning* getTuning() { return &tuning_; }
  111. struct ValueChangedCallback : public CallbackMessage {
  112. ValueChangedCallback(std::shared_ptr<SynthBase*> listener, std::string name, vital::mono_float val) :
  113. listener(listener), control_name(std::move(name)), value(val) { }
  114. void messageCallback() override;
  115. std::weak_ptr<SynthBase*> listener;
  116. std::string control_name;
  117. vital::mono_float value;
  118. };
  119. protected:
  120. vital::modulation_change createModulationChange(vital::ModulationConnection* connection);
  121. bool isInvalidConnection(const vital::modulation_change& change);
  122. virtual SynthGuiInterface* getGuiInterface() = 0;
  123. json saveToJson();
  124. bool loadFromJson(const json& state);
  125. vital::ModulationConnection* getConnection(const std::string& source, const std::string& destination);
  126. inline bool getNextModulationChange(vital::modulation_change& change) {
  127. return modulation_change_queue_.try_dequeue_non_interleaved(change);
  128. }
  129. inline void clearModulationQueue() {
  130. vital::modulation_change change;
  131. while (modulation_change_queue_.try_dequeue_non_interleaved(change))
  132. ;
  133. }
  134. void processAudio(AudioSampleBuffer* buffer, int channels, int samples, int offset);
  135. void processAudioWithInput(AudioSampleBuffer* buffer, const vital::poly_float* input_buffer,
  136. int channels, int samples, int offset);
  137. void writeAudio(AudioSampleBuffer* buffer, int channels, int samples, int offset);
  138. void processMidi(MidiBuffer& buffer, int start_sample = 0, int end_sample = 0);
  139. void processKeyboardEvents(MidiBuffer& buffer, int num_samples);
  140. void processModulationChanges();
  141. void updateMemoryOutput(int samples, const vital::poly_float* audio);
  142. std::unique_ptr<vital::SoundEngine> engine_;
  143. std::unique_ptr<MidiManager> midi_manager_;
  144. std::unique_ptr<MidiKeyboardState> keyboard_state_;
  145. std::unique_ptr<WavetableCreator> wavetable_creators_[vital::kNumOscillators];
  146. std::shared_ptr<SynthBase*> self_reference_;
  147. File active_file_;
  148. vital::poly_float oscilloscope_memory_[2 * vital::kOscilloscopeMemoryResolution];
  149. vital::poly_float oscilloscope_memory_write_[2 * vital::kOscilloscopeMemoryResolution];
  150. std::unique_ptr<vital::StereoMemory> audio_memory_;
  151. vital::mono_float last_played_note_;
  152. int last_num_pressed_;
  153. vital::mono_float memory_reset_period_;
  154. vital::mono_float memory_input_offset_;
  155. int memory_index_;
  156. bool expired_;
  157. std::map<std::string, String> save_info_;
  158. vital::control_map controls_;
  159. vital::CircularQueue<vital::ModulationConnection*> mod_connections_;
  160. moodycamel::ConcurrentQueue<vital::control_change> value_change_queue_;
  161. moodycamel::ConcurrentQueue<vital::modulation_change> modulation_change_queue_;
  162. Tuning tuning_;
  163. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SynthBase)
  164. };
  165. class HeadlessSynth : public SynthBase {
  166. public:
  167. virtual const CriticalSection& getCriticalSection() override {
  168. return critical_section_;
  169. }
  170. virtual void pauseProcessing(bool pause) override {
  171. if (pause)
  172. critical_section_.enter();
  173. else
  174. critical_section_.exit();
  175. }
  176. protected:
  177. virtual SynthGuiInterface* getGuiInterface() override { return nullptr; }
  178. private:
  179. CriticalSection critical_section_;
  180. };