23 #include "../../system/log.h"
24 #include "../../math/mathtools.h"
50 double sustain,
double release,
double hammer) :
104 if (mNumberOfKeys < 0 or mNumberOfKeys > 256)
105 {
LogW(
"Called init with an invalid number of keys = %d",
mNumberOfKeys);
return; }
116 for (
int i=0; i<datasize; i++)
162 if (numberOfKeys < 0 or numberOfKeys > 255)
164 LogW(
"Unreasonable number of keys = %d.",numberOfKeys);
231 const double frequency,
234 const bool waitforcomputation,
237 if (frequency <= 0 or volume <= 0 or
mNumberOfKeys == 0)
return;
241 double position = (20+(keynumber&0xff)) * 1.0 / (
mNumberOfKeys+40);
242 if (not stereo) position = 0.5;
252 if (frequency>0 and frequency<10)
255 and timeout++ < 1000) {
256 std::this_thread::sleep_for(std::chrono::milliseconds(1));
334 int64_t clock_timeout = 40*sampleRate;
337 if (channels<=0 or channels>2)
return false;
340 for (
size_t bufferIndex = channels - 1; bufferIndex < outputBuffer.size(); bufferIndex += channels) {
342 double left = 0, right = 0;
349 double y = tone.amplitude;
354 y += envelope.
attack/sampleRate;
355 if (envelope.
decay>0)
357 if (y >= 1) tone.stage++;
361 if (y >= envelope.
sustain) tone.stage+=2;
365 y *= (1-(1+y)*envelope.
decay/sampleRate);
366 if (y <= envelope.
sustain) tone.stage++;
370 if (tone.clock > clock_timeout) tone.stage=4;
373 y *= (1-envelope.
release/sampleRate);
381 if (tone.frequency > 10)
383 double t = 1+tone.clock*1.0/sampleRate;
384 int i =
static_cast<int64_t
>(
SineLength*tone.frequency*t);
385 int j =
static_cast<int64_t
>(
SineLength*tone.frequency*(t+tone.phaseshift));
391 if (envelope.
hammer)
if (tone.clock < hammerwavesize)
394 int phaseshifted = tone.clock +
static_cast<int>(tone.phaseshift * sampleRate);
395 if (phaseshifted < hammerwavesize)
399 double t = (1+tone.clock*1.0/sampleRate)*tone.frequency;
400 left += tone.leftamplitude * y * 0.3 *
402 right += tone.rightamplitude * y * 0.3 *
407 const double reverbamplitude = 0.2;
412 left += reverbamplitude * ( echo2 + echo3 );
413 right += reverbamplitude * ( echo1 + echo4 );
449 const Tone *snd(
nullptr);
451 for (
auto &ch :
mPlayingTones)
if (ch.keynumber==
id) { snd=&ch;
break; }
460 for (
auto &ch :
mPlayingTones)
if (ch.keynumber==
id) { snd=&ch;
break; }
481 for (
auto &ch :
mPlayingTones)
if ((ch.keynumber & 0xff)==
id) { ch.stage=4; released=
true; }
483 if (not released)
LogW(
"Release: Sound with id=%d does not exist.",
id);
526 else LogW (
"Cannot modify sustain level: id %d does not exist",
id);
int stage
1=attack 2=decay 3=sustain 4=release.
double sustain
Sustain level.
std::vector< PCMDataType > PacketType
Type definition of a PCM packet (vector of PCM values).
int_fast64_t clock
Running time in sample cycles.
double leftamplitude
Left stereo volume.
std::vector< Tone > mPlayingTones
Chord defined as a collection of tones.
bool isPlaying(const int id) const
Check whether a sound with given id is still playing.
int keynumber
Identification tag (negativ=sine)
const Tone * getSoundPointer(const int id) const
Get a pointer to the sound according to the given ID.
virtual void init(const int sampleRate, const int channels)
Initialize the PCM-Writer with given sample rate and channel number.
Envelope(double attack=0, double decay=0, double sustain=0, double release=0, double hammer=0)
Envelope::Envelope.
double rightamplitude
Right stereo volume.
std::vector< double > mReverbL
std::vector< FFTComplexType > FFTComplexVector
int mNumberOfKeys
Number of keys, passed in init()
WaveformGenerator mWaveformGenerator
void playSound(const int id, const double frequency, const double volume, const Envelope &env, const bool waitforcomputation=false, const bool stereo=true)
Function which plays a single note (sound)
FFTRealVector mHammerWaveRight
std::vector< double > mReverbR
Reverb.
Waveform mSineWave
Sine wave vector, computed in init().
static const std::vector< std::vector< int > > mHammerKnockFFT
Hammerknock Fourier data.
double decay
Subsequent decay rate.
Synthesizer()
Constructor, intitializes the member variables.
std::mutex mPlayingMutex
Mutex to protect access to the chord.
double phaseshift
Stereo phase shift.
double attack
Initial attack rate.
int mSampleRate
Sample rate.
std::complex< double > FFTComplexType
virtual bool generateAudioSignal(AudioBase::PacketType &outputPacket) overridefinal
Generate waveform.
void releaseSound(const int id)
Terminate a sound.
virtual void start()
Start the thread.
int mChannels
Number of channels.
const int_fast64_t SineLength
sine value buffer length.
void updateIntensity()
Update function to update intensity.
void setNumberOfKeys(int numberOfKeys)
Tell the synthesizer to change the total number of keys.
Envelope envelope
Dynamic properties of the tone.
double frequency
Fundamental frequency.
double hammer
Intensity of hammer noise.
void preCalculateWaveform(const int id, const Spectrum &spectrum)
Pre-calculate the PCM waveform of a sound.
void ModifySustainLevel(const int id, const double level)
Change the level (sustain level) of a constantly playing sound.
std::map< double, double > Spectrum
double release
Release rate.
virtual void init(int sampleRate, int channels) overridefinal
Initialize and start the synthesizer.
const double CutoffVolume
Fade-out volume cutoff.
Structure describing the envelope (dynamics) of a sound.
WaveformGenerator::Waveform waveform
Copy of the waveform.
FFTRealVector mHammerWaveLeft
Hammer noise, computed in init().
double amplitude
current envelope amplitude
void calculateFFT(const FFTRealVector &in, FFTComplexVector &out)
Foward FFT, mapping a real vector with size N to a complex one with size N/2+1.
Structure of a single tone.
Thread-safe implementation of fftw3.