Tag: midi

  • MicroPython MIDI mayhem (kinda)

    It pleased me to learn about umidiparser – MIDI file parser for Micropython. Could I use my previous adventures in beepy nonsense to turn a simple MIDI file into a terrible squeaky rendition of same? You betcha!

    MIDI seems to be absurdly complex. In all the files I looked at, there didn’t seem to be much of a standard in encoding whether the note duration was in the NOTE_ON event or the NOTE_OFF event. Eventually, I managed to fudge a tiny single channel file that had acceptable note durations in the NOTE_OFF events. Here is the file:

    I used the same setup as before:

    Raspberry Pi Pico with small piezo speaker connected to pins 23 and 26
    piezo between pins 26 and 23

    With this code:

    # extremely crude MicroPython MIDI demo
    # MicroPython / Raspberry Pi Pico - scruss, 2022-08
    # see https://github.com/bixb922/umidiparser
    
    import umidiparser
    from time import sleep_us
    from machine import Pin, PWM
    
    # pin 26 - GP20; just the right distance from GND at pin 23
    #  to use one of those PC beepers with the 4-pin headers
    pwm = PWM(Pin(20))
    led = Pin('LED', Pin.OUT)
    
    
    def play_tone(freq, usec):
        # play RTTL/midi notes, also flash onboard LED
        # original idea thanks to
        #   https://github.com/dhylands/upy-rtttl
        print('freq = {:6.1f} usec = {:6.1f}'.format(freq, usec))
        if freq > 0:
            pwm.freq(int(freq))       # Set frequency
            pwm.duty_u16(32767)       # 50% duty cycle
        led.on()
        sleep_us(int(0.9 * usec))     # Play for a number of usec
        pwm.duty_u16(0)               # Stop playing for gap between notes
        led.off()
        sleep_us(int(0.1 * usec))     # Pause for a number of usec
    
    
    # map MIDI notes (0-127) to frequencies. Note 69 is 440 Hz ('A4')
    freqs = [440 * 2**((float(x) - 69) / 12) for x in range(128)]
    
    for event in umidiparser.MidiFile("lg2.mid", reuse_event_object=True):
        if event.status == umidiparser.NOTE_OFF and event.channel == 0:
            play_tone(freqs[event.note], event.delta_us)
    
    

    This isn’t be any means a general MIDI parser, but is rather specialized to play monophonic tunes on channel 0. The result is gloriously awful:

    apologies to LG
  • It works! It works!

    on a messy desk, a small USB midi keyboard is connected to a Korg NTS-1 mini synthesizer via a small micro-controller board that acts as a USB host for the Akai keyboard, converting USB MIDI to traditional MIDI for the Korg
    Akai LPK25 keyboard has USB MIDI out, but the Korg NTS-1 only has regular MIDI in. The little board in the middle acts as a USB host for the Akai and MIDI source for the Korg

    This is great: gdsports/midiuartusbh: MIDI DIN to MIDI USB Host Converter allows your USB MIDI instruments to act as traditional MIDI controllers. It uses a Adafruit Trinket M0 to act as the USB host and MIDI output.

    I modified gdsports’ design very slightly:

    1. Instead of using a 74AHCT125 Logic level converter and driver, I used a FET-based SparkFun Logic Level Converter
    2. Instead of a 5-pin DIN socket, I used a 3.5 mm stereo socket.

    And it works!

    breadboard showing Trinket M0 microcontroller board, logic level shifter, audio socket breakout and two resistors
    Breadboard layout for MIDI-standard 3.5 mm output (Korg). The resistors are both 220 ohm, and the boards need 5 V power