ultimatepp/examples/Synth/FM.cpp
cxl 376df036cd .examples
git-svn-id: svn://ultimatepp.org/upp/trunk@12698 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2019-01-22 09:33:28 +00:00

99 lines
2.3 KiB
C++

#include "Synth.h"
double ADSR::Evaluate(double t, double duration)
{
if(t < delay)
return 0;
if(t > duration) {
t -= duration;
if(t > release)
return 0;
return sustain * (release - t) / release;
}
t -= delay;
if(t < attack)
return t / attack;
t -= attack;
if(t < decay) {
return (sustain * t + decay - t) / decay;
}
return sustain;
}
struct FMSound : SoundGenerator, FMPatch {
virtual bool Get(float *data, int len);
double volume;
double duration;
double fc, fm1, fm2, fmf;
int ti = 0;
double noisedir = 0;
double noiseval = 0;
void SetVolume(double vol) { volume = vol; }
void Set(double volume, double frequency, double duration, const FMPatch& m);
FMSound(double volume, double frequency, double duration, const FMPatch& m) {
Set(volume, frequency, duration, m);
}
};
void FMSound::Set(double volume, double frequency, double duration, const FMPatch& m)
{
(FMPatch&)*this = m;
this->volume = volume;
this->duration = duration;
fc = frequency;
fm1 = fc * m1;
fm2 = fc * m2;
fmf = fc * mf;
}
bool FMSound::Get(float *b, int len)
{
bool plays = true;
double t;
for(int i = 0; i < len; i++) {
t = ti * (1.0 / 44200);
double pt = M_2PI * t;
static dword state = 1;
state ^= state << 13;
state ^= state >> 17;
state ^= state << 5;
double white = 2.0 / 4294967295.0 * state - 1;
/* noisedir = clamp(noisedir + 0.0001 * fc * white, -0.08, 0.08);
noiseval = noisedir;
if(noiseval > 1) {
noisedir = -abs(noisedir);
noiseval = 1;
}
if(noiseval < 0) {
noisedir = abs(noisedir);
noiseval = -1;
}
*b++ = tanh(noiseval);
*/
*b++ = float(volume * adsr.Evaluate(t, duration)
* sin(pt * fc + adsr1.Evaluate(t, duration)
* beta1
* sin(pt * fm1 + betan * white + betaf * adsrf.Evaluate(t, duration) * sin(pt * fmf))
+ adsr2.Evaluate(t, duration) * beta2 * sin(pt * fm2)));
ti++;
}
return t < duration + adsr.release;
}
int64 Play(double volume, double frequency, double duration, const FMPatch& patch)
{
return AddSound(new FMSound(volume, frequency, duration, patch));
}