Working on teensy 4.0 + PAJ7620
This commit is contained in:
parent
7f867b3018
commit
458b9eb891
|
@ -1,249 +0,0 @@
|
|||
/* Audio Library for Teensy 3.X
|
||||
* Copyright (c) 2018, Paul Stoffregen, paul@pjrc.com
|
||||
*
|
||||
* Development of this audio library was funded by PJRC.COM, LLC by sales of
|
||||
* Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop
|
||||
* open source software by purchasing Teensy or other PJRC products.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice, development funding notice, and this permission
|
||||
* notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(ADAFRUIT_TRELLIS_M4_EXPRESS)
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "synth_waveform.h"
|
||||
#include "arm_math.h"
|
||||
#include "utility/dspinst.h"
|
||||
|
||||
void AudioSynthWaveformModulated::update(void)
|
||||
{
|
||||
audio_block_t *block, *moddata, *shapedata;
|
||||
int16_t *bp, *end;
|
||||
int32_t val1, val2;
|
||||
int16_t magnitude15;
|
||||
uint32_t i, ph, index, index2, scale, priorphase;
|
||||
const uint32_t inc = phase_increment;
|
||||
|
||||
moddata = receiveReadOnly(0);
|
||||
shapedata = receiveReadOnly(1);
|
||||
|
||||
// Pre-compute the phase angle for every output sample of this update
|
||||
ph = phase_accumulator;
|
||||
priorphase = phasedata[AUDIO_BLOCK_SAMPLES-1];
|
||||
if (moddata && modulation_type == 0) {
|
||||
// Frequency Modulation
|
||||
bp = moddata->data;
|
||||
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
|
||||
int32_t n = (*bp++) * modulation_factor; // n is # of octaves to mod
|
||||
int32_t ipart = n >> 27; // 4 integer bits
|
||||
n &= 0x7FFFFFF; // 27 fractional bits
|
||||
#ifdef IMPROVE_EXPONENTIAL_ACCURACY
|
||||
// exp2 polynomial suggested by Stefan Stenzel on "music-dsp"
|
||||
// mail list, Wed, 3 Sep 2014 10:08:55 +0200
|
||||
int32_t x = n << 3;
|
||||
n = multiply_accumulate_32x32_rshift32_rounded(536870912, x, 1494202713);
|
||||
int32_t sq = multiply_32x32_rshift32_rounded(x, x);
|
||||
n = multiply_accumulate_32x32_rshift32_rounded(n, sq, 1934101615);
|
||||
n = n + (multiply_32x32_rshift32_rounded(sq,
|
||||
multiply_32x32_rshift32_rounded(x, 1358044250)) << 1);
|
||||
n = n << 1;
|
||||
#else
|
||||
// exp2 algorithm by Laurent de Soras
|
||||
// https://www.musicdsp.org/en/latest/Other/106-fast-exp2-approximation.html
|
||||
n = (n + 134217728) << 3;
|
||||
n = multiply_32x32_rshift32_rounded(n, n);
|
||||
n = multiply_32x32_rshift32_rounded(n, 715827883) << 3;
|
||||
n = n + 715827882;
|
||||
#endif
|
||||
uint32_t scale = n >> (14 - ipart);
|
||||
uint64_t phstep = (uint64_t)inc * scale;
|
||||
uint32_t phstep_msw = phstep >> 32;
|
||||
if (phstep_msw < 0x7FFE) {
|
||||
ph += phstep >> 16;
|
||||
} else {
|
||||
ph += 0x7FFE0000;
|
||||
}
|
||||
phasedata[i] = ph;
|
||||
}
|
||||
release(moddata);
|
||||
} else if (moddata) {
|
||||
// Phase Modulation
|
||||
bp = moddata->data;
|
||||
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
|
||||
// more than +/- 180 deg shift by 32 bit overflow of "n"
|
||||
uint32_t n = (uint16_t)(*bp++) * modulation_factor;
|
||||
phasedata[i] = ph + n;
|
||||
ph += inc;
|
||||
}
|
||||
release(moddata);
|
||||
} else {
|
||||
// No Modulation Input
|
||||
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
|
||||
phasedata[i] = ph;
|
||||
ph += inc;
|
||||
}
|
||||
}
|
||||
phase_accumulator = ph;
|
||||
|
||||
// If the amplitude is zero, no output, but phase still increments properly
|
||||
if (magnitude == 0) {
|
||||
if (shapedata) release(shapedata);
|
||||
return;
|
||||
}
|
||||
block = allocate();
|
||||
if (!block) {
|
||||
if (shapedata) release(shapedata);
|
||||
return;
|
||||
}
|
||||
bp = block->data;
|
||||
|
||||
// Now generate the output samples using the pre-computed phase angles
|
||||
switch(tone_type) {
|
||||
case WAVEFORM_SINE:
|
||||
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
|
||||
ph = phasedata[i];
|
||||
index = ph >> 24;
|
||||
val1 = AudioWaveformSine[index];
|
||||
val2 = AudioWaveformSine[index+1];
|
||||
scale = (ph >> 8) & 0xFFFF;
|
||||
val2 *= scale;
|
||||
val1 *= 0x10000 - scale;
|
||||
*bp++ = multiply_32x32_rshift32(val1 + val2, magnitude);
|
||||
}
|
||||
break;
|
||||
|
||||
case WAVEFORM_ARBITRARY:
|
||||
if (!arbdata) {
|
||||
release(block);
|
||||
if (shapedata) release(shapedata);
|
||||
return;
|
||||
}
|
||||
// len = 256
|
||||
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
|
||||
ph = phasedata[i];
|
||||
index = ph >> 24;
|
||||
index2 = index + 1;
|
||||
if (index2 >= 256) index2 = 0;
|
||||
val1 = *(arbdata + index);
|
||||
val2 = *(arbdata + index2);
|
||||
scale = (ph >> 8) & 0xFFFF;
|
||||
val2 *= scale;
|
||||
val1 *= 0x10000 - scale;
|
||||
*bp++ = multiply_32x32_rshift32(val1 + val2, magnitude);
|
||||
}
|
||||
break;
|
||||
|
||||
case WAVEFORM_PULSE:
|
||||
if (shapedata) {
|
||||
magnitude15 = signed_saturate_rshift(magnitude, 16, 1);
|
||||
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
|
||||
uint32_t width = ((shapedata->data[i] + 0x8000) & 0xFFFF) << 16;
|
||||
if (phasedata[i] < width) {
|
||||
*bp++ = magnitude15;
|
||||
} else {
|
||||
*bp++ = -magnitude15;
|
||||
}
|
||||
}
|
||||
break;
|
||||
} // else fall through to orginary square without shape modulation
|
||||
|
||||
case WAVEFORM_SQUARE:
|
||||
magnitude15 = signed_saturate_rshift(magnitude, 16, 1);
|
||||
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
|
||||
if (phasedata[i] & 0x80000000) {
|
||||
*bp++ = -magnitude15;
|
||||
} else {
|
||||
*bp++ = magnitude15;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WAVEFORM_SAWTOOTH:
|
||||
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
|
||||
*bp++ = signed_multiply_32x16t(magnitude, phasedata[i]);
|
||||
}
|
||||
break;
|
||||
|
||||
case WAVEFORM_SAWTOOTH_REVERSE:
|
||||
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
|
||||
*bp++ = signed_multiply_32x16t(0xFFFFFFFFu - magnitude, phasedata[i]);
|
||||
}
|
||||
break;
|
||||
|
||||
case WAVEFORM_TRIANGLE_VARIABLE:
|
||||
if (shapedata) {
|
||||
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
|
||||
uint32_t width = (shapedata->data[i] + 0x8000) & 0xFFFF;
|
||||
uint32_t rise = 0xFFFFFFFF / width;
|
||||
uint32_t fall = 0xFFFFFFFF / (0xFFFF - width);
|
||||
uint32_t halfwidth = width << 15;
|
||||
uint32_t n;
|
||||
ph = phasedata[i];
|
||||
if (ph < halfwidth) {
|
||||
n = (ph >> 16) * rise;
|
||||
*bp++ = ((n >> 16) * magnitude) >> 16;
|
||||
} else if (ph < 0xFFFFFFFF - halfwidth) {
|
||||
n = 0x7FFFFFFF - (((ph - halfwidth) >> 16) * fall);
|
||||
*bp++ = (((int32_t)n >> 16) * magnitude) >> 16;
|
||||
} else {
|
||||
n = ((ph + halfwidth) >> 16) * rise + 0x80000000;
|
||||
*bp++ = (((int32_t)n >> 16) * magnitude) >> 16;
|
||||
}
|
||||
ph += inc;
|
||||
}
|
||||
break;
|
||||
} // else fall through to orginary triangle without shape modulation
|
||||
|
||||
case WAVEFORM_TRIANGLE:
|
||||
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
|
||||
ph = phasedata[i];
|
||||
uint32_t phtop = ph >> 30;
|
||||
if (phtop == 1 || phtop == 2) {
|
||||
*bp++ = ((0xFFFF - (ph >> 15)) * magnitude) >> 16;
|
||||
} else {
|
||||
*bp++ = (((int32_t)ph >> 15) * magnitude) >> 16;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WAVEFORM_SAMPLE_HOLD:
|
||||
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
|
||||
ph = phasedata[i];
|
||||
if (ph < priorphase) { // does not work for phase modulation
|
||||
sample = random(magnitude) - (magnitude >> 1);
|
||||
}
|
||||
priorphase = ph;
|
||||
*bp++ = sample;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (tone_offset) {
|
||||
bp = block->data;
|
||||
end = bp + AUDIO_BLOCK_SAMPLES;
|
||||
do {
|
||||
val1 = *bp;
|
||||
*bp++ = signed_saturate_rshift(val1 + tone_offset, 16, 0);
|
||||
} while (bp < end);
|
||||
}
|
||||
if (shapedata) release(shapedata);
|
||||
transmit(block, 0);
|
||||
release(block);
|
||||
}
|
||||
|
||||
#endif
|
121
synth_waveform.h
121
synth_waveform.h
|
@ -1,121 +0,0 @@
|
|||
/** Backport modulated waveform to Adafruit fork
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/* Audio Library for Teensy 3.X
|
||||
* Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com
|
||||
*
|
||||
* Development of this audio library was funded by PJRC.COM, LLC by sales of
|
||||
* Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop
|
||||
* open source software by purchasing Teensy or other PJRC products.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice, development funding notice, and this permission
|
||||
* notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(ADAFRUIT_TRELLIS_M4_EXPRESS)
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Audio.h>
|
||||
#include "AudioStream.h"
|
||||
#include "arm_math.h"
|
||||
|
||||
#define WAVEFORM_TRIANGLE_VARIABLE 8
|
||||
|
||||
class AudioSynthWaveformModulated : public AudioStream
|
||||
{
|
||||
public:
|
||||
AudioSynthWaveformModulated(void) : AudioStream(2, inputQueueArray),
|
||||
phase_accumulator(0), phase_increment(0), modulation_factor(32768),
|
||||
magnitude(0), arbdata(NULL), sample(0), tone_offset(0),
|
||||
tone_type(WAVEFORM_SINE), modulation_type(0) {
|
||||
}
|
||||
|
||||
void frequency(float freq) {
|
||||
if (freq < 0.0) {
|
||||
freq = 0.0;
|
||||
} else if (freq > AUDIO_SAMPLE_RATE_EXACT / 2) {
|
||||
freq = AUDIO_SAMPLE_RATE_EXACT / 2;
|
||||
}
|
||||
phase_increment = freq * (4294967296.0 / AUDIO_SAMPLE_RATE_EXACT);
|
||||
if (phase_increment > 0x7FFE0000u) phase_increment = 0x7FFE0000;
|
||||
}
|
||||
void amplitude(float n) { // 0 to 1.0
|
||||
if (n < 0) {
|
||||
n = 0;
|
||||
} else if (n > 1.0) {
|
||||
n = 1.0;
|
||||
}
|
||||
magnitude = n * 65536.0;
|
||||
}
|
||||
void offset(float n) {
|
||||
if (n < -1.0) {
|
||||
n = -1.0;
|
||||
} else if (n > 1.0) {
|
||||
n = 1.0;
|
||||
}
|
||||
tone_offset = n * 32767.0;
|
||||
}
|
||||
void begin(short t_type) {
|
||||
tone_type = t_type;
|
||||
}
|
||||
void begin(float t_amp, float t_freq, short t_type) {
|
||||
amplitude(t_amp);
|
||||
frequency(t_freq);
|
||||
tone_type = t_type;
|
||||
}
|
||||
void arbitraryWaveform(const int16_t *data, float maxFreq) {
|
||||
arbdata = data;
|
||||
}
|
||||
void frequencyModulation(float octaves) {
|
||||
if (octaves > 12.0) {
|
||||
octaves = 12.0;
|
||||
} else if (octaves < 0.1) {
|
||||
octaves = 0.1;
|
||||
}
|
||||
modulation_factor = octaves * 4096.0;
|
||||
modulation_type = 0;
|
||||
}
|
||||
void phaseModulation(float degrees) {
|
||||
if (degrees > 9000.0) {
|
||||
degrees = 9000.0;
|
||||
} else if (degrees < 30.0) {
|
||||
degrees = 30.0;
|
||||
}
|
||||
modulation_factor = degrees * (65536.0 / 180.0);
|
||||
modulation_type = 1;
|
||||
}
|
||||
virtual void update(void);
|
||||
|
||||
private:
|
||||
audio_block_t *inputQueueArray[2];
|
||||
uint32_t phase_accumulator;
|
||||
uint32_t phase_increment;
|
||||
uint32_t modulation_factor;
|
||||
int32_t magnitude;
|
||||
const int16_t *arbdata;
|
||||
uint32_t phasedata[AUDIO_BLOCK_SAMPLES];
|
||||
int16_t sample; // for WAVEFORM_SAMPLE_HOLD
|
||||
int16_t tone_offset;
|
||||
uint8_t tone_type;
|
||||
uint8_t modulation_type;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
163
uilleann.ino
163
uilleann.ino
|
@ -1,16 +1,17 @@
|
|||
#include <Audio.h>
|
||||
#include <Wire.h>
|
||||
#include <Adafruit_NeoTrellisM4.h>
|
||||
#include <SFE_MicroOLED.h>
|
||||
#include <Adafruit_GFX.h>
|
||||
#include <Adafruit_SSD1306.h>
|
||||
#include <SparkFun_Qwiic_Button.h>
|
||||
#include <Adafruit_MPR121.h>
|
||||
#include <paj7620.h>
|
||||
#include "synth.h"
|
||||
#include "patches.h"
|
||||
#include "notes.h"
|
||||
#include "fingering.h"
|
||||
|
||||
#define DRONES
|
||||
#define DEBUG
|
||||
#define KNEE_OFFSET 0
|
||||
#define KEY_OFFSET 2
|
||||
|
||||
FMVoice Chanter;
|
||||
|
@ -22,17 +23,15 @@ AudioMixer4 mixDrones;
|
|||
AudioMixer4 mixRegulators;
|
||||
AudioMixer4 mixL;
|
||||
AudioMixer4 mixR;
|
||||
AudioOutputAnalogStereo dacs1;
|
||||
|
||||
#ifdef DEBUG
|
||||
AudioSynthNoiseWhite debug;
|
||||
#endif
|
||||
AudioOutputI2S out1;
|
||||
AudioSynthNoiseWhite noise;
|
||||
|
||||
AudioConnection FMVoicePatchCords[] = {
|
||||
#ifdef DEBUG
|
||||
{debug, 0, mixL, 3},
|
||||
{debug, 0, mixR, 3},
|
||||
#endif
|
||||
//{0, 0, 0, 0}, // For some reason, the first one is ignored
|
||||
|
||||
{noise, 0, mixDrones, 3},
|
||||
{noise, 0, mixL, 3},
|
||||
{noise, 0, mixR, 3},
|
||||
|
||||
{Chanter.outputMixer, 0, biquad1, 0},
|
||||
{biquad1, 0, mixL, 0},
|
||||
|
@ -50,56 +49,71 @@ AudioConnection FMVoicePatchCords[] = {
|
|||
{mixRegulators, 0, mixL, 2},
|
||||
{mixRegulators, 0, mixR, 2},
|
||||
|
||||
{mixL, 0, dacs1, 0},
|
||||
{mixR, 0, dacs1, 1},
|
||||
{mixL, 0, out1, 0},
|
||||
{mixR, 0, out1, 1},
|
||||
|
||||
FMVoiceWiring(Chanter),
|
||||
FMVoiceWiring(Drones[0]),
|
||||
FMVoiceWiring(Drones[1]),
|
||||
FMVoiceWiring(Drones[2]),
|
||||
FMVoiceWiring(Drones[3]),
|
||||
FMVoiceWiring(Regulators[0]),
|
||||
FMVoiceWiring(Regulators[1]),
|
||||
FMVoiceWiring(Regulators[2]),
|
||||
FMVoiceWiring(Regulators[3]),
|
||||
};
|
||||
|
||||
int currentPatch = 0;
|
||||
|
||||
Adafruit_MPR121 cap = Adafruit_MPR121();
|
||||
Adafruit_NeoTrellisM4 trellis = Adafruit_NeoTrellisM4();
|
||||
MicroOLED oled(9, 1);
|
||||
Adafruit_SSD1306 display(128, 32, &Wire, -1);
|
||||
QwiicButton bag;
|
||||
bool use_bag;
|
||||
|
||||
void blink(bool forever) {
|
||||
for (;;) {
|
||||
digitalWrite(LED_BUILTIN, true);
|
||||
delay(200);
|
||||
digitalWrite(LED_BUILTIN, false);
|
||||
delay(200);
|
||||
if (! forever) break;
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
setupJustPitches(NOTE_D4, PITCH_D4);
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
digitalWrite(LED_BUILTIN, true);
|
||||
|
||||
setupJustPitches(NOTE_D4, PITCH_D4);
|
||||
|
||||
// Wire.begin needs a moment
|
||||
delay(100);
|
||||
Wire.begin();
|
||||
|
||||
// Initialize OLED display
|
||||
oled.begin();
|
||||
oled.clear(ALL);
|
||||
// Initialize gesture/proximity sensor
|
||||
if (paj7620Init()) {
|
||||
// XXX: Error handling
|
||||
}
|
||||
|
||||
// Initialize display display
|
||||
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3c)) {
|
||||
blink(true);
|
||||
}
|
||||
display.clearDisplay();
|
||||
display.setTextSize(1);
|
||||
display.setTextColor(SSD1306_WHITE);
|
||||
display.print("Starting");
|
||||
display.display();
|
||||
|
||||
// Initialize bag
|
||||
bag.begin();
|
||||
|
||||
// Initialize the Trellis
|
||||
trellis.begin();
|
||||
use_bag = bag.isConnected();
|
||||
|
||||
// Initialize touch sensor
|
||||
bool blink = true;
|
||||
while (!cap.begin(0x5A)) {
|
||||
oled.clear(PAGE);
|
||||
oled.setCursor(0, 0);
|
||||
oled.print("No Pipe?");
|
||||
oled.display();
|
||||
|
||||
trellis.setPixelColor(0, blink?0xff6666:0);
|
||||
blink = !blink;
|
||||
delay(200);
|
||||
display.clearDisplay();
|
||||
display.setCursor(0, 0);
|
||||
display.print("Pipe?");
|
||||
display.display();
|
||||
blink(false);
|
||||
}
|
||||
|
||||
// Set aside some memory for the audio library
|
||||
|
@ -125,17 +139,12 @@ void setup() {
|
|||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
debug.amplitude(0.1);
|
||||
noise.amplitude(0.1);
|
||||
mixL.gain(3, 0.1);
|
||||
mixR.gain(3, 0.1);
|
||||
#endif
|
||||
}
|
||||
|
||||
#define BUTTON_UP 0
|
||||
#define BUTTON_DOWN 8
|
||||
#define BUTTON_PITCH 24
|
||||
#define BUTTON_VOLUME 25
|
||||
|
||||
#define INIT_PITCH_ADJUST 0
|
||||
#define INIT_GAIN 0.7
|
||||
#define INIT_PATCH 0
|
||||
|
@ -162,7 +171,6 @@ void updateTunables(uint8_t buttons, int note) {
|
|||
|
||||
float adj = pow(2, pitchAdjust / 32768.0);
|
||||
setupJustPitches(NOTE_D4, PITCH_D4*adj);
|
||||
trellis.setPixelColor(BUTTON_PITCH, trellis.ColorHSV(uint16_t(pitchAdjust), 255, 80));
|
||||
|
||||
if (!note || (note == NOTE_G4)) {
|
||||
// Volume adjust if playing G
|
||||
|
@ -178,20 +186,14 @@ void updateTunables(uint8_t buttons, int note) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<3; i++) {
|
||||
mixL.gain(i, chanterGain);
|
||||
mixR.gain(i, chanterGain);
|
||||
}
|
||||
trellis.setPixelColor(BUTTON_VOLUME, trellis.ColorHSV(uint16_t(chanterGain * 65535), 255, 80));
|
||||
|
||||
if (!note || (note == NOTE_CS5)) {
|
||||
if (buttons == 3) {
|
||||
patch = INIT_PATCH;
|
||||
} else if (trellis.justPressed(BUTTON_DOWN)) {
|
||||
patch -= 1;
|
||||
} else if (trellis.justPressed(BUTTON_UP)) {
|
||||
patch += 1;
|
||||
}
|
||||
|
||||
// wrap
|
||||
|
@ -201,14 +203,13 @@ void updateTunables(uint8_t buttons, int note) {
|
|||
FMPatch *p = &Bank[patch];
|
||||
FMVoiceLoadPatch(&Chanter, p);
|
||||
|
||||
oled.clear(PAGE);
|
||||
oled.setFontType(0);
|
||||
oled.setCursor(0, 0);
|
||||
oled.print(p->name);
|
||||
oled.setCursor(0, 10);
|
||||
oled.print("Patch ");
|
||||
oled.print(patch);
|
||||
oled.display();
|
||||
display.clearDisplay();
|
||||
display.setCursor(0, 0);
|
||||
display.print(p->name);
|
||||
display.setCursor(0, 10);
|
||||
display.print("Patch ");
|
||||
display.print(patch);
|
||||
display.display();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -216,7 +217,8 @@ const uint8_t CLOSEDVAL = 0x30;
|
|||
const uint8_t OPENVAL = 0x70;
|
||||
const uint8_t GLISSANDO_STEPS = OPENVAL - CLOSEDVAL;
|
||||
|
||||
bool playing = false;
|
||||
uint8_t loopno = 0;
|
||||
uint8_t last_note = 0;
|
||||
|
||||
void loop() {
|
||||
uint8_t keys = 0;
|
||||
|
@ -225,10 +227,15 @@ void loop() {
|
|||
uint8_t glissandoNote;
|
||||
float glissandoOpenness = 0;
|
||||
bool silent = false;
|
||||
bool knee = cap.filteredData(KNEE_OFFSET) < CLOSEDVAL;
|
||||
uint8_t buttons = trellis.isPressed(BUTTON_DOWN)?1:0 | trellis.isPressed(BUTTON_UP)?2:0;
|
||||
uint8_t paj_knee = 127;
|
||||
bool knee = false;
|
||||
|
||||
trellis.tick();
|
||||
loopno++;
|
||||
|
||||
paj7620ReadReg(0x6c, 1, &paj_knee);
|
||||
if (paj_knee > 240) {
|
||||
knee = true;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
uint16_t val = max(cap.filteredData(i+KEY_OFFSET), CLOSEDVAL);
|
||||
|
@ -246,9 +253,6 @@ void loop() {
|
|||
}
|
||||
}
|
||||
|
||||
// print key states
|
||||
//trellis.setPixelColor(7 - i, trellis.ColorHSV(65536/12, 255, 120*openness));
|
||||
trellis.setPixelColor(7 - i, trellis.ColorHSV(22222*openness, 255, 40));
|
||||
}
|
||||
|
||||
note = uilleann_matrix[keys];
|
||||
|
@ -265,20 +269,37 @@ void loop() {
|
|||
silent = true;
|
||||
}
|
||||
}
|
||||
// Look up the note name
|
||||
char *note_name = NoteNames[note % 12];
|
||||
if (silent) {
|
||||
note_name = "-";
|
||||
}
|
||||
|
||||
// Jump octave if the bag is squished
|
||||
//bag = !digitalRead(BAG);
|
||||
if (bag.isPressed()) {
|
||||
if (use_bag && bag.isPressed()) {
|
||||
if (keys & bit(7)) {
|
||||
note += 12;
|
||||
glissandoNote += 12;
|
||||
}
|
||||
}
|
||||
|
||||
// Read some trellis button states
|
||||
if (buttons) {
|
||||
updateTunables(buttons, note);
|
||||
}
|
||||
#if 0
|
||||
display.clearDisplay();
|
||||
display.setCursor(0, 0);
|
||||
display.print("mem: ");
|
||||
display.print(AudioMemoryUsageMax());
|
||||
display.print(" prx: ");
|
||||
display.print(paj_knee);
|
||||
display.setCursor(0, 24);
|
||||
display.print("Note: ");
|
||||
display.print(note);
|
||||
display.print(" n: ");
|
||||
display.print(loopno);
|
||||
display.display();
|
||||
return;
|
||||
#endif
|
||||
|
||||
|
||||
if (silent) {
|
||||
FMVoiceNoteOff(&Chanter);
|
||||
|
@ -305,4 +326,12 @@ void loop() {
|
|||
FMVoiceNoteOn(&Chanter, pitch);
|
||||
}
|
||||
}
|
||||
|
||||
if (note != last_note) {
|
||||
display.clearDisplay();
|
||||
display.setCursor(0, 0);
|
||||
display.print(note_name);
|
||||
display.display();
|
||||
last_note = note;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue