pull/955/merge
soyer 6 days ago committed by GitHub
commit d5e0c16e6e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 10
      .github/workflows/build.yml
  2. 97
      src/effect_mixer.hpp
  3. 33
      src/minidexed.cpp
  4. 73
      src/patches/0001-PluginFX-change-gain-at-zero-crossing.patch

@ -39,6 +39,11 @@ jobs:
wget -q https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz
tar xf gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz
# Patch Synth_Dexed PluginFX
- name: Patch Synth_Dexed
run: |
( cd Synth_Dexed ; patch -p1 < ../src/patches/0001-PluginFX-change-gain-at-zero-crossing.patch )
- name: Build for Raspberry Pi 5 (64-bit)
run: |
set -ex
@ -124,6 +129,11 @@ jobs:
wget -q https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-arm-none-eabi.tar.xz
tar xf gcc-arm-10.3-2021.07-x86_64-arm-none-eabi.tar.xz
# Patch Synth_Dexed PluginFX
- name: Patch Synth_Dexed
run: |
( cd Synth_Dexed ; patch -p1 < ../src/patches/0001-PluginFX-change-gain-at-zero-crossing.patch )
- name: Build for Raspberry Pi 2 (32-bit)
run: |
set -ex

@ -22,7 +22,10 @@ public:
{
buffer_length=len;
for (uint8_t i=0; i<NN; i++)
{
multiplier[i] = UNITY_GAIN;
multiplier_w[i] = UNITY_GAIN;
}
sumbufL=new float32_t[buffer_length];
arm_fill_f32(0.0f, sumbufL, len);
@ -52,7 +55,7 @@ public:
gain = MAX_GAIN;
else if (gain < MIN_GAIN)
gain = MIN_GAIN;
multiplier[channel] = powf(gain, 4); // see: https://www.dr-lex.be/info-stuff/volumecontrols.html#ideal2
multiplier_w[channel] = powf(gain, 4); // see: https://www.dr-lex.be/info-stuff/volumecontrols.html#ideal2
}
void gain(float32_t gain)
@ -63,7 +66,7 @@ public:
gain = MAX_GAIN;
else if (gain < MIN_GAIN)
gain = MIN_GAIN;
multiplier[i] = powf(gain, 4); // see: https://www.dr-lex.be/info-stuff/volumecontrols.html#ideal2
multiplier_w[i] = powf(gain, 4); // see: https://www.dr-lex.be/info-stuff/volumecontrols.html#ideal2
}
}
@ -79,6 +82,7 @@ public:
protected:
float32_t multiplier[NN];
float32_t multiplier_w[NN];
float32_t* sumbufL;
uint16_t buffer_length;
};
@ -92,6 +96,8 @@ public:
{
panorama[i][0] = UNITY_PANORAMA;
panorama[i][1] = UNITY_PANORAMA;
panorama_w[i][0] = UNITY_PANORAMA;
panorama_w[i][1] = UNITY_PANORAMA;
}
sumbufR=new float32_t[buffer_length];
@ -103,6 +109,26 @@ public:
delete [] sumbufR;
}
uint32_t find_zc_f32(const float32_t *pSrc, uint32_t blockSize)
{
const float32_t *pIn = pSrc;
uint32_t blkCnt = blockSize;
pIn++;
blkCnt--;
while (blkCnt > 0U)
{
if (*pIn >= 0 && *(pIn - 1) < 0)
return blockSize - blkCnt;
pIn++;
blkCnt--;
}
return blockSize;
}
void pan(uint8_t channel, float32_t pan)
{
if (channel >= NN) return;
@ -113,43 +139,38 @@ public:
pan = MIN_PANORAMA;
// From: https://stackoverflow.com/questions/67062207/how-to-pan-audio-sample-data-naturally
panorama[channel][0]=arm_sin_f32(mapfloat(pan, MIN_PANORAMA, MAX_PANORAMA, 0.0, M_PI/2.0));
panorama[channel][1]=arm_cos_f32(mapfloat(pan, MIN_PANORAMA, MAX_PANORAMA, 0.0, M_PI/2.0));
panorama_w[channel][0]=arm_cos_f32(mapfloat(pan, MIN_PANORAMA, MAX_PANORAMA, 0.0, M_PI/2.0));
panorama_w[channel][1]=arm_sin_f32(mapfloat(pan, MIN_PANORAMA, MAX_PANORAMA, 0.0, M_PI/2.0));
}
void doAddMix(uint8_t channel, float32_t* in)
{
float32_t tmp[buffer_length];
uint32_t zc;
assert(in);
// left
arm_scale_f32(in, panorama[channel][0], tmp, buffer_length);
if(multiplier[channel]!=UNITY_GAIN)
arm_scale_f32(tmp,multiplier[channel],tmp,buffer_length);
arm_add_f32(sumbufL, tmp, sumbufL, buffer_length);
// right
arm_scale_f32(in, panorama[channel][1], tmp, buffer_length);
if(multiplier[channel]!=UNITY_GAIN)
arm_scale_f32(tmp,multiplier[channel],tmp,buffer_length);
arm_add_f32(sumbufR, tmp, sumbufR, buffer_length);
}
void doAddMix(uint8_t channel, float32_t* inL, float32_t* inR)
{
float32_t tmp[buffer_length];
if ((panorama[channel][0] != panorama_w[channel][0] || multiplier[channel] != multiplier_w[channel]) &&
(zc = find_zc_f32(in, buffer_length)) != buffer_length)
{
arm_scale_f32(in, panorama[channel][0] * multiplier[channel], tmp, zc);
arm_scale_f32(in + zc, panorama_w[channel][0] * multiplier_w[channel], tmp + zc, buffer_length - zc);
arm_add_f32(sumbufL, tmp, sumbufL, buffer_length);
panorama[channel][0] = panorama_w[channel][0];
assert(inL);
assert(inR);
arm_scale_f32(in, panorama[channel][1] * multiplier[channel], tmp, zc);
arm_scale_f32(in + zc, panorama_w[channel][1] * multiplier_w[channel], tmp + zc, buffer_length - zc);
arm_add_f32(sumbufR, tmp, sumbufR, buffer_length);
panorama[channel][1] = panorama_w[channel][1];
// left
if(multiplier[channel]!=UNITY_GAIN)
arm_scale_f32(inL,multiplier[channel],tmp,buffer_length);
arm_add_f32(sumbufL, tmp, sumbufL, buffer_length);
// right
if(multiplier[channel]!=UNITY_GAIN)
arm_scale_f32(inR,multiplier[channel],tmp,buffer_length);
arm_add_f32(sumbufR, tmp, sumbufR, buffer_length);
multiplier[channel] = multiplier_w[channel];
}
else
{
arm_scale_f32(in, panorama[channel][0] * multiplier[channel], tmp, buffer_length);
arm_add_f32(sumbufL, tmp, sumbufL, buffer_length);
arm_scale_f32(in, panorama[channel][1] * multiplier[channel], tmp, buffer_length);
arm_add_f32(sumbufR, tmp, sumbufR, buffer_length);
}
}
void getMix(float32_t* bufferL, float32_t* bufferR)
@ -168,11 +189,27 @@ public:
arm_fill_f32(0.0f, sumbufR, buffer_length);
}
void getBuffers(float32_t (*buffers[2]))
{
buffers[0] = sumbufL;
buffers[1] = sumbufR;
}
void zeroFill()
{
if(sumbufL)
arm_fill_f32(0.0f, sumbufL, buffer_length);
if(sumbufR)
arm_fill_f32(0.0f, sumbufR, buffer_length);
}
protected:
using AudioMixer<NN>::sumbufL;
using AudioMixer<NN>::multiplier;
using AudioMixer<NN>::multiplier_w;
using AudioMixer<NN>::buffer_length;
float32_t panorama[NN][2];
float32_t panorama_w[NN][2];
float32_t* sumbufR;
};

