Skip to content

Commit

Permalink
Synth - added VoiceMixer
Browse files Browse the repository at this point in the history
  • Loading branch information
pio committed Dec 15, 2024
1 parent 9d3b0c0 commit b79b041
Show file tree
Hide file tree
Showing 8 changed files with 771 additions and 2 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ The effecs are ported from the main [floating point version of the library](http
### [Stereo Modulated Ping-Pong Delay](DelayStereo.md "Stereo Modulated Ping-Pong Delay")
### Stereo 12 stage Phaser

## Synth

### 8 channel voice mixer with stereo output and modulation inputs

---
Copyright 11.2024 by Piotr Zapart
www.hexefx.com
Expand Down
Binary file added gui/img/voicemixer_example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
92 changes: 91 additions & 1 deletion gui/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,9 @@ <h5 id="node-help-label">Keyboard Shortcuts <span style="float: right;"><a href=
{"type":"AudioEffectPlateReverb_i16","data":{"defaults":{"name":{"value":"new"}},"shortName":"PlateReveverb","inputs":"2","output":"2","category":"hexefx","color":"#E6E0F8","icon":"arrow-in.png","outputs":"2"}},
{"type":"AudioEffectSpringReverb_i16","data":{"defaults":{"name":{"value":"new"}},"shortName":"SpringReverb","inputs":"2","output":"2","category":"hexefx","color":"#E6E0F8","icon":"arrow-in.png","outputs":"2"}},
{"type":"AudioEffectReverbSc_i16","data":{"defaults":{"name":{"value":"new"}},"shortName":"Reverb_SC","inputs":"2","output":"2","category":"hexefx","color":"#E6E0F8","icon":"arrow-in.png","outputs":"2"}},
{"type":"AudioEffectDelayStereo_i16","data":{"defaults":{"name":{"value":"new"}},"shortName":"PP_delay","inputs":"2","output":"2","category":"hexefx","color":"#E6E0F8","icon":"arrow-in.png","outputs":"2"}}
{"type":"AudioEffectDelayStereo_i16","data":{"defaults":{"name":{"value":"new"}},"shortName":"PP_delay","inputs":"2","output":"2","category":"hexefx","color":"#E6E0F8","icon":"arrow-in.png","outputs":"2"}},

{"type":"AudioMixerSynth8ch_i16","data":{"defaults":{"name":{"value":"new"}},"shortName":"mixer8","inputs":"10","output":"2","category":"hexefx","color":"#E6E0F8","icon":"arrow-in.png","outputs":"2"}}


]}
Expand Down Expand Up @@ -6242,6 +6244,94 @@ <h3>Functions</h3>
</div>
</script>

<!-- ============ AudioMixerSynth8_i16 ========= -->
<script type="text/x-red" data-help-name="AudioMixerSynth8ch_i16">
<h3>Summary</h3>
<div class=tooltipinfo>
<p>Combine up to 8 audio signals together, each with adjustable gain
and panorama setting. Dedicated voice mixer block designed for polyphonic synths. </p>
<p>hexefx_audiolib_i16 extension.</p>
</div>
<h3>Audio Connections</h3>
<table class=doc align=center cellpadding=3>
<tr class=top><th>Port</th><th>Purpose</th></tr>
<tr class=odd><td align=center>In 0</td><td>Input signal #1</td></tr>
<tr class=odd><td align=center>In 1</td><td>Input signal #2</td></tr>
<tr class=odd><td align=center>In 2</td><td>Input signal #3</td></tr>
<tr class=odd><td align=center>In 3</td><td>Input signal #4</td></tr>
<tr class=odd><td align=center>In 4</td><td>Input signal #5</td></tr>
<tr class=odd><td align=center>In 5</td><td>Input signal #6</td></tr>
<tr class=odd><td align=center>In 6</td><td>Input signal #7</td></tr>
<tr class=odd><td align=center>In 7</td><td>Input signal #8</td></tr>
<tr class=odd><td align=center>In 8</td><td>Input volume modulation</td></tr>
<tr class=odd><td align=center>In 9</td><td>Input panorama modulation</td></tr>
<tr class=odd><td align=center>Out 0</td><td>Sum of all inputs Left</td></tr>
<tr class=odd><td align=center>Out 1</td><td>Sum of all inputs Right</td></tr>
</table>
<h3>Functions</h3>
<h4>Volume controls</h4>
<p class=func><span class=keyword>gain</span>(<strong>uint8_t </strong>channel, <strong>float32_t </strong>gain, <strong>float32_t </strong>modMult);</p>
<p class=desc>Adjust the channel volume level and it's modulation multiplier. "channel" must
be 0 to 7. "gain" may be any floating point number from 0 to 1.0.
"modMult" controls the volume modulation input which is mixed with the static gain setting ans has range from -1.0 (inverted phase) to 1.0.
</p>

<p class=func><span class=keyword>gain</span>(<strong>uint8_t </strong>channel, <strong>float32_t </strong>gain);</p>
<p class=desc>Adjust the channel volume level leaving the modulation multiplier intact. "channel" must
be 0 to 7. "gain" may be any floating point number from 0 to 1.0.</p>

