Skip to content

Commit 690a1a2

Browse files
author
Dr. Christian Nöding
committed
Improved ruggedness of dynamics against startup problems. Prevented DIVby0. 8-channel mixer is working with gate, EQ and compression.
1 parent 5e40e65 commit 690a1a2

3 files changed

Lines changed: 50 additions & 15 deletions

File tree

dsp/dsp1/src/audio.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ void audioProcessData(void) {
107107
// 30 FLOP per channel * 40 channels = 1,200 FLOP in total
108108

109109
float audioProcessedSample;
110+
float mainDebug;
110111
float mainLeft;
111112
float mainRight;
112113
float mainSub;
@@ -118,14 +119,15 @@ void audioProcessData(void) {
118119
// now iterate through all channels and all samples
119120
// 24 channels are the hard limit at the moment - on some occasions it will not be able to process all data until next buffer
120121
// so stay at 8 channels for now
121-
//for (int i_tdm = 0; i_tdm < TDM_INPUTS; i_tdm++) {
122122
for (int s = 0; s < SAMPLES_IN_BUFFER; s++) {
123123
bufferSampleIndex = (BUFFER_SIZE * audioBufferCounter) + (CHANNELS_PER_TDM * s); // (select correct buffer 0 or 1) + (sample-offset)
124124

125125
mainLeft = 0.0f;
126126
mainRight = 0.0f;
127127
mainSub = 0.0f;
128+
mainDebug = 0.0f;
128129

130+
//for (int i_tdm = 0; i_tdm < TDM_INPUTS; i_tdm++) {
129131
for (int i_tdm = 0; i_tdm < 1; i_tdm++) {
130132
bufferTdmIndex = bufferSampleIndex + (BUFFER_COUNT * BUFFER_SIZE * i_tdm);
131133

@@ -140,6 +142,7 @@ void audioProcessData(void) {
140142
// input -> Noisegate -> EQ1 -> EQ2 -> EQ3 -> EQ4 -> EQ5 -> Compressor -> output
141143

142144
audioProcessedSample = audioRxBuf[bufferReadIndex];
145+
mainDebug += (audioRxBuf[bufferReadIndex]); // direct-through signal on output 1
143146

144147
// process noisegate
145148
audioProcessedSample = fxProcessGate(audioProcessedSample, &dsp.dspChannel[dspCh].gate);
@@ -186,12 +189,14 @@ void audioProcessData(void) {
186189
// Ch25-32: UltraNet 9-16
187190
// Ch33-40: AUX 1-6 / MonitorL/R
188191

189-
// copy masterLeft to TDM0, ch0
190-
// copy masterRight to TDM0, ch1
191-
// copy masterSub to TDM0, ch2
192-
audioTxBuf[bufferSampleIndex] = mainLeft;
193-
audioTxBuf[bufferSampleIndex + 1] = mainRight;
194-
audioTxBuf[bufferSampleIndex + 2] = mainSub;
192+
// copy mainDebug to TDM0, ch0 for direct passthrough-test
193+
// copy mainLeft to TDM0, ch1
194+
// copy mainRight to TDM0, ch2
195+
// copy mainSub to TDM0, ch3
196+
audioTxBuf[bufferSampleIndex] = mainDebug;
197+
audioTxBuf[bufferSampleIndex + 1] = mainLeft;
198+
audioTxBuf[bufferSampleIndex + 2] = mainRight;
199+
audioTxBuf[bufferSampleIndex + 3] = mainSub;
195200
}
196201

197202
// increment buffer-counter for next call

dsp/dsp1/src/dsp1.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,18 @@ void delay(int i) {
7676
}
7777
}
7878

79+
void openx32Init(void) {
80+
// initialize the default samplerate with 48kHz
81+
// other samplerates up to 192kHz are possible with AD and DA converters
82+
dsp.samplerate = 48000;
83+
84+
// initialize states of dynamics
85+
for (int ch = 0; ch < MAX_CHAN; ch++) {
86+
dsp.dspChannel[ch].gate.state = GATE_CLOSED;
87+
dsp.dspChannel[ch].compressor.state = COMPRESSOR_IDLE;
88+
}
89+
}
90+
7991
void openx32Command(unsigned short classId, unsigned short channel, unsigned short index, unsigned short valueCount, void* values) {
8092
/*
8193
SPI ClassIds:
@@ -165,7 +177,7 @@ int main() {
165177
systemExternalMemoryInit();
166178
systemSruInit();
167179

168-
dsp.samplerate = 48000; // other samplerates up to 192kHz are possible with AD and DA converters
180+
openx32Init();
169181
spiInit();
170182
audioInit();
171183
systemSportInit();

dsp/dsp1/src/fx.c

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ float fxProcessGate(float input, sGate* gate) {
66
// calculate the gate-logic and online-parameters
77
switch (gate->state) {
88
case GATE_CLOSED:
9+
gate->gainSet = gate->value_gainmin;
910
// check if we have to open the gate
1011
if (!gate->closed) {
1112
gate->state = GATE_ATTACK;
@@ -39,6 +40,9 @@ float fxProcessGate(float input, sGate* gate) {
3940
gate->coeff = gate->value_coeff_release;
4041
gate->state = GATE_CLOSED;
4142
break;
43+
default:
44+
gate->state = GATE_CLOSED;
45+
break;
4246
}
4347

4448
// gainCurrent = (gainCurrent * coeff) + (gainSet - gainSet * coeff);
@@ -61,28 +65,39 @@ float fxProcessEq(float input, sPEQ* peq) {
6165
}
6266

6367
float fxProcessCompressor(float input, sCompressor* compressor) {
64-
compressor->active = (abs(input) > compressor->value_threshold);
68+
float input_abs = abs(input);
69+
70+
compressor->active = (input_abs > compressor->value_threshold);
6571

6672
// calculate the gate-logic and online-parameters
6773
switch (compressor->state) {
6874
case COMPRESSOR_IDLE:
75+
compressor->gainSet = 1.0f;
6976
// check if we have to open the gate
7077
if (compressor->active) {
7178
compressor->state = COMPRESSOR_ATTACK;
7279
}
7380
break;
7481
case COMPRESSOR_ATTACK:
75-
compressor->gainSet = (((abs(input) - compressor->value_threshold) / compressor->value_ratio) + compressor->value_threshold) / input;
82+
// overshoot = abs(sample) - threshold
83+
// output = (overshoot / ratio) + threshold
84+
// gainSet = output / abs(input)
85+
if ((input_abs > 0) && (compressor->value_ratio != 0)) {
86+
compressor->gainSet = (((input_abs - compressor->value_threshold) / compressor->value_ratio) + compressor->value_threshold) / input_abs;
87+
}
7688
compressor->coeff = compressor->value_coeff_attack;
7789
compressor->state = COMPRESSOR_ACTIVE;
7890
break;
7991
case COMPRESSOR_ACTIVE:
8092
if (compressor->active) {
8193
// check if we have to compress even more
82-
float newValue = (((abs(input) - compressor->value_threshold) / compressor->value_ratio) + compressor->value_threshold) / input;
83-
if (newValue < compressor->gainSet) {
84-
// compress even more
85-
compressor->gainSet = newValue;
94+
float newValue;
95+
if ((input_abs > 0) && (compressor->value_ratio != 0)) {
96+
newValue = (((input_abs - compressor->value_threshold) / compressor->value_ratio) + compressor->value_threshold) / input_abs;
97+
if (newValue < compressor->gainSet) {
98+
// compress even more
99+
compressor->gainSet = newValue;
100+
}
86101
}
87102
}else{
88103
compressor->holdCounter = compressor->value_hold_ticks;
@@ -107,10 +122,13 @@ float fxProcessCompressor(float input, sCompressor* compressor) {
107122
compressor->coeff = compressor->value_coeff_release;
108123
compressor->state = COMPRESSOR_IDLE;
109124
break;
125+
default:
126+
compressor->state = COMPRESSOR_IDLE;
127+
break;
110128
}
111129

112130
// gainCurrent = (gainCurrent * coeff) + gainSet - (gainSet * coeff);
113131
compressor->gainCurrent = (compressor->gainCurrent * compressor->coeff) + compressor->gainSet - (compressor->gainSet * compressor->coeff);
114132

115-
return (input * compressor->gainCurrent) * compressor->value_makeup;
133+
return input * compressor->gainCurrent * compressor->value_makeup;
116134
}

0 commit comments

Comments
 (0)