|
|
|
@ -1,8 +1,10 @@ |
|
|
|
|
/* synth_sin_cos_f32.h
|
|
|
|
|
* AudioSynthSineCosine_F32 |
|
|
|
|
*
|
|
|
|
|
* |
|
|
|
|
* Status: Checked for function and accuracy. 19 April 2020 |
|
|
|
|
* 10 March 2021 Corrected Interpolation equations. Bob L |
|
|
|
|
* 23 Feb 2022 Added "pure spectrum" filtering. RSL |
|
|
|
|
* This adds the function pureSpectrum(bool _setPure); // Default: false
|
|
|
|
|
* |
|
|
|
|
* Created: Bob Larkin 15 April 2020 |
|
|
|
|
* |
|
|
|
@ -19,19 +21,19 @@ |
|
|
|
|
* (-amplitude, amplitude) range. If these are at the default values, |
|
|
|
|
* called doSimple, the caluclation is faster. |
|
|
|
|
* For doSimple either true or false, the frequency can be changed |
|
|
|
|
* at will using the frequency() method.
|
|
|
|
|
*
|
|
|
|
|
* at will using the frequency() method. |
|
|
|
|
* |
|
|
|
|
* Defaults: |
|
|
|
|
* Frequency: 1000.0 Hz |
|
|
|
|
* Phase of Sine: 0.0 radians (0.0 deg) |
|
|
|
|
* Phase of Cosine: pi/2 radians (90.0 deg) ahead of Sine |
|
|
|
|
* Amplitude: -1.0 to 1.0 |
|
|
|
|
*
|
|
|
|
|
* |
|
|
|
|
* Time: T3.6 update() block of 128 with doSimple is 36 microseconds |
|
|
|
|
* Same using flexible doSimple=false is 49 microseconds |
|
|
|
|
* T4.0 update() block of 128 with doSimple is 16 microseconds |
|
|
|
|
* Same using flexible doSimple=false is 24 microseconds |
|
|
|
|
*
|
|
|
|
|
* |
|
|
|
|
* Copyright (c) 2020 Bob Larkin |
|
|
|
|
* |
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy |
|
|
|
@ -79,16 +81,47 @@ class AudioSynthSineCosine_F32 : public AudioStream_F32 { |
|
|
|
|
public: |
|
|
|
|
AudioSynthSineCosine_F32(void) : AudioStream_F32(0, NULL) { } //uses default AUDIO_SAMPLE_RATE from AudioStream.h
|
|
|
|
|
|
|
|
|
|
AudioSynthSineCosine_F32(const AudioSettings_F32 &settings) : AudioStream_F32(0, NULL) {
|
|
|
|
|
AudioSynthSineCosine_F32(const AudioSettings_F32 &settings) : AudioStream_F32(0, NULL) { |
|
|
|
|
setSampleRate_Hz(settings.sample_rate_Hz); |
|
|
|
|
setBlockLength(settings.audio_block_samples); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void frequency(float32_t fr) { // Frequency in Hz
|
|
|
|
|
freq = fr; |
|
|
|
|
if (freq < 0.0f) freq = 0.0f; |
|
|
|
|
else if (freq > sample_rate_Hz/2.0f) freq = sample_rate_Hz/2.0f; |
|
|
|
|
phaseIncrement = 512.0f * freq / sample_rate_Hz; |
|
|
|
|
|
|
|
|
|
// Find coeff for 2 stages of BPF to remove harmoncs
|
|
|
|
|
// Always compute these in case pureSpectrum is enabled later.
|
|
|
|
|
if(freq > 0.003f*sample_rate_Hz) |
|
|
|
|
{ |
|
|
|
|
float32_t q = 20.0f; |
|
|
|
|
float32_t w0 = freq * (2.0f * 3.141592654f / sample_rate_Hz); |
|
|
|
|
float32_t alpha = sin(w0) / (q * 2.0); |
|
|
|
|
float32_t scale = 1.0f / (1.0f + alpha); |
|
|
|
|
/* b0 */ coeff32[0] = alpha * scale; |
|
|
|
|
/* b1 */ coeff32[1] = 0; |
|
|
|
|
/* b2 */ coeff32[2] = (-alpha) * scale; |
|
|
|
|
/* a1 */ coeff32[3] = -(-2.0 * cos(w0)) * scale; |
|
|
|
|
/* a2 */ coeff32[4] = -(1.0 - alpha) * scale; |
|
|
|
|
/* b0 */ coeff32[5] = coeff32[0]; |
|
|
|
|
/* b1 */ coeff32[6] = coeff32[1]; |
|
|
|
|
/* b2 */ coeff32[7] = coeff32[2]; |
|
|
|
|
/* a1 */ coeff32[8] = coeff32[3]; |
|
|
|
|
/* a2 */ coeff32[9] = coeff32[4]; |
|
|
|
|
arm_biquad_cascade_df1_init_f32( &bq_instS, 2, coeff32, state32S ); |
|
|
|
|
arm_biquad_cascade_df1_init_f32( &bq_instC, 2, coeff32, state32C ); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
for(int ii=0; ii<10; ii++) // Coeff for BiQuad BPF
|
|
|
|
|
coeff32[ii] = 0.0; |
|
|
|
|
coeff32[0] = 1.0; // b0 = 1 for pass through
|
|
|
|
|
coeff32[5] = 1.0; |
|
|
|
|
arm_biquad_cascade_df1_init_f32( &bq_instS, 2, coeff32, state32S ); |
|
|
|
|
arm_biquad_cascade_df1_init_f32( &bq_instC, 2, coeff32, state32C ); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Externally, phase comes in the range (0,2*M_PI) keeping with C math functions
|
|
|
|
@ -102,7 +135,7 @@ public: |
|
|
|
|
doSimple = false; |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// phaseS_C_r is the number of radians that the cosine output leads the
|
|
|
|
|
// sine output. The default is M_PI_2 = pi/2 = 1.57079633 radians,
|
|
|
|
|
// corresponding to 90.00 degrees cosine leading sine.
|
|
|
|
@ -123,7 +156,7 @@ public: |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Speed up calculations by setting phaseS_C=90deg, amplitude=1
|
|
|
|
|
// Speed up calculations by setting phaseS_C=90deg, amplitude=1
|
|
|
|
|
// Note, s=true will override any setting of phaseS_C_r or amplitude.
|
|
|
|
|
void simple(bool s) { |
|
|
|
|
doSimple = s; |
|
|
|
@ -132,7 +165,7 @@ public: |
|
|
|
|
amplitude_pk = 1.0f; |
|
|
|
|
} |
|
|
|
|
return; |
|
|
|
|
}
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void setSampleRate_Hz(float32_t fs_Hz) { |
|
|
|
|
// Check freq range
|
|
|
|
@ -145,7 +178,9 @@ public: |
|
|
|
|
if(bl > 128) bl = 128; |
|
|
|
|
block_length = bl; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void pureSpectrum(bool _setPure) { doPureSpectrum = _setPure; } |
|
|
|
|
|
|
|
|
|
virtual void update(void); |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
@ -159,5 +194,11 @@ private: |
|
|
|
|
// if only freq() is used, the complexities of phase, phaseS_C,
|
|
|
|
|
// and amplitude are not used, speeding up the sin and cos:
|
|
|
|
|
bool doSimple = true; |
|
|
|
|
bool doPureSpectrum = false; // Adds bandpass filter (not normally needed)
|
|
|
|
|
float32_t coeff32[10]; // 2 biquad stages for filtering output shared S&C
|
|
|
|
|
float32_t state32S[8]; |
|
|
|
|
arm_biquad_casd_df1_inst_f32 bq_instS; // ARM DSP Math library filter instance.
|
|
|
|
|
float32_t state32C[8]; |
|
|
|
|
arm_biquad_casd_df1_inst_f32 bq_instC; // ARM DSP Math library filter instance.
|
|
|
|
|
}; |
|
|
|
|
#endif |
|
|
|
|