mirror of https://github.com/gfvalvo/ToneShift.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
207 lines
6.3 KiB
207 lines
6.3 KiB
#include <Audio.h>
|
|
#include "mod-delay-gain.h"
|
|
#include "NewEncoder.h"
|
|
|
|
void configureShift(void), setOutputMix(void);
|
|
|
|
const int8_t minToneShift = -50;
|
|
const int8_t maxToneShift = 50;
|
|
const uint8_t shiftEncoderPinA = 2;
|
|
const uint8_t shiftEncoderPinB = 3;
|
|
|
|
const int8_t minOutputMix = 0;
|
|
const int8_t maxOutputMix = 25;
|
|
const uint8_t mixEncoderPinA = 4;
|
|
const uint8_t mixEncoderPinB = 5;
|
|
|
|
const uint16_t overlap = 16; // Overlap between complementry delay ramps
|
|
const uint16_t rampLength = 128 + overlap;
|
|
const uint16_t waveformSize = 256;
|
|
const int32_t delayBufferLength = 4500;
|
|
|
|
int16_t rampDown[waveformSize], rampUp[waveformSize], window[waveformSize];
|
|
int16_t delayBuf1[delayBufferLength];
|
|
int16_t delayBuf2[delayBufferLength];
|
|
int16_t *currentRamp = rampDown;
|
|
float modFreq = 0.0, outputMix = 0.0;
|
|
|
|
NewEncoder toneShiftEncoder(shiftEncoderPinA, shiftEncoderPinB, minToneShift, maxToneShift, 0);
|
|
NewEncoder mixingEncoder(mixEncoderPinA, mixEncoderPinB, minOutputMix, maxOutputMix, 0);
|
|
|
|
AudioInputI2S i2sIn; //xy=82,429
|
|
AudioMixer4 inputGain; //xy=282,475
|
|
|
|
AudioSynthWaveform delaySweep1; //xy=261,323
|
|
AudioSynthWaveform envelope1; //xy=268,375
|
|
AudioSynthWaveform delaySweep2; //xy=289,539
|
|
AudioSynthWaveform envelope2; //xy=301,590
|
|
|
|
AudioEffectModDelayGain modulatedDelay1; //xy=511,329
|
|
AudioEffectModDelayGain modulatedDelay2; //xy=515,547
|
|
|
|
AudioMixer4 outputMixer; //xy=752,420
|
|
AudioOutputI2S i2sOut; //xy=973,422
|
|
AudioAnalyzeRMS outputLevel; //xy=989,475
|
|
|
|
AudioConnection patchCord1(i2sIn, 0, inputGain, 0);
|
|
AudioConnection patchCord2(inputGain, 0, outputMixer, 2);
|
|
|
|
AudioConnection patchCord5(inputGain, 0, modulatedDelay1, 0);
|
|
AudioConnection patchCord3(delaySweep1, 0, modulatedDelay1, 1);
|
|
AudioConnection patchCord4(envelope1, 0, modulatedDelay1, 2);
|
|
|
|
AudioConnection patchCord6(inputGain, 0, modulatedDelay2, 0);
|
|
AudioConnection patchCord7(delaySweep2, 0, modulatedDelay2, 1);
|
|
AudioConnection patchCord8(envelope2, 0, modulatedDelay2, 2);
|
|
|
|
AudioConnection patchCord9(modulatedDelay1, 0, outputMixer, 0);
|
|
AudioConnection patchCord10(modulatedDelay2, 0, outputMixer, 1);
|
|
|
|
AudioConnection patchCord11(outputMixer, 0, i2sOut, 0);
|
|
AudioConnection patchCord12(outputMixer, 0, i2sOut, 1);
|
|
AudioConnection patchCord13(outputMixer, outputLevel);
|
|
|
|
void setup() {
|
|
double decrement, increment, delayValue, windowValue;
|
|
uint16_t index1, temp1;
|
|
|
|
Serial.begin(115200);
|
|
delay(2000);
|
|
Serial.println("Starting");
|
|
|
|
if (!toneShiftEncoder.begin()) {
|
|
Serial.println(
|
|
F("Tone Shift Encoder failed to initialize. Check pin assignments and available interrupts. Aborting"));
|
|
while (1) {
|
|
}
|
|
}
|
|
|
|
if (!mixingEncoder.begin()) {
|
|
Serial.println(
|
|
F("Mixing Encoder failed to initialize. Check pin assignments and available interrupts. Aborting"));
|
|
while (1) {
|
|
}
|
|
}
|
|
|
|
AudioNoInterrupts();
|
|
AudioMemory(20);
|
|
|
|
// create the arrays to ramp delay value
|
|
decrement = (double) 32767.0 / (double) (rampLength - 1);
|
|
delayValue = 32767.0;
|
|
for (index1 = 0; index1 < rampLength; index1++) {
|
|
rampDown[index1] = (delayValue + 0.5 > 0) ? delayValue + 0.5 : 0;
|
|
rampUp[index1] = 32767 - rampDown[index1];
|
|
delayValue -= decrement;
|
|
}
|
|
//for (; index1 < 256; index1++) {
|
|
for (; index1 < waveformSize; index1++) {
|
|
rampDown[index1] = 0;
|
|
rampUp[index1] = 32767;
|
|
}
|
|
|
|
// create the amplitude window array
|
|
increment = 1.0 / (double) (overlap - 1);
|
|
windowValue = 0.0;
|
|
//for (index1 = 127; index1 < 256; index1++) {
|
|
for (index1 = 0; index1 < waveformSize; index1++) {
|
|
window[index1] = 0;
|
|
}
|
|
for (index1 = 0; index1 < overlap; index1++) {
|
|
temp1 = sqrt(windowValue) * 32767 + 0.5;
|
|
temp1 = (temp1 < 32768) ? temp1 : 32767;
|
|
window[index1] = temp1;
|
|
//window[127 + overlap - index1] = temp1;
|
|
window[waveformSize / 2 - 1 + overlap - index1] = temp1;
|
|
windowValue += increment;
|
|
}
|
|
//for (; index1 <= 127; index1++) {
|
|
for (; index1 < waveformSize / 2; index1++) {
|
|
window[index1] = 32767;
|
|
}
|
|
|
|
modulatedDelay1.setbuf(delayBufferLength, delayBuf1);
|
|
modulatedDelay2.setbuf(delayBufferLength, delayBuf2);
|
|
|
|
//outputMixer.gain(0, 1.0);
|
|
//outputMixer.gain(1, 1.0);
|
|
//outputMixer.gain(2, 0.0);
|
|
outputMixer.gain(3, 0.0);
|
|
setOutputMix();
|
|
|
|
inputGain.gain(0, 5.0);
|
|
inputGain.gain(1, 0.0);
|
|
inputGain.gain(2, 0.0);
|
|
inputGain.gain(3, 0.0);
|
|
|
|
configureShift();
|
|
}
|
|
|
|
void loop() {
|
|
static elapsedMillis fps;
|
|
static int16_t lastToneShiftDecoderPosition = -5000;
|
|
static int16_t lastMixDecoderPosition = -5000;
|
|
int16_t currentDecoderPosition;
|
|
|
|
if (fps > 24) {
|
|
if (outputLevel.available()) {
|
|
fps = 0;
|
|
int monoPeak = outputLevel.read() * 30.0;
|
|
Serial.print("|");
|
|
for (int cnt = 0; cnt < monoPeak; cnt++) {
|
|
Serial.print(">");
|
|
}
|
|
Serial.println();
|
|
}
|
|
}
|
|
|
|
currentDecoderPosition = toneShiftEncoder;
|
|
if (currentDecoderPosition != lastToneShiftDecoderPosition) {
|
|
lastToneShiftDecoderPosition = currentDecoderPosition;
|
|
Serial.print("New Tone Shift Position = ");
|
|
Serial.println(currentDecoderPosition);
|
|
if (currentDecoderPosition >= 0) {
|
|
modFreq = 5.0 * currentDecoderPosition / maxToneShift;
|
|
currentRamp = rampDown;
|
|
} else {
|
|
modFreq = 2.5 * currentDecoderPosition / minToneShift;
|
|
currentRamp = rampUp;
|
|
}
|
|
configureShift();
|
|
}
|
|
|
|
currentDecoderPosition = mixingEncoder;
|
|
if (currentDecoderPosition != lastMixDecoderPosition) {
|
|
lastMixDecoderPosition = currentDecoderPosition;
|
|
Serial.print("New Mix Position = ");
|
|
Serial.print(currentDecoderPosition);
|
|
outputMix = (float) currentDecoderPosition / (maxOutputMix - minOutputMix) + minOutputMix;
|
|
Serial.print(" ----> ");
|
|
Serial.println(outputMix);
|
|
setOutputMix();
|
|
}
|
|
}
|
|
|
|
void configureShift() {
|
|
AudioNoInterrupts();
|
|
|
|
delaySweep1.begin(1, modFreq, WAVEFORM_ARBITRARY);
|
|
delaySweep1.arbitraryWaveform(currentRamp, 100);
|
|
delaySweep2.begin(1, modFreq, WAVEFORM_ARBITRARY);
|
|
delaySweep2.arbitraryWaveform(currentRamp, 100);
|
|
delaySweep2.phase(180.0);
|
|
|
|
envelope1.begin(1, modFreq, WAVEFORM_ARBITRARY);
|
|
envelope1.arbitraryWaveform(window, 100);
|
|
envelope2.begin(1, modFreq, WAVEFORM_ARBITRARY);
|
|
envelope2.arbitraryWaveform(window, 100);
|
|
envelope2.phase(180.0);
|
|
|
|
AudioInterrupts();
|
|
}
|
|
|
|
void setOutputMix() {
|
|
outputMixer.gain(0, (1.0 - outputMix) / 2.0);
|
|
outputMixer.gain(1, (1.0 - outputMix) / 2.0);
|
|
outputMixer.gain(2, outputMix);
|
|
}
|
|
|