@ -213,10 +213,6 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt,
m_pSoundDevice = new CHDMISoundBaseDevice (pInterrupt, pConfig->GetSampleRate (),
pConfig->GetChunkSize ());
// The channels are swapped by default in the HDMI sound driver.
// TODO: Remove this line, when this has been fixed in the driver.
m_bChannelsSwapped = !m_bChannelsSwapped;
#endif
}
else
@ -1406,34 +1402,35 @@ void CMiniDexed::ProcessSound (void)
if(nMasterVolume > 0.0)
{
// get the mix buffer of all TGs
float32_t (*SampleBuffer[2]);
tg_mixer->getBuffers(SampleBuffer);
tg_mixer->zeroFill();
for (uint8_t i = 0; i < m_nToneGenerators; i++)
{
tg_mixer->doAddMix(i,m_OutputLevel[i]);
reverb_send_mixer->doAddMix(i,m_OutputLevel[i]);
}
// END TG mixing
// BEGIN create SampleBuffer for holding audio data
float32_t SampleBuffer[2][nFrames];
// END create SampleBuffer for holding audio data
// get the mix of all TGs
tg_mixer->getMix(SampleBuffer[indexL], SampleBuffer[indexR]);
// BEGIN adding reverb
if (m_nParameter[ParameterReverbEnable])
{
float32_t ReverbBuffer[2][nFrames];
float32_t ReverbSendBuffer[2][nFrames];
arm_fill_f32(0.0f, ReverbBuffer[indexL], nFrames);
arm_fill_f32(0.0f, ReverbBuffer[indexR], nFrames);
arm_fill_f32(0.0f, ReverbSendBuffer[indexR], nFrames);
arm_fill_f32(0.0f, ReverbSendBuffer[indexL], nFrames);
float32_t (*ReverbSendBuffer[2]);
reverb_send_mixer->getBuffers(ReverbSendBuffer);
reverb_send_mixer->zeroFill();
for (uint8_t i = 0; i < m_nToneGenerators; i++)
{
reverb_send_mixer->doAddMix(i,m_OutputLevel[i]);
}
m_ReverbSpinLock.Acquire ();
reverb_send_mixer->getMix(ReverbSendBuffer[indexL], ReverbSendBuffer[indexR]);
reverb->doReverb(ReverbSendBuffer[indexL],ReverbSendBuffer[indexR],ReverbBuffer[indexL], ReverbBuffer[indexR],nFrames);
// scale down and add left reverb buffer by reverb level

@ -0,0 +1,73 @@
From 7daa07bd662d1894bc312b81c6b9e79260e7a66a Mon Sep 17 00:00:00 2001
From: Gergo Koteles <soyer@irl.hu>
Date: Fri, 11 Jul 2025 20:28:52 +0200
Subject: [PATCH] PluginFX change gain at zero crossing
---
src/PluginFx.cpp | 26 +++++++++++++++++++-------
src/PluginFx.h | 2 ++
2 files changed, 21 insertions(+), 7 deletions(-)
diff --git a/src/PluginFx.cpp b/src/PluginFx.cpp
index 7c3a1ab..2b7bb9b 100644
--- a/src/PluginFx.cpp
+++ b/src/PluginFx.cpp
@@ -56,6 +56,7 @@ PluginFx::PluginFx() {
Cutoff = 1.0;
Reso = 0.0;
Gain = 1.0;
+ aGain = 1.0;
}
void PluginFx::init(FRAC_NUM sr) {
@@ -117,16 +118,27 @@ void PluginFx::process(float *work, uint16_t sampleSize) {
dc_od = work[sampleSize - 1];
- // Gain
- if (Gain == 0.0)
- {
+ if (Gain != aGain) {
for (uint16_t i = 0; i < sampleSize; i++ )
- work[i] = 0.0;
+ {
+ if (i != 0 && work[i] >= 0 && work[i-1] <= 0)
+ aGain = Gain;
+ work[i] *= aGain;
+ }
}
- else if ( Gain != 1.0)
+ else
{
- for (uint16_t i = 0; i < sampleSize; i++ )
- work[i] *= Gain;
+ // Gain
+ if (aGain == 0.0)
+ {
+ for (uint16_t i = 0; i < sampleSize; i++ )
+ work[i] = 0.0;
+ }
+ else if ( aGain != 1.0)
+ {
+ for (uint16_t i = 0; i < sampleSize; i++ )
+ work[i] *= aGain;
+ }
}
// don't apply the LPF if the cutoff is to maximum
diff --git a/src/PluginFx.h b/src/PluginFx.h
index 090e241..c27ccc5 100644
--- a/src/PluginFx.h
+++ b/src/PluginFx.h
@@ -67,6 +67,8 @@ class PluginFx {
float Reso;
float Gain;
+ float aGain;
+
void init(FRAC_NUM sampleRate);
void process(float *work, uint16_t sampleSize);
float getGain(void);
--
2.50.1
Loading…
Cancel
Save