alexandros
Well-known member
I'm building an audio project with a Teensy 3.6 and the Audio Board. When I develop it and upload new code, the project runs fine. When I unplug and re-plug the Teensy, I get nothing from the headphones. When I upload the code again, I still get nothing.
To make it work I need to upload an example with audio output from the Audio examples and then upload my code and it will work fine.
Here's my code:
I'm using Arduino IDE 1.8.5, Teensyduino 1.42 or 1.43 (can't remember exactly which one), on Ubuntu Studio 18.04. Any help appreciated.
To make it work I need to upload an example with audio output from the Audio examples and then upload my code and it will work fine.
Here's my code:
Code:
// GUItool: begin automatically generated code
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
AudioSynthWaveformSine sines[2];
AudioEffectFade faders[2];
AudioMixer4 mixer1;
AudioOutputI2S i2s1;
AudioConnection patchCord1(sines[1], faders[1]);
AudioConnection patchCord2(sines[0], faders[0]);
AudioConnection patchCord3(faders[0], 0, mixer1, 0);
AudioConnection patchCord4(faders[1], 0, mixer1, 1);
AudioConnection patchCord5(mixer1, 0, i2s1, 0);
// GUItool: end automatically generated code
// define a delta value difference for the ribons, to eliminate noisy readings
#define RIBDELTA 8
// define a delta value difference for frequencies passed to the last for loop
#define FREQDELTA 50
// define the analog resolution in bits
#define ANALOGRES 10
#define FRETS 15
// define the tuning A frequency for converting from MIDI to frequency if the freq ribon
// is split to the number of frets set above
#define TUNING_A 440.0
const int ribons = 4;
int ribonPins[ribons] = { 2, 3, 6, 7 };
int ribVals[ribons] = { 0 };
int curVals[ribons] = { 0 };
// we copy the values of the ribons at the end of loop()
// otherwise they'll constantly change and the beginning of loop()
// will constantly update them
int ribValsCopy[ribons] = { 0 };
// these booleans set whether a value sent is an extreme value (0 or 1000)
bool extremeValSent[ribons] = { false };
// we constrain the analog readings to the following two extremes
// their values are set in setup() according to anaolgReadResolution()
// unless ANALOGRES is not defined, then they will default to the values below
int floorVal = 40;
int ceilVal = 1000;
int range = ceilVal - floorVal;
int fretRange = range / FRETS;
// variables for the switches (both lever and rotary)
const int numSwitches = 4;
const int numRotSwitches = 2;
const int numRotSwitchPos = 4;
int switchPins[numSwitches] = { 28, 29, 30, 31 };
int rotSwitchPins[numRotSwitches][numRotSwitchPos] { { 2, 3, 4, 5 }, { 24, 25, 26, 27 } };
int currentSwitchVals[numSwitches];
int currentRotSwitchVals[numRotSwitches][numRotSwitchPos];
// we're using pull-up resistors, so default value is 1
int switchVals[numSwitches] = { 1, 1, 1, 1 };
int oldSwitchVals[numSwitches] = { 1, 1, 1, 1 };
int rotSwitchVals[numRotSwitches][numRotSwitchPos] = { { 1, 1, 1, 1 }, { 1, 1, 1, 1 } };
int oldRotSwitchVals[numRotSwitches][numRotSwitchPos] = { { 1, 1, 1, 1 }, { 1, 1, 1, 1 } };
unsigned long lastDebounceSwitches[numSwitches] = { 0 };
unsigned long lastDebounceRotSwitches[numRotSwitches][numRotSwitchPos] = { { 0 }, { 0 } };
unsigned long debounceTime = 50;
// the following variables are for determining whether we're sustaining the notes or not
// for octaves setting
// and for setting an unfretted or tuned layout for the ribbons
// FIY: ribon 0 is the top fretboard, 2 is bottom fretboard
// ribon 1 is top volume, and 3 bottom volume
// lever switch 3 is top unfretted/tuned switch
// lever switch 1 is bottom unfretted/tuned switch
// lever switch 2 is top sustain switch
// lever switch 0 is bottom sustain switch
// rotary switch 0 is top, and 1 is bottom
int sustainNotes[2] = { 0 };
int frettedRibons[2] = { 0 };
int lowFreqs[4] = { 40, 30, 20, 0 };
int highFreqs[4] = { 1000, 500, 300, 200 };
int lowFreq[2] = { lowFreqs[3], lowFreqs[3] };
int highFreq[2] = { highFreqs[3], highFreqs[3] };
// for MIDI notes we only need the lower part, cause all we do is add it to the current MIDI
// note read by the ribon
int lowMidiNotes[4] = { 40, 30, 20, 10 };
int lowMidiNote[2] = { lowMidiNotes[3], lowMidiNotes[3] };
// these two variables are used to determine whether fading in or out is changing
// when sustain is not set, so we can avoid constantly fading in or out
// until we get a change (amp going to or coming from zero)
int curAmp[2];
int oldAmp[2] = { 0 };
// the two booleans below are used to determing whether we'll do frequency and amplitude
// calculations after we've read all ribons and switches
bool ribValChanged[2] = { false, false };
int fadeMs = 100;
// determine whether we're not touching the ribon at all
bool zeroFreq[2];
int oldRibVal[2] = { 0 };
void setup() {
// Audio connections require memory to work. For more
// detailed information, see the MemoryAndCpuUsage example
AudioMemory(15);
for (int i = 0; i < numSwitches; i++) {
pinMode(switchPins[i], INPUT_PULLUP);
}
for (int i = 0; i < numRotSwitches; i++) {
for (int j = 0; j < numRotSwitchPos; j++) {
pinMode(rotSwitchPins[i][j], INPUT_PULLUP);
}
}
for (int i = 0; i < 2; i++) {
sines[i].amplitude(0.0);
// a higher gain in the mixer results in only clicks when both signals are combined
// and get above a certain amplitude, this gain solves this problem
mixer1.gain(i, 0.25);
}
#ifdef ANALOGRES
analogReadResolution(ANALOGRES);
switch(ANALOGRES) {
case 10:
floorVal = 40;
ceilVal = 1000;
range = ceilVal - floorVal;
fretRange = range / FRETS;
break;
case 12:
floorVal = 80;
ceilVal = 4000;
range = ceilVal - floorVal;
fretRange = range / FRETS;
break;
case 13:
floorVal = 120;
ceilVal = 8000;
range = ceilVal - floorVal;
fretRange = range / FRETS;
break;
default:
break;
}
#endif
//Serial.begin(115200);
//while(!Serial) {};
}
void loop() {
// run through the analog pins, constrain to the defined extremes
// then test if the new value is more or less that RIBDELTA
// than the last value stored
for (int i = 0; i < ribons; i++) {
curVals[i] = analogRead(ribonPins[i]);
curVals[i] = constrain(curVals[i], floorVal, ceilVal);
if (abs(curVals[i] - ribVals[i]) > RIBDELTA) {
ribVals[i] = curVals[i];
//Serial.print("Ribon "); Serial.print(i);
//Serial.print(": "); Serial.println(ribVals[i]);
// check if we're sending an extreme value
if ((ribVals[i] <= floorVal) || (ribVals[i] >= ceilVal)) {
extremeValSent[i] = true;
}
else {
extremeValSent[i] = false;
}
ribValChanged[i] = true;
}
// check if we're at the extremes
if ((curVals[i] <= floorVal) || (curVals[i] >= ceilVal)) {
// if we're at the extremes and an extreme value hasn't been sent, send it
if (!extremeValSent[i]) {
ribVals[i] = curVals[i];
//Serial.print("Ribon "); Serial.print(i);
//Serial.print(": "); Serial.println(ribVals[i]);
extremeValSent[i] = true;
ribValChanged[i] = true;
}
}
}
// Using the debounce technique from the Arduino tutorials
// because the switches seem to be quite noisy
for (int i = 0; i < numSwitches; i++) {
// read the state of the switch into a local variable:
currentSwitchVals[i] = digitalRead(switchPins[i]);
// If the switch changed, due to noise or pressing:
if (currentSwitchVals[i] != oldSwitchVals[i]) {
// reset the debouncing timer
lastDebounceSwitches[i] = millis();
}
if ((millis() - lastDebounceSwitches[i]) > debounceTime) {
if (currentSwitchVals[i] != switchVals[i]) {
switchVals[i] = currentSwitchVals[i];
switch(i) {
case 0:
sustainNotes[1] = !switchVals[i];
break;
case 1:
frettedRibons[1] = !switchVals[i];
break;
case 2:
sustainNotes[0] = !switchVals[i];
break;
case 3:
frettedRibons[0] = !switchVals[i];
break;
}
}
}
// save the reading. Next time through the loop, it'll be the lastButtonState:
oldSwitchVals[i] = currentSwitchVals[i];
}
for (int i = 0; i < numRotSwitches; i++) {
for (int j = 0; j < numRotSwitchPos; j++) {
currentRotSwitchVals[i][j] = digitalRead(rotSwitchPins[i][j]);
if (currentRotSwitchVals[i][j] != oldRotSwitchVals[i][j]) {
lastDebounceRotSwitches[i][j] = millis();
}
if ((millis() - lastDebounceRotSwitches[i][j]) > debounceTime) {
if (currentRotSwitchVals[i][j] != rotSwitchVals[i][j]) {
rotSwitchVals[i][j] = currentRotSwitchVals[i][j];
if (!rotSwitchVals[i][j]) {
// by changing the position of a rotary switch, both the current and the previous
// pin will change states, but we only care about the one that's connected to the common
lowFreq[i] = lowFreqs[j];
highFreq[i] = highFreqs[j];
lowMidiNote[i] = lowMidiNotes[j];
}
}
}
oldRotSwitchVals[i][j] = currentRotSwitchVals[i][j];
}
}
// after we've read all ribons and switches
// we write the frequency and amplitude values to the oscillators
for (int i = 0; i < 2; i++) {
// ribons are wired this way:
// 0 is freq for channel 1, 2 is amp for channel 1
// 1 is freq for channel 2, 3 is amp for channel 2
int freqIdx = i * 2;
int ampIdx = (i * 2) + 1;
// calcute frequency and amplitude only if a value of a ribon has changed
if (ribValChanged[freqIdx] || ribValChanged[ampIdx]) {
// using i instead of freqIdx in some places cause freqIdx is either 0 or 2
// and sometimes we need 0 and 1
ribValsCopy[freqIdx] = ribVals[freqIdx];
ribValsCopy[ampIdx] = ribVals[ampIdx];
// determine whether we're touching the ribon or not
if ((ribValsCopy[freqIdx] <= floorVal) || (abs(ribValsCopy[freqIdx] - oldRibVal[i]) > FREQDELTA)) {
zeroFreq[i] = true;
}
else {
zeroFreq[i] = false;
}
oldRibVal[i] = ribValsCopy[freqIdx];
//Serial.print("Ribon "); Serial.print(i);
//Serial.print(": "); Serial.println(ribValsCopy[freqIdx]);
int freq = map(ribValsCopy[freqIdx], floorVal, ceilVal, lowFreq[i], highFreq[i]);
int midiNote = ribValsCopy[freqIdx] / fretRange;
// can't use map for the amplitude cause we need a float
ribValsCopy[ampIdx] -= floorVal;
float amp = (float) ribValsCopy[ampIdx] / (float) (ceilVal - floorVal);
sines[i].amplitude(amp);
// if the ribons are set to fretted intervals divide the freq value by the fretRange variable
if (frettedRibons[i]) {
midiNote += lowMidiNote[i];
float midiFreq = pow(2, (((float)midiNote - 69.0) / 12.0)) * TUNING_A;
if (zeroFreq[i]) {
if (!sustainNotes[i]) {
faders[i].fadeOut(fadeMs);
}
}
else {
if (!sustainNotes[i]) {
// update the frequency only when we're touching the ribon
sines[i].frequency(midiFreq);
faders[i].fadeIn(fadeMs);
}
}
}
else {
if (zeroFreq[i]) {
if (!sustainNotes[i]) {
faders[i].fadeOut(fadeMs);
}
}
else {
if (!sustainNotes[i]) {
// update the frequency only when we're touching the ribon
sines[i].frequency(freq);
faders[i].fadeIn(fadeMs);
}
}
}
if (ribValChanged[freqIdx]) {
ribValChanged[freqIdx] = false;
}
if (ribValChanged[ampIdx]) {
ribValChanged[ampIdx] = false;
}
}
}
}
I'm using Arduino IDE 1.8.5, Teensyduino 1.42 or 1.43 (can't remember exactly which one), on Ubuntu Studio 18.04. Any help appreciated.