mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 14:16:07 -06:00
99 lines
2.3 KiB
C++
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));
|
|
}
|