pull/955/merge
soyer 7 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 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 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) - name: Build for Raspberry Pi 5 (64-bit)
run: | run: |
set -ex 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 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 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) - name: Build for Raspberry Pi 2 (32-bit)
run: | run: |
set -ex set -ex

@ -22,7 +22,10 @@ public:
{ {
buffer_length=len; buffer_length=len;
for (uint8_t i=0; i<NN; i++) for (uint8_t i=0; i<NN; i++)
{
multiplier[i] = UNITY_GAIN; multiplier[i] = UNITY_GAIN;
multiplier_w[i] = UNITY_GAIN;
}
sumbufL=new float32_t[buffer_length]; sumbufL=new float32_t[buffer_length];
arm_fill_f32(0.0f, sumbufL, len); arm_fill_f32(0.0f, sumbufL, len);
@ -52,7 +55,7 @@ public:
gain = MAX_GAIN; gain = MAX_GAIN;
else if (gain < MIN_GAIN) else if (gain < MIN_GAIN)
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) void gain(float32_t gain)
@ -63,7 +66,7 @@ public:
gain = MAX_GAIN; gain = MAX_GAIN;
else if (gain < MIN_GAIN) else if (gain < MIN_GAIN)
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: protected:
float32_t multiplier[NN]; float32_t multiplier[NN];
float32_t multiplier_w[NN];
float32_t* sumbufL; float32_t* sumbufL;
uint16_t buffer_length; uint16_t buffer_length;
}; };
@ -92,6 +96,8 @@ public:
{ {
panorama[i][0] = UNITY_PANORAMA; panorama[i][0] = UNITY_PANORAMA;
panorama[i][1] = 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]; sumbufR=new float32_t[buffer_length];
@ -103,6 +109,26 @@ public:
delete [] sumbufR; 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) void pan(uint8_t channel, float32_t pan)
{ {
if (channel >= NN) return; if (channel >= NN) return;
@ -113,43 +139,38 @@ public:
pan = MIN_PANORAMA; pan = MIN_PANORAMA;
// From: https://stackoverflow.com/questions/67062207/how-to-pan-audio-sample-data-naturally // 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_w[channel][0]=arm_cos_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][1]=arm_sin_f32(mapfloat(pan, MIN_PANORAMA, MAX_PANORAMA, 0.0, M_PI/2.0));
} }
void doAddMix(uint8_t channel, float32_t* in) void doAddMix(uint8_t channel, float32_t* in)
{ {
float32_t tmp[buffer_length]; float32_t tmp[buffer_length];
uint32_t zc;
assert(in); assert(in);
// left if ((panorama[channel][0] != panorama_w[channel][0] || multiplier[channel] != multiplier_w[channel]) &&
arm_scale_f32(in, panorama[channel][0], tmp, buffer_length); (zc = find_zc_f32(in, buffer_length)) != buffer_length)
if(multiplier[channel]!=UNITY_GAIN) {
arm_scale_f32(tmp,multiplier[channel],tmp,buffer_length); arm_scale_f32(in, panorama[channel][0] * multiplier[channel], tmp, zc);
arm_add_f32(sumbufL, tmp, sumbufL, buffer_length); arm_scale_f32(in + zc, panorama_w[channel][0] * multiplier_w[channel], tmp + zc, buffer_length - zc);
// right arm_add_f32(sumbufL, tmp, sumbufL, buffer_length);
arm_scale_f32(in, panorama[channel][1], tmp, buffer_length); panorama[channel][0] = panorama_w[channel][0];
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];
assert(inL); arm_scale_f32(in, panorama[channel][1] * multiplier[channel], tmp, zc);
assert(inR); 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 multiplier[channel] = multiplier_w[channel];
if(multiplier[channel]!=UNITY_GAIN) }
arm_scale_f32(inL,multiplier[channel],tmp,buffer_length); else
arm_add_f32(sumbufL, tmp, sumbufL, buffer_length); {
// right arm_scale_f32(in, panorama[channel][0] * multiplier[channel], tmp, buffer_length);
if(multiplier[channel]!=UNITY_GAIN) arm_add_f32(sumbufL, tmp, sumbufL, buffer_length);
arm_scale_f32(inR,multiplier[channel],tmp,buffer_length); arm_scale_f32(in, panorama[channel][1] * multiplier[channel], tmp, buffer_length);
arm_add_f32(sumbufR, tmp, sumbufR, buffer_length); arm_add_f32(sumbufR, tmp, sumbufR, buffer_length);
}
} }
void getMix(float32_t* bufferL, float32_t* bufferR) void getMix(float32_t* bufferL, float32_t* bufferR)
@ -168,11 +189,27 @@ public:
arm_fill_f32(0.0f, sumbufR, buffer_length); 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: protected:
using AudioMixer<NN>::sumbufL; using AudioMixer<NN>::sumbufL;
using AudioMixer<NN>::multiplier; using AudioMixer<NN>::multiplier;
using AudioMixer<NN>::multiplier_w;
using AudioMixer<NN>::buffer_length; using AudioMixer<NN>::buffer_length;
float32_t panorama[NN][2]; float32_t panorama[NN][2];
float32_t panorama_w[NN][2];
float32_t* sumbufR; float32_t* sumbufR;
}; };

@ -213,10 +213,6 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt,
m_pSoundDevice = new CHDMISoundBaseDevice (pInterrupt, pConfig->GetSampleRate (), m_pSoundDevice = new CHDMISoundBaseDevice (pInterrupt, pConfig->GetSampleRate (),
pConfig->GetChunkSize ()); 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 #endif
} }
else else
@ -1406,34 +1402,35 @@ void CMiniDexed::ProcessSound (void)
if(nMasterVolume > 0.0) 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++) for (uint8_t i = 0; i < m_nToneGenerators; i++)
{ {
tg_mixer->doAddMix(i,m_OutputLevel[i]); tg_mixer->doAddMix(i,m_OutputLevel[i]);
reverb_send_mixer->doAddMix(i,m_OutputLevel[i]);
} }
// END TG mixing // 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 // BEGIN adding reverb
if (m_nParameter[ParameterReverbEnable]) if (m_nParameter[ParameterReverbEnable])
{ {
float32_t ReverbBuffer[2][nFrames]; float32_t ReverbBuffer[2][nFrames];
float32_t ReverbSendBuffer[2][nFrames];
arm_fill_f32(0.0f, ReverbBuffer[indexL], nFrames); float32_t (*ReverbSendBuffer[2]);
arm_fill_f32(0.0f, ReverbBuffer[indexR], nFrames); reverb_send_mixer->getBuffers(ReverbSendBuffer);
arm_fill_f32(0.0f, ReverbSendBuffer[indexR], nFrames);
arm_fill_f32(0.0f, ReverbSendBuffer[indexL], nFrames); reverb_send_mixer->zeroFill();
for (uint8_t i = 0; i < m_nToneGenerators; i++)
{
reverb_send_mixer->doAddMix(i,m_OutputLevel[i]);
}
m_ReverbSpinLock.Acquire (); m_ReverbSpinLock.Acquire ();
reverb_send_mixer->getMix(ReverbSendBuffer[indexL], ReverbSendBuffer[indexR]);
reverb->doReverb(ReverbSendBuffer[indexL],ReverbSendBuffer[indexR],ReverbBuffer[indexL], ReverbBuffer[indexR],nFrames); reverb->doReverb(ReverbSendBuffer[indexL],ReverbSendBuffer[indexR],ReverbBuffer[indexL], ReverbBuffer[indexR],nFrames);
// scale down and add left reverb buffer by reverb level // 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