Jesse
Jesse

Reputation: 11

Arduino USB Midi

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

Answers (0)

Related Questions