#ifndef _Synth_Synth_h #define _Synth_Synth_h #include using namespace Upp; enum FORMS { WAVEFORM_SIN = 0, WAVEFORM_SQUARE = 1, WAVEFORM_TRIANGLE = 2, WAVEFORM_SAWTOOTH = 3, WAVEFORM_FIRSTSAMPLE = 4, WAVEFORM_SAXOPHONE = WAVEFORM_FIRSTSAMPLE, WAVEFORM_VIOLIN = 5, WAVEFORM_DOUBLEBASS = 6, WAVEFORM_BANJO = 7, WAVEFORM_TRUMPET = 8, WAVEFORM_LASTSAMPLE = 8, WAVEFORM_BROWN = 100, WAVEFORM_WHITE = 101, }; struct FMOP { double duration = 99000; double volume = 0; double f = 1; double fdrift = 0; double attack = 100; double decay = 100; double sustain = 100; double release = 100; int waveform = WAVEFORM_SIN; String Save() const; const char *Load(const char *s); }; #define OPCOUNT 5 struct Sound { double f = 440; FMOP op[OPCOUNT]; double pan = 0.5; String Save() const; void Load(const char *s); Sound(); }; struct SoundGen { struct FMOPGen : FMOP { int p; double v; double n; double *wave_tab; void Start() { v = 1e-3; p = 0; n = 0; } void Comp(); String ToString() const; double Evaluate(int t, double mf, double mod, double& current_volume); }; int serial; int param_serial; int id; int priority; double f = 440; float lpan = 0.5f; float rpan = 0.5f; int t; int delay; FMOPGen op[OPCOUNT]; float feedback[8192]; double current_volume = 0; double lfo_mod = 0; void Start(const Sound& s); float Get(); String ToString() const; }; #define CHUNK_SIZE 512 #define NUM_CHANNELS 20 void InitSoundSynth(bool initsdl = true); void CloseSoundSynth(bool exitsdl = true); void SetChannel(int chi, const Sound& c, int priority = INT_MAX, int id = 0); void SetChannelVolume(int chi, double volume); void StopChannelById(int id); int FindChannel(int priority, int from, double new_volume); void StopChannels(int id); void SetGlobalVolume(float vol); struct SoundEvent : Moveable { Sound *snd; float duration; float frequency; float volume; }; struct SoundSequence { mutable int at = 0; int cursor = 0; int loop = Null; ArrayMap bank; Vector> event; int GetAt(double at) { return (int)(at * 44100 / 512); } Vector& At(double at) { return event.At(GetAt(at)); } void LoopAt(double at) { loop = GetAt(at); } int SoundIndex(const String& s); void Put(double at, int i, double volume, double freqency, double duration, bool direct = false); void Put(double at, const String& snd, double volume, double freqency, double duration, bool direct = false); }; void PlaySequence(const SoundSequence& s); void PlayTempSequence(SoundSequence&& s); void StopSequencer(); bool IsPlayingSequence(); SoundSequence ParseQSF(const String& data); #endif