/* * This file is part of libEmuSC, a Sound Canvas emulator library * Copyright (C) 2022-2024 HÃ¥kon Skjelten * * libEmuSC is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * libEmuSC 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 Lesser General Public License for more details. * * You should have received a copy of the GNU General Public License * along with libEmuSC. If not, see . */ #ifndef __SYNTH_H__ #define __SYNTH_H__ #include "control_rom.h" #include "params.h" #include "pcm_rom.h" #include #include #include #include #include /* Public API for libEmuSC * * This Synth class is responsible for receiving MIDI events from client, * process the event based on information in Control and PCM ROMS, and * finally responding to audio buffer requests. * * Synth class constructor depends on a valid Control Rom and PCM ROM. * * MIDI events is sent to the emulator via the midi_input() method using the * three bytes from raw MIDI events. * * Audio samples are extracted by calling the get_next_sample() method. This * is typically done from a callback function triggered by the OS audio * driver when the audio buffer is running low. * * All settings are configured through the Settings class. */ namespace EmuSC { class Part; class Settings; class Synth { public: enum class SoundMap { GS, // Default GS settings GS_GM, // GS settings in GM mode (available on SC55mk2+) MT32 // MT32 arrangement }; Synth(ControlRom &cRom, PcmRom &pRom, SoundMap map = SoundMap::GS); ~Synth(); // Add start() and stop()? Won't start if sampleRate is not set? void midi_input(uint8_t status, uint8_t data1, uint8_t data2); void midi_input_sysex(const uint8_t *data, uint16_t length); int get_next_sample(int16_t *sample); int get_next_sample(float *sample); std::array get_parts_last_peak_sample(void); // Setting audio properties (default is 44100, 2) void set_audio_format(uint32_t sampleRate, uint8_t channels); void set_interpolation_mode(int mode); void reset(SoundMap sm, bool resetParts = false); void panic(void); // Mute all parts. Similar to push MUTE-button on real hardware void mute(void); // Unmute all parts. Similar to push MUTE-button on real hardware void unmute(void); // Mute 1-n parts void mute_parts(std::vector parts); // Unute all parts void unmute_parts(std::vector parts); // Returns libEmuSC version as a string static std::string version(void); // REMOVE! bool get_part_mute(uint8_t partId); uint8_t get_part_instrument(uint8_t partId, uint8_t &bank); void set_part_mute(uint8_t partId, bool mute); void set_part_instrument(uint8_t partId, uint8_t index, uint8_t bank); void add_part_midi_mod_callback(std::function callback); void clear_part_midi_mod_callback(void); void set_part_envelope_callback(int partId, std::function callback); void clear_part_envelope_callback(int partId); void set_part_lfo_callback(int partId, std::function callback); void clear_part_lfo_callback(int partId); // EmuSC clients methods for getting synth paramters uint8_t get_param(enum SystemParam sp); uint8_t* get_param_ptr(enum SystemParam sp); uint16_t get_param_32nib(enum SystemParam sp); uint8_t get_param(enum PatchParam pp, int8_t part = -1); uint8_t* get_param_ptr(enum PatchParam pp, int8_t part = -1); uint16_t get_param_uint14(enum PatchParam pp, int8_t part = -1); uint8_t get_param_nib16(enum PatchParam pp, int8_t part = -1); uint8_t get_patch_param(uint16_t address, int8_t part = -1); uint8_t get_param(enum DrumParam, uint8_t map, uint8_t key); int8_t* get_param_ptr(enum DrumParam, uint8_t map); // EmuSC clients methods for setting synth paramters void set_param(enum SystemParam sp, uint8_t value); void set_param(enum SystemParam sp, uint32_t value); void set_param(enum SystemParam sp, const uint8_t *data, uint8_t size = 1); void set_param_32nib(enum SystemParam sp, uint16_t value); void set_param(enum PatchParam pp, uint8_t value, int8_t part = -1); void set_param(enum PatchParam sp, const uint8_t *data, uint8_t size = 1, int8_t part = -1); void set_param_uint14(enum PatchParam pp, uint16_t value, int8_t part = -1); void set_param_nib16(enum PatchParam pp, uint8_t value, int8_t part = -1); void set_patch_param(uint16_t address, uint8_t value, int8_t part = 1); void set_param(enum DrumParam dp, uint8_t map, uint8_t key, uint8_t value); void set_param(enum DrumParam dp, uint8_t map, const uint8_t *data, uint8_t length); /* End of public API. Below are internal data structures only */ private: Settings *_settings; uint32_t _sampleRate; uint8_t _channels; std::mutex midiMutex; struct std::vector _parts; std::vector> _partMidiModCallbacks; ControlRom &_ctrlRom; PcmRom &_pcmRom; // MIDI message types static const uint8_t midi_NoteOff = 0x80; static const uint8_t midi_NoteOn = 0x90; static const uint8_t midi_PolyKeyPressure = 0xa0; static const uint8_t midi_CtrlChange = 0xb0; static const uint8_t midi_PrgChange = 0xc0; static const uint8_t midi_ChPressure = 0xd0; static const uint8_t midi_PitchBend = 0xe0; void _init_parts(void); // int _export_sample_24(std::vector &sampleSet, std::string filename); void _add_note(uint8_t midiChannel, uint8_t key, uint8_t velocity); void _midi_input_sysex_DT1(uint8_t model, const uint8_t *data, uint16_t length); Synth(); }; } #endif // __SYNTH_H__