Reputation: 11
I'm having an issue with a USB midi controller I have been working on similar to the EWI. The instrument works by an IR LED casting light onto a photodiode with a balloon that inflates to block more or less of the light to get a variable signal for volume. The keys are just regular mechanical keyboard switches. For a controller I am using a Teensy 4.1.
I am running the controller with Ableton Live 11 just using he operator to make a sine wave. My issue is that when I blow air into the instrument, the only sound it makes is a buzzing noise. I'll attach a file showing the issue.
https://drive.google.com/file/d/1Hu0NHskzVzzX72kmhePuPmrTLq5DlxXW/view?usp=drive_link
To add additional information, if I press a random key that isn't part of a fingering while blowing into the instrument, it suddenly produces the sine tone. I have verified that the controller is sending the correct midi note as well as an accurate volume value.
Please let me know if you have any questions or need some more clarification. Thank you!
#include <MIDI.h>
// Mechanical switch pins
const int buttonPin[29] = {40, 39, 29, 28, 27, 26, 25, 12, 11, 10, 30, 6, 7, 23, 21, 19, 18, 22, 20, 17, 5, 4, 3, 2, 38, 37, 36, 34, 35};
// SPDT switch pins
const int switchPin[2] = {0, 1};
// Photodiode
const int photodiodePin = A10; // pin 24
const int IRledPin = 9;
// Variables for keys
const int numButtons = 28; // Not including octave key
int buttonState[numButtons] = {0};
int buttonNum[numButtons] = {0};
// Thresholds
const int maxVelocity = 500;
// Initialize some variables
int transpose;
int volume;
int modulation;
bool notePlaying = false;
int currentNote = 0;
const int channel = 1;
int octave = 0;
const float smoothingFactor = 0.1;
int smoothedValue = 0;
// All note IDs
static constexpr int C3[1] = {109477898};
static constexpr int Cs3Db3[1] = {109477900};
static constexpr int D3[1] = {109478408};
static constexpr int Ds3Eb3[1] = {109481992};
static constexpr int E3[4] = {110526472, 109479944, 110527496, 111577096};
static constexpr int F3[2] = {111575048, 109478920};
static constexpr int Fs3Gb3[2] = {110002184, 109494280};
static constexpr int G3[1] = {109477896};
static constexpr int Gs3Ab3[1] = {109486088};
static constexpr int nA3[1] = {109445128};
static constexpr int As3Bb3[1] = {109314056};
static constexpr int B3[2] = {109182984, 109379592};
static constexpr int C4[1] = {109051912};
static constexpr int Cs4Db4[1] = {113246216};
static constexpr int D4[1] = {100663304};
static constexpr int Ds4Eb4[3] = {117440520, 100663560, 67371016};
static constexpr int E4[1] = {67108872};
static constexpr int F4[1] = {8};
static constexpr int Fs4Gb4[2] = {67108864, 104};
static constexpr int G4[1] = {0};
static constexpr int Gs4Ab4[1] = {134217728};
static constexpr int nA4[1] = {268435456};
static constexpr int As4Bb4[2] = {268435472, 268435584};
static constexpr int B4[6] = {110526488, 109479960, 110527512, 111577112, 268435712, 268435600};
static constexpr int C5[3] = {111575064, 109478936, 268435840};
static constexpr int Cs5Db5[4] = {110002200, 109494296, 110003224, 111591448};
static constexpr int D5[1] = {109477912};
static constexpr int Ds5Eb5[1] = {109486104};
static constexpr int E5[1] = {109445144};
static constexpr int F5[1] = {109314072};
static constexpr int Fs5Gb5[2] = {109183000, 109379608};
static constexpr int G5[1] = {109051928};
static constexpr int Gs5Ab5[1] = {113246232};
static constexpr int nA5[1] = {100663320};
static constexpr int As5Bb5[2] = {100663352, 67371032};
static constexpr int B5[1] = {67108888};
static constexpr int C6[1] = {24};
static constexpr int Cs6Db6[1] = {42336280};
static constexpr int D6[2] = {42205208, 42213400};
static constexpr int Ds6Eb6[2] = {42270744, 42278936};
static constexpr int E6[2] = {41943064, 41951256};
static constexpr int F6[2] = {46137368, 46145560};
static constexpr int Fs6Gb6[4] = {33554456, 37748760, 33562648, 37756952};
static constexpr int G6[4] = {33882136, 8781848, 33890328, 8790040};
static constexpr int Gs6Ab6[2] = {42074136, 42082328};
static constexpr int nA6[2] = {42467352, 41959448};
//static constexpr int #A6Bb6[2] = {}; //******NEED FINGERINGS******
//static constexpr int B6[2] = {}; //******NEED FINGERINGS******
//static constexpr int C7[2] = {}; //******NEED FINGERINGS******
// Function to generate note ID
int noteID(int binaryArray[], int arraySize)
{
int noteID = 0;
for (int i = 0; i < arraySize; i++)
{
noteID = (noteID << 1) | binaryArray[i];
}
return noteID*2;
}// end noteID
void playNote(int note)
{
if (notePlaying && currentNote == note)
{
// Check if a note is already playing
usbMIDI.sendControlChange(2, volume, channel);
//Serial.println(note);
}
else if (notePlaying)
{
// Send Note Off message for the current note
usbMIDI.sendNoteOff(currentNote, 0, channel);
notePlaying = false;
}
// Send Note On message for the new note
usbMIDI.sendNoteOn(note, volume, channel);
//Serial.println(note);
currentNote = note;
notePlaying = true;
}// end playNote
void setup()
{
Serial.begin(9600);
// Turn on LED and give some delay
pinMode(IRledPin, OUTPUT);
digitalWrite(IRledPin, HIGH);
delay(500);
// Sets mode for SPDT switch and POT
pinMode(switchPin[0], INPUT_PULLUP);
pinMode(switchPin[1], INPUT_PULLUP);
// Initialize mechanical switch pins as inputs
for (int i = 0; i < numButtons + 1; i++) // +1 to include octave key
{
pinMode(buttonPin[i], INPUT_PULLUP);
}
}// end setup
void loop()
{
volume = map(analogRead(photodiodePin), 0, maxVelocity, 0, 127);
if (volume > 127)
{
volume = 127;
}
// 3-way switch for transposing
if (digitalRead(switchPin[0]) == HIGH and digitalRead(switchPin[1]) == LOW)
{
transpose = 2; // Bb
}
else if (digitalRead(switchPin[0]) == LOW and digitalRead(switchPin[1]) == HIGH)
{
transpose = 3; // A
}
else
{
transpose = 0; // C
}// end transposing
// Read the state of each push button
for (int i = 0; i < numButtons; i++)
{
buttonState[i] = digitalRead(buttonPin[i]);
// Update the result variable for each button based on its state
if (buttonState[i] == LOW)
{
buttonNum[i] = 1; // Button is pressed
}
else
{
buttonNum[i] = 0; // Button is not pressed
}
}
// Read octave key
int octaveKey = digitalRead(buttonPin[28]);
if (octaveKey == LOW)
{
octave = -12;
}
else
{
octave = 0;
}
// Send MIDI based on fingerings
if (volume > 0)
{
switch (noteID(buttonNum, numButtons))
{
// C3
case C3[0]:
playNote(48+transpose+octave);
break;
// C#3/Db3
case Cs3Db3[0]:
playNote(49+transpose+octave);
break;
// D3
case D3[0]:
playNote(50+transpose+octave);
break;
// D#3/Eb3
case Ds3Eb3[0]:
playNote(51+transpose+octave);
break;
// E3
case E3[0]:
case E3[1]:
case E3[2]:
case E3[3]:
playNote(52+transpose+octave);
break;
// F3
case F3[0]:
case F3[1]:
playNote(53+transpose+octave);
break;
// F#3/Gb3
case Fs3Gb3[0]:
case Fs3Gb3[1]:
playNote(54+transpose+octave);
break;
// G3
case G3[0]:
playNote(55+transpose+octave);
break;
// G#3/Ab3
case Gs3Ab3[0]:
playNote(56+transpose+octave);
break;
// A3
case nA3[0]:
playNote(57+transpose+octave);
break;
// A#3/Bb3
case As3Bb3[0]:
playNote(58+transpose+octave);
break;
// B3
case B3[0]:
case B3[1]:
playNote(59+transpose+octave);
break;
// C4
case C4[0]:
playNote(60+transpose+octave);
break;
// C#4/Db4
case Cs4Db4[0]:
playNote(61+transpose+octave);
break;
// D4
case D4[0]:
playNote(62+transpose+octave);
break;
// D#4/Eb4
case Ds4Eb4[0]:
case Ds4Eb4[1]:
case Ds4Eb4[2]:
playNote(63+transpose+octave);
break;
// E4
case E4[0]:
playNote(64+transpose+octave);
break;
// F4
case F4[0]:
playNote(65+transpose+octave);;
break;
// F#4/Gb4
case Fs4Gb4[0]:
case Fs4Gb4[1]:
playNote(66+transpose+octave);
break;
// G4
case G4[0]:
playNote(67+transpose+octave);
break;
// G#4/Ab4
case Gs4Ab4[0]:
playNote(68+transpose+octave);
break;
// A4
case nA4[0]:
playNote(69+transpose+octave);
break;
// A#4/Bb4
case As4Bb4[0]:
case As4Bb4[1]:
playNote(70+transpose+octave);
break;
// B4
case B4[0]:
case B4[1]:
case B4[2]:
case B4[3]:
case B4[4]:
case B4[5]:
playNote(71+transpose+octave);
break;
// C5
case C5[0]:
case C5[1]:
case C5[2]:
playNote(72+transpose+octave);
break;
// C#5/Db5
case Cs5Db5[0]:
case Cs5Db5[1]:
case Cs5Db5[2]:
case Cs5Db5[3]:
playNote(73+transpose+octave);
break;
// D5
case D5[0]:
playNote(74+transpose+octave);
break;
// D#5/Eb5
case Ds5Eb5[0]:
playNote(75+transpose+octave);
break;
// E5
case E5[0]:
playNote(76+transpose+octave);
break;
// F5
case F5[0]:
playNote(77+transpose+octave);
break;
// F#5/Gb5
case Fs5Gb5[0]:
case Fs5Gb5[1]:
playNote(78+transpose+octave);
break;
// G5
case G5[0]:
playNote(79+transpose+octave);
break;
// G#5/Ab5
case Gs5Ab5[0]:
playNote(80+transpose+octave);
break;
// A5
case nA5[0]:
playNote(81+transpose+octave);
break;
// A#5/Bb5
case As5Bb5[0]:
case As5Bb5[1]:
playNote(82+transpose+octave);
break;
// B5
case B5[0]:
playNote(83+transpose+octave);
break;
// C6
case C6[0]:
playNote(84+transpose+octave);
break;
// C#6/Db6
case Cs6Db6[0]:
playNote(85+transpose+octave);
break;
// D6
case D6[0]:
case D6[1]:
playNote(86+transpose+octave);
break;
// D#6/Eb6
case Ds6Eb6[0]:
case Ds6Eb6[1]:
playNote(87+transpose+octave);
break;
// E6
case E6[0]:
case E6[1]:
playNote(88+transpose+octave);
break;
// F6
case F6[0]:
case F6[1]:
playNote(89+transpose+octave);
break;
// F#6/Gb6
case Fs6Gb6[0]:
case Fs6Gb6[1]:
case Fs6Gb6[2]:
case Fs6Gb6[3]:
playNote(90+transpose+octave);
break;
// G6
case G6[0]:
case G6[1]:
case G6[2]:
case G6[3]:
playNote(91+transpose+octave);
break;
// G#6/Ab6
case Gs6Ab6[0]:
case Gs6Ab6[1]:
playNote(92+transpose+octave);
break;
// A6
case nA6[0]:
case nA6[1]:
playNote(93+transpose+octave);
break;
default:
// Do nothing if fingering isn't recognized
break;
} // end fingering switch case
} // end play notes
else // Stops all notes if there is no air
{
usbMIDI.sendControlChange(123, 0, channel); //control, value, channel
} // end else
//Serial.println(noteID(buttonNum, numButtons));
} // end loop
I have tried making sure that it is sending the correct midi note, made sure that the correct volume value is being sent, and that the correct fingering ID was being generated. I also tried connecting a regular midi keyboard (Launchkey Mini) and that was working correctly.
Upvotes: 1
Views: 48