Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 5 of 5

Thread: Analog To Midi (voice To Midi)

  1. #1
    Junior Member
    Join Date
    Nov 2017
    Posts
    4

    Analog To Midi (voice To Midi)

    Hi, I am a Teensy beginner.
    I want to make Arduino example "Analog To Midi" using a Teensy.
    Teensy (3.2 or 3.6) could expect higher quality.
    I found some examples like guitar tuners, but it's a bit different from what I want.
    Thank you for any hints or examples.
    I have "Electret Microphone Amplifier - MAX4466"

    Code:
    *
      Analog to Midi Converter for Arduino MKR1000
    
      Demonstrates how to sample an input signal and get back its corresponding MIDI note
    
      This example code is in the public domain
    
      http://arduino.cc/en/Tutorial/AnalogToMidi
    
      created by Arturo Guadalupi <a.guadalupi@arduino.cc>
      29 Jan 2016
    */
    
    #include <AudioFrequencyMeter.h>
    #include <MIDIUSB.h>
    #include <frequencyToNote.h>
    #include <pitchToNote.h>
    
    #define DEPTH         60                      // Defines depth of the array for averaged frequencies
    #define HUMAN_RATE    50                      // Defines 50ms corresponding to 20 notes/s
    #define MAX_DURATION  1000                    // Defines the max play duration of the note
    
    AudioFrequencyMeter meter;
    
    int notesArray[DEPTH];                        // Array to store detected notes and find the "correct" note which occurred the most often
    int occurrences[DEPTH];                       // Array in which the number of occurrences for each note are stored
    bool marked[DEPTH];                           // Array to indicate which of the notes have been checked
    int frequencyIndex = 0;                       // Used to navigate to where the current note must be stored
    
    int previousNote;
    unsigned int startTime;                       // Used to determine when the note must stop
    unsigned int humanTime;                       // Used to determine when the next note can be sampled (using HUMAN_RATE timing)
    
    int intensity = 64;                           // The volume of the played note is fixed at 64
    
    void setup() {
      // put your setup code here, to run once:
      Serial.begin(115200);
      pinMode(11, OUTPUT);
      meter.setBandwidth(75.00, 600.00);          // Set available bandwidth between 75Hz and 600Hz
      meter.begin(A0, 45000);                     // Intialize A0 at sample rate of 45kHz
    }
    
    void loop() {
      float frequency = meter.getFrequency();
    
      if (frequency > 0)
      {
        int noteIndex = searchForNote(frequency); // Find the index of the corresponding frequency
        int note = notePitch[noteIndex];          // Use that index to find the corresponding note in the LUT
        notesArray[frequencyIndex++] = note;      // Store the note and continue to next value in array
    
        if (frequencyIndex > DEPTH)               // If all the notes have been stored
        {
          frequencyIndex = 0;                     // Reset the index
          int i, j;
    
          /*Reset all the occurences and marked positions*/
          for (i = 0; i < DEPTH; i++)
          {
            occurrences[i] = 0;
            marked[i] = 0;
          }
    
          /*Count the number of occurrences*/
          for (i = 0; i < DEPTH; i++)
          {
            for (j = 0; j < DEPTH; j++)
            {
              // If notes are the same and the note has not been marked yet
              if ((!marked[j]) && (notesArray[j] == notesArray[i]))
              {
                occurrences[i]++;                 // Increment the number of occurrences
                marked[j] = true;                 // Signal the note as marked
              }
            }
          }
    
          int numberOfdifferentFrequencies = 0;   // Used to determine how many different Frequencies have been detected
    
          for (i = 0; i < DEPTH; i++)
          {
            // If the counter does not equal zero
            if (occurrences[i] != 0)
            {
              // Store the the various detected Frequencies
              notesArray[numberOfdifferentFrequencies] = notesArray[i];
              // And the number of occurrences for each note
              occurrences[numberOfdifferentFrequencies] = occurrences[i];
              numberOfdifferentFrequencies++;      // Increment the number of detected Frequencies
            }
          }
    
          /*Search for the maximum number of occurrences to discriminate the played note*/
          int maxNumberOfFrequencies = occurrences[0];
          int rightIndex = 0;
    
          for (i = 0; i < numberOfdifferentFrequencies; i++);
          {
            // If a new maximum exist
            if (occurrences[i] > maxNumberOfFrequencies)
            {
              // Update the value
              maxNumberOfFrequencies = occurrences[i];
              // Update the index
              rightIndex = i;
            }
          }
          note = notesArray[rightIndex];          // Note to be played is that with the most occurrences
          // If the specified time has elapsed before the next note
          if (millis() - humanTime > HUMAN_RATE)
          {
            humanTime = millis();                 // Update the timer
            startTime = millis();                 // Update the note duration
            noteOff(0, previousNote, intensity);  // Stop playing the previous note
            previousNote = note;                  // Update previous note with the new one
            Serial.println(note);                 // Print the note to be played
            noteOn(0, note, intensity);           // Play the note!
          }
        }
      }
    
      if (millis() - startTime > MAX_DURATION)    // If maximum time elapsed
        noteOff(0, previousNote, intensity);      // Turn the note off
    }
    
    int searchForNote(float frequency)
    {
      float minimum = abs(frequency - noteFrequency[0]);
      float newMinimum;
      int index = 0;
    
      /*Search for the nearest frequency that is in the vector*/
      for (int i = 0; i < NUMBER_OF_NOTES - 1; i++)
      {
        newMinimum = abs(frequency - noteFrequency[i]);
        if (newMinimum < minimum)
        {
          minimum = newMinimum;
          index = i;
        }
      }
    
      return index;
    }
    
    void noteOn(byte channel, byte pitch, byte velocity) {
      midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
      MidiUSB.sendMIDI(noteOn);
    }
    
    void noteOff(byte channel, byte pitch, byte velocity) {
      midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
      MidiUSB.sendMIDI(noteOff);
    }

  2. #2
    hi,

    the teensy audio library can do this with the Audio->Analyze->NoteFrequency object.
    but this works only monophonic and detect the fundamental note frequency of an tone. for example your voice or an guitar note if only one string is played. it can not detect a chord.

    so, if AudioFrequencyMeter from your example works polyphonic there is no real alternative object available in teensy audio library. maybe fft can do this, but to detect the correct fundamentals of a chord by using fft analyse you need a deep knowledge to compute this. as lower the frequency as more problems you become. also you need an good idea to compute the different envelop states in a chord. hard enough to design a fast envelope tracking for only one incoming voice or guitar string.

    i use Collin Duffy s https://github.com/duff2013/AudioTuner from github, the newer version from Audio->Analyze->NoteFrequency, in an teensy based guitar synthesizer(monophonic). this works fine here. and it is possible to perform acceptable latency between plugged guitar string and synthesizer output. dependent to note frequency i get frequency values after 2 and 5 ms. higher notes compute faster. some intervals perform not fast. i do not know why. mostly octave intervals perform slow. but if you know the limitations you can play with them.

    /g
    wolke

  3. #3
    Junior Member
    Join Date
    Nov 2017
    Posts
    4
    Thank you for your reply.
    I want to convert the voice (frequency about 130hz ~ 500hz) into monophonic note.
    Example https://github.com/duff2013/AudioTuner or Audio-> Analyze-> NoteFrequency
    I think this is the example I'm looking for. I'll try it right away.
    By the way, I wonder coefficients what defined coeff.h and use in the AudioTuner example code mean.
    If you know it, please answer it.
    Thanks again.

    Code:
    tuner.begin (.15, fir_22059_HZ_coefficients, sizeof (fir_22059_HZ_coefficients), 2);
    Last edited by mrdoor; 11-20-2017 at 11:39 AM.

  4. #4
    hi,

    i use as default the existing "fir_22059_HZ_coefficients" defined in coeff.h, which works very well to detect frequencies from guitar.

    Code:
    int16_t fir_22059_HZ_coefficients[20] =
    {
        0, 1, -6, -54, 18, 326,
        -14, -1178, -6, 5001, 8209, 5001,
        -6, -1178, -14, 326, 18, -54,
        -6, 1
    };
    important, to get frequencies faster from tuner, you need to adjust AUDIO_GUITARTUNER_BLOCKS in AudioTuner.h line 42.
    default this is set to 24. i use 9 at this point. this is much faster. and audiotuner can properly detect
    frequency down to ~80Hz. 24 allow much lower detection but increase the detection time a lot.
    Code:
    #define AUDIO_GUITARTUNER_BLOCKS  24
    change to
    Code:
    #define AUDIO_GUITARTUNER_BLOCKS  9 //faster detection, but min detection freq ~80Hz
    /g
    wolke

    ps:
    here is my monophonic guitar synth which works well with collin duffy's tuner object.
    https://forum.pjrc.com/threads/43842...light=gitsynth

  5. #5
    Junior Member
    Join Date
    Nov 2017
    Posts
    4
    Thanks for reply.
    I purchased teensy 3.2 and compiled the audio tuner code.
    However, an error occurs.

    "Arduino / libraries / AudioTuner-master / AudioTuner.cpp: 23: 35: fatal error: analyze_notefreq_fast.h: No such file or directory
    compilation terminated. "

    Thank you for any hints
    (NoteFrequency example works well.)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •