Added full implementation of plate reverb.

pull/59/head
Holger Wirtz 3 years ago
parent c0c62916bb
commit 2a20eb82a0
  1. 36
      src/effect_platervbstereo.cpp
  2. 8
      src/effect_platervbstereo.h
  3. 13
      src/minidexed.cpp
  4. 5
      src/minidexed.ini

@ -1,6 +1,6 @@
/* Stereo plate reverb for Teensy 4 /* Stereo plate reverb for Teensy 4
* *
* Adapted for use in MiniDexed (Holger Wirtz <wirtz@parasitstudio.de>) * Adapted for MiniDexed (Holger Wirtz <dcoredump@googlemail.com>)
* *
* Author: Piotr Zapart * Author: Piotr Zapart
* www.hexefx.com * www.hexefx.com
@ -33,6 +33,7 @@
#include <stdio.h> #include <stdio.h>
#include <cstdlib> #include <cstdlib>
#include <assert.h>
#include "effect_platervbstereo.h" #include "effect_platervbstereo.h"
#define INP_ALLP_COEFF (0.65f) // default input allpass coeff #define INP_ALLP_COEFF (0.65f) // default input allpass coeff
@ -151,11 +152,13 @@ AudioEffectPlateReverb::AudioEffectPlateReverb(float32_t samplerate)
lfo1_adder = (UINT32_MAX + 1)/(samplerate * LFO1_FREQ_HZ); lfo1_adder = (UINT32_MAX + 1)/(samplerate * LFO1_FREQ_HZ);
lfo2_phase_acc = 0; lfo2_phase_acc = 0;
lfo2_adder = (UINT32_MAX + 1)/(samplerate * LFO2_FREQ_HZ); lfo2_adder = (UINT32_MAX + 1)/(samplerate * LFO2_FREQ_HZ);
send_level = 0.0;
} }
// #define sat16(n, rshift) signed_saturate_rshift((n), 16, (rshift)) // #define sat16(n, rshift) signed_saturate_rshift((n), 16, (rshift))
void AudioEffectPlateReverb::doReverb(uint16_t len, int16_t inblock[][2], int16_t outblock[][2]) void AudioEffectPlateReverb::doReverb(uint16_t len, int16_t audioblock[][2])
{ {
int i; int i;
float32_t input, acc, temp1, temp2; float32_t input, acc, temp1, temp2;
@ -193,17 +196,11 @@ void AudioEffectPlateReverb::doReverb(uint16_t len, int16_t inblock[][2], int16_
cleanup_done = true; cleanup_done = true;
} }
if (!inblock && outblock)
memset(outblock,0,len*sizeof(int16_t)*2);
return; return;
} }
cleanup_done = false; cleanup_done = false;
// convert data to float32
//arm_q15_to_float((q15_t *)inblockL, input_blockL, len);
//arm_q15_to_float((q15_t *)inblockR, input_blockR, len);
rv_time = rv_time_k; rv_time = rv_time_k;
for (i=0; i < len; i++) for (i=0; i < len; i++)
@ -239,7 +236,8 @@ void AudioEffectPlateReverb::doReverb(uint16_t len, int16_t inblock[][2], int16_
y += (int64_t)y1 * idx; y += (int64_t)y1 * idx;
lfo2_out_cos = (int32_t) (y >> (32-8)); // 16bit output lfo2_out_cos = (int32_t) (y >> (32-8)); // 16bit output
input = (float32_t(inblock[i][0])/32768.0f) * input_attn; input = (float32_t(audioblock[i][0])/32767.0f) * input_attn;
// chained input allpasses, channel L // chained input allpasses, channel L
acc = in_allp1_bufL[in_allp1_idxL] + input * in_allp_k; acc = in_allp1_bufL[in_allp1_idxL] + input * in_allp_k;
in_allp1_bufL[in_allp1_idxL] = input - in_allp_k * acc; in_allp1_bufL[in_allp1_idxL] = input - in_allp_k * acc;
@ -261,7 +259,8 @@ void AudioEffectPlateReverb::doReverb(uint16_t len, int16_t inblock[][2], int16_
in_allp_out_L = acc; in_allp_out_L = acc;
if (++in_allp4_idxL >= sizeof(in_allp4_bufL)/sizeof(float32_t)) in_allp4_idxL = 0; if (++in_allp4_idxL >= sizeof(in_allp4_bufL)/sizeof(float32_t)) in_allp4_idxL = 0;
input = (float32_t(inblock[i][1])/32768.0f) * input_attn; input = (float32_t(audioblock[i][1])/32767.0f) * input_attn;
// chained input allpasses, channel R // chained input allpasses, channel R
acc = in_allp1_bufR[in_allp1_idxR] + input * in_allp_k; acc = in_allp1_bufR[in_allp1_idxR] + input * in_allp_k;
in_allp1_bufR[in_allp1_idxR] = input - in_allp_k * acc; in_allp1_bufR[in_allp1_idxR] = input - in_allp_k * acc;
@ -407,7 +406,13 @@ void AudioEffectPlateReverb::doReverb(uint16_t len, int16_t inblock[][2], int16_
temp1 = acc - master_lowpass_l; temp1 = acc - master_lowpass_l;
master_lowpass_l += temp1 * master_lowpass_f; master_lowpass_l += temp1 * master_lowpass_f;
outblock[i][0]=(int16_t)(master_lowpass_l * 32767.0f); //sat16(output * 30, 0); int32_t out = audioblock[i][0] + int16_t(master_lowpass_l * 32767.0f * send_level);
if(out > INT16_MAX)
audioblock[i][0] = INT16_MAX;
else if(out < INT16_MIN)
audioblock[i][0] = INT16_MIN;
else
audioblock[i][0] = out;
// Channel R // Channel R
#ifdef TAP1_MODULATED #ifdef TAP1_MODULATED
@ -450,6 +455,13 @@ void AudioEffectPlateReverb::doReverb(uint16_t len, int16_t inblock[][2], int16_
// Master lowpass filter // Master lowpass filter
temp1 = acc - master_lowpass_r; temp1 = acc - master_lowpass_r;
master_lowpass_r += temp1 * master_lowpass_f; master_lowpass_r += temp1 * master_lowpass_f;
outblock[i][1]=(int16_t)(master_lowpass_r * 32767.0f);
out = audioblock[i][1] + int16_t(master_lowpass_l * 32767.0f * send_level);
if(out > INT16_MAX)
audioblock[i][1] = INT16_MAX;
else if(out < INT16_MIN)
audioblock[i][1] = INT16_MIN;
else
audioblock[i][1] = out;
} }
} }

@ -89,7 +89,7 @@ class AudioEffectPlateReverb
{ {
public: public:
AudioEffectPlateReverb(float32_t samplerate); AudioEffectPlateReverb(float32_t samplerate);
void doReverb(uint16_t len, int16_t inblock[][2], int16_t outblock[][2]); void doReverb(uint16_t len, int16_t audioblock[][2]);
void size(float n) void size(float n)
{ {
@ -136,12 +136,18 @@ public:
//__enable_irq(); //__enable_irq();
} }
void send(float n)
{
send_level = constrain(n, 0.0f, 1.0f);
}
float32_t get_size(void) {return rv_time_k;} float32_t get_size(void) {return rv_time_k;}
bool get_bypass(void) {return bypass;} bool get_bypass(void) {return bypass;}
void set_bypass(bool state) {bypass = state;}; void set_bypass(bool state) {bypass = state;};
void tgl_bypass(void) {bypass ^=1;} void tgl_bypass(void) {bypass ^=1;}
private: private:
bool bypass = false; bool bypass = false;
float32_t send_level;
float32_t input_attn; float32_t input_attn;
float32_t in_allp_k; // input allpass coeff float32_t in_allp_k; // input allpass coeff

@ -112,10 +112,11 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt,
// BEGIN setup reverb // BEGIN setup reverb
reverb = new AudioEffectPlateReverb(pConfig->GetSampleRate()); reverb = new AudioEffectPlateReverb(pConfig->GetSampleRate());
reverb->size(0.7); reverb->size(0.7);
reverb->hidamp(0.8); reverb->hidamp(0.5);
reverb->lodamp(0.5); reverb->lodamp(0.5);
reverb->lowpass(0.3); reverb->lowpass(0.3);
reverb->diffusion(0.2); reverb->diffusion(0.2);
reverb->send(0.8);
// END setup reverb // END setup reverb
}; };
@ -558,6 +559,7 @@ void CMiniDexed::ProcessSound (void)
// now mix the output of all TGs // now mix the output of all TGs
int16_t SampleBuffer[nFrames][2]; int16_t SampleBuffer[nFrames][2];
assert (CConfig::ToneGenerators == 8); assert (CConfig::ToneGenerators == 8);
for (unsigned i = 0; i < nFrames; i++) for (unsigned i = 0; i < nFrames; i++)
{ {
@ -594,14 +596,7 @@ void CMiniDexed::ProcessSound (void)
} }
// BEGIN adding reverb // BEGIN adding reverb
int16_t ReverbBuffer[nFrames][2]; reverb->doReverb(nFrames,SampleBuffer);
reverb->doReverb(nFrames,SampleBuffer,ReverbBuffer);
for (unsigned i = 0; i < nFrames; i++)
{
SampleBuffer[i][0] = ReverbBuffer[i][0];
SampleBuffer[i][1] = ReverbBuffer[i][1];
}
// END adding reverb // END adding reverb
if (m_pSoundDevice->Write (SampleBuffer, sizeof SampleBuffer) != (int) sizeof SampleBuffer) if (m_pSoundDevice->Write (SampleBuffer, sizeof SampleBuffer) != (int) sizeof SampleBuffer)

@ -4,6 +4,7 @@
# Sound device # Sound device
SoundDevice=pwm SoundDevice=pwm
#SoundDevice=hdmi
SampleRate=48000 SampleRate=48000
#ChunkSize=256 #ChunkSize=256
DACI2CAddress=0 DACI2CAddress=0
@ -29,5 +30,5 @@ EncoderPinData=6
EncoderPinSwitch=26 EncoderPinSwitch=26
# Debug # Debug
MIDIDumpEnabled=1 MIDIDumpEnabled=0
ProfileEnabled=1 ProfileEnabled=0

Loading…
Cancel
Save