OscilGen.h (9022B)
1 /* 2 ZynAddSubFX - a software synthesizer 3 4 OscilGen.h - Waveform generator for ADnote 5 Copyright (C) 2002-2005 Nasca Octavian Paul 6 Author: Nasca Octavian Paul 7 8 This program is free software; you can redistribute it and/or 9 modify it under the terms of the GNU General Public License 10 as published by the Free Software Foundation; either version 2 11 of the License, or (at your option) any later version. 12 */ 13 14 #ifndef OSCIL_GEN_H 15 #define OSCIL_GEN_H 16 17 #include "../globals.h" 18 #include <rtosc/ports.h> 19 #include "../Params/Presets.h" 20 #include "../DSP/FFTwrapper.h" 21 22 namespace zyn { 23 24 class NoCopyNoMove 25 { 26 public: 27 NoCopyNoMove() = default; 28 NoCopyNoMove(const NoCopyNoMove& other) = delete; 29 NoCopyNoMove& operator=(const NoCopyNoMove& other) = delete; 30 NoCopyNoMove(NoCopyNoMove&& other) = delete; 31 NoCopyNoMove& operator=(NoCopyNoMove&& other) = delete; 32 }; 33 34 //Temporary args to safely create OscilGenBuffers 35 struct OscilGenBuffersCreator 36 { 37 FFTwrapper* const fft; 38 const int oscilsize; 39 OscilGenBuffersCreator(FFTwrapper* fft, int oscilsize) : 40 fft(fft), oscilsize(oscilsize) {} 41 }; 42 43 //All temporary variables and buffers for OscilGen computations 44 class OscilGenBuffers : NoCopyNoMove 45 { 46 public: 47 OscilGenBuffers(OscilGenBuffersCreator creator); 48 ~OscilGenBuffers(); 49 void defaults(); 50 51 private: 52 // OscilGen needs to work with this data 53 // Anyone else should not touch these 54 friend class OscilGen; 55 56 const int oscilsize; 57 58 FFTfreqBuffer oscilFFTfreqs; 59 fft_t *pendingfreqs; 60 61 //This array stores some temporary data and it has OSCIL_SIZE elements 62 FFTsampleBuffer tmpsmps; 63 FFTfreqBuffer outoscilFFTfreqs; 64 FFTsampleBuffer cachedbasefunc; 65 bool cachedbasevalid; 66 67 FFTfreqBuffer basefuncFFTfreqs; //Base function frequencies 68 FFTfreqBuffer scratchFreqs; //Yet another tmp buffer 69 70 //Internal Data 71 unsigned char oldbasefunc, oldbasepar, oldhmagtype, 72 oldwaveshapingfunction, oldwaveshaping; 73 int oldfilterpars, oldsapars, oldbasefuncmodulation, 74 oldbasefuncmodulationpar1, oldbasefuncmodulationpar2, 75 oldbasefuncmodulationpar3, oldharmonicshift; 76 int oldmodulation, oldmodulationpar1, oldmodulationpar2, 77 oldmodulationpar3; 78 79 int oscilprepared; //1 if the oscil is prepared, 0 if it is not prepared and is need to call ::prepare() before ::get() 80 81 float hmag[MAX_AD_HARMONICS], hphase[MAX_AD_HARMONICS]; //the magnituides and the phases of the sine/nonsine harmonics 82 }; 83 84 class OscilGen:public Presets, NoCopyNoMove 85 { 86 public: 87 OscilGen(const SYNTH_T &synth, FFTwrapper *fft_, const Resonance *res_); 88 89 //You need to call this func if you need your own buffers for get() etc. 90 OscilGenBuffersCreator createOscilGenBuffers() const; 91 92 /**computes the full spectrum of oscil from harmonics,phases and basefunc*/ 93 void prepare(OscilGenBuffers& bfrs) const; 94 void prepare() { return prepare(myBuffers()); } 95 96 void prepare(OscilGenBuffers& bfrs, FFTfreqBuffer data) const; 97 98 /**do the antialiasing(cut off higher freqs.),apply randomness and do a IFFT*/ 99 //returns where should I start getting samples, used in block type randomness 100 short get(OscilGenBuffers& bfrs, float *smps, float freqHz, int resonance = 0) const; 101 short get(float *smps, float freqHz, int resonance = 0) { 102 return get(myBuffers(), smps, freqHz, resonance); 103 } 104 //if freqHz is smaller than 0, return the "un-randomized" sample for UI 105 106 void getbasefunction(OscilGenBuffers& bfrs, FFTsampleBuffer smps) const; 107 108 //called by UI 109 void getspectrum(int n, float *spc, int what); //what=0 pt. oscil,1 pt. basefunc 110 void getcurrentbasefunction(FFTsampleBuffer smps); 111 /**convert oscil to base function*/ 112 void useasbase(); 113 114 void paste(OscilGen &o); 115 void add2XML(XMLwrapper& xml) override; 116 void defaults(); 117 void getfromXML(XMLwrapper& xml); 118 119 void convert2sine(); 120 121 //Parameters 122 123 /** 124 * The hmag and hphase starts counting from 0, so the first harmonic(1) has the index 0, 125 * 2-nd harmonic has index 1, ..the 128 harminic has index 127 126 */ 127 unsigned char Phmag[MAX_AD_HARMONICS], Phphase[MAX_AD_HARMONICS]; //the MIDI parameters for mag. and phases 128 129 130 /**The Type of magnitude: 131 * 0 - Linear 132 * 1 - dB scale (-40) 133 * 2 - dB scale (-60) 134 * 3 - dB scale (-80) 135 * 4 - dB scale (-100)*/ 136 unsigned char Phmagtype; 137 138 unsigned char Pcurrentbasefunc; //The base function used - 0=sin, 1=... 139 unsigned char Pbasefuncpar; //the parameter of the base function 140 141 unsigned char Pbasefuncmodulation; //what modulation is applied to the basefunc 142 unsigned char Pbasefuncmodulationpar1, Pbasefuncmodulationpar2, 143 Pbasefuncmodulationpar3; //the parameter of the base function modulation 144 145 unsigned char Pwaveshaping, Pwaveshapingfunction; 146 unsigned char Pfiltertype, Pfilterpar1, Pfilterpar2; 147 bool Pfilterbeforews; 148 unsigned char Psatype, Psapar; //spectrum adjust 149 150 int Pharmonicshift; //how the harmonics are shifted 151 int Pharmonicshiftfirst; //if the harmonic shift is done before waveshaping and filter 152 153 unsigned char Pmodulation; //what modulation is applied to the oscil 154 unsigned char Pmodulationpar1, Pmodulationpar2, Pmodulationpar3; //the parameter of the parameters 155 156 /**Realtime parameters for ADnote*/ 157 158 /*the Randomness: 159 64=no randomness 160 63..0 - block type randomness - 0 is maximum 161 65..127 - each harmonic randomness - 127 is maximum*/ 162 unsigned char Prand; 163 unsigned char Pamprandpower, Pamprandtype; //amplitude randomness 164 unsigned char Padaptiveharmonics; //the adaptive harmonics status (off=0,on=1,etc..) 165 unsigned char Padaptiveharmonicsbasefreq; //the base frequency of the adaptive harmonic (30..3000Hz) 166 unsigned char Padaptiveharmonicspower; //the strength of the effect (0=off,100=full) 167 unsigned char Padaptiveharmonicspar; //the parameters in 2,3,4.. modes of adaptive harmonics 168 169 170 171 //makes a new random seed for Amplitude Randomness 172 //this should be called every note on event 173 void newrandseed(unsigned int randseed); 174 175 bool ADvsPAD; //!< true if it is used by PADsynth instead of ADsynth 176 177 static const rtosc::MergePorts ports; 178 static const rtosc::Ports non_realtime_ports; 179 static const rtosc::Ports realtime_ports; 180 181 /* Oscillator Frequencies - 182 * this is different than the harmonics set-up by the user, 183 * it may contain time-domain data if the antialiasing is turned off*/ 184 185 //Access m_myBuffers. Should be avoided. 186 OscilGenBuffers& myBuffers() { return m_myBuffers; } 187 188 private: 189 190 //This has the advantage that it is the "old", "stable" code, and that 191 //prepare can be re-used. The disadvantage is that, if multiple threads 192 //work on this variable in parallel, race conditions would be possible. 193 //So this might vanish, soon 194 OscilGenBuffers m_myBuffers; 195 196 FFTwrapper *fft; 197 //computes the basefunction and make the FFT; newbasefunc<0 = same basefunc 198 void changebasefunction(OscilGenBuffers& bfrs) const; 199 //Waveshaping 200 void waveshape(OscilGenBuffers& bfrs, FFTfreqBuffer freqs) const; 201 202 //Filter the oscillator accotding to Pfiltertype and Pfilterpar 203 void oscilfilter(fft_t *freqs) const; 204 205 //Adjust the spectrum 206 void spectrumadjust(fft_t *freqs) const; 207 208 //Shift the harmonics 209 void shiftharmonics(fft_t *freqs) const; 210 211 //Do the oscil modulation stuff 212 void modulation(OscilGenBuffers& bfrs, FFTfreqBuffer freqs) const; 213 214 float userfunc(OscilGenBuffers& bfrs, float x) const; 215 216 public: 217 //Check system for needed updates 218 bool needPrepare(OscilGenBuffers& bfrs) const; 219 bool needPrepare() { return needPrepare(myBuffers()); } 220 private: 221 222 //Do the adaptive harmonic stuff 223 void adaptiveharmonic(fft_t *f, float freq) const; 224 225 //Do the adaptive harmonic postprocessing (2n+1,2xS,2xA,etc..) 226 //this function is called even for the user interface 227 //this can be called for the sine and components, and for the spectrum 228 //(that's why the sine and cosine components should be processed with a separate call) 229 void adaptiveharmonicpostprocess(fft_t *f, int size) const; 230 231 const Resonance *res; 232 233 unsigned int randseed; 234 public: 235 const SYNTH_T &synth; 236 }; 237 238 typedef float filter_func_t(unsigned int, float, float); 239 filter_func_t *getFilter(unsigned char func); 240 typedef float base_func_t(float, float); 241 base_func_t *getBaseFunction(unsigned char func); 242 243 } 244 245 #endif