<p class=func><span class=keyword>gainAll</span>(<strong>float32_t </strong>gain);</p>
<p class=desc>Set the channel volume level for all inputs at once. "gain" may be any floating point number from 0 to 1.0.</p>

<p class=func><span class=keyword>gainMod</span>(<strong>uint8_t </strong>channel, <strong>float32_t </strong>modMult);</p>
<p class=desc>Set the volume modulation multiplier for the chosen input channel. Works as "tremolo" depth control. The range is
from -1.0 to 1.0.</p>

<p class=func><span class=keyword>gainModAll</span>(<strong>float32_t </strong>modMult);</p>
<p class=desc>Set the volume modulation multiplier for all the input channels. Works as "tremolo" depth control. The range is
from -1.0 to 1.0.</p>

<h4>Panorama controls</h4>
<p class=func><span class=keyword>pan</span>(<strong>uint8_t </strong>channel, <strong>float32_t </strong>p);</p>
<p class=desc>Adjust the panorama setting for the chosen channel (0-7). Panorama range is 0.0 (left), through 0.5 (center) to
1.0 (right).</p>

<p class=func><span class=keyword>panAll</span>(<strong>float32_t </strong>p);</p>
<p class=desc>Adjust the panorama setting for all the input channels. Panorama range is 0.0 (left), through 0.5 (center) to
1.0 (right).</p>

<p class=func><span class=keyword>panMod</span>(<strong>uint8_t </strong>channel, <strong>float32_t </strong>modMult);</p>
<p class=desc>Set the panorama modulation multiplier for the chosen input channel. Works as "auto-pan" depth control. The range is
from -1.0 to 1.0.</p>

<p class=func><span class=keyword>panModAll</span>(<strong>float32_t </strong>modMult);</p>
<p class=desc>Set the panorama modulation multiplier for all the input channels. Works as "tremolo" depth control. The range is
from -1.0 to 1.0.</p>

<h4>Modulation inputs</h4>

<p class=func><span class=keyword>modEnable</span>(<strong>uint8_t </strong>channel, <strong>uint8_t </strong>mask);</p>
<p class=desc>Allows to switch between 4 modulation modes for the chosen channel: <strong>VOICEMIXER_MOD_OFF</strong>,
<strong>VOICEMIXER_MOD_VOL</strong>, <strong>VOICEMIXER_MOD_PAN</strong>, <strong>VOICEMIXER_MOD_VOL_PAN</strong>.
This setting overrides the corresponding multiplier values and should be used as a quick method to turn the modulation on/off
without affecting any parameter values.</p>

<p class=func><span class=keyword>modEnableAll</span>(<strong>uint8_t </strong>mask);</p>
<p class=desc>Does the same as the function above, but globally for all channels at once.</p>

<h3>Example</h3>
<img src="img/voicemixer_example.png" alt="Voicemixer example of use"/>
<h4>Gain/Pan mixing emulation</h4>
<a href="https://hexeguitar.github.io/p5js_projects/TeensySynth.html" target="__blank">CLICK HERE</a>

</script>
<script type="text/x-red" data-template-name="AudioMixerSynth8ch_i16">
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
</script>


</body>
</html>
19 changes: 19 additions & 0 deletions src/basic_DSPutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <Arduino.h>
#include <arm_math.h>
#include "utility/dspinst.h"

#define F32_TO_I32_NORM_FACTOR (2147483647) // which is 2^31-1
#define I32_TO_F32_NORM_FACTOR (4.656612875245797e-10) //which is 1/(2^31 - 1)
Expand All @@ -27,6 +28,24 @@ static inline void mix_pwr(float32_t mix, float32_t *wetMix, float32_t *dryMix)
*dryMix = D * D;
}

/**
* @brief Constant amplitude xfader curve based on equation y = x^2 * (3-2*x)
*
* @param mix mix setting in range 0-32767
* @param wetMix pointer to the wet channel gain
* @param dryMix pointer to the dry channel gain
*/
static inline void mix_const_ampl_i16(int16_t mix, int16_t *wetMix, int16_t *dryMix);
static inline void mix_const_ampl_i16(int16_t mix, int16_t *wetMix, int16_t *dryMix)
{
if (mix < 0) mix = 0;
uint32_t tmp32 = 3*32767 - (mix<<1);
uint32_t gw = signed_saturate_rshift(multiply_16bx16b(mix, mix), 16, 15);
gw = signed_saturate_rshift(gw*tmp32, 16, 15);
*wetMix = gw;
*dryMix = 32767 - gw;
}

void scale_float_to_int32range(const float32_t *pSrc, float32_t *pDst, uint32_t blockSize);

/**
Expand Down
2 changes: 2 additions & 0 deletions src/hexefx_audio_I16.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@
#include "effect_delaystereo_i16.h"
#include "effect_phaserStereo_i16.h"

#include "mixer_synth8ch_i16.h"

#endif // _HEXEFX_AUDIO_H
Loading

0 comments on commit b79b041

Please sign in to comment.