This sequencer is perfect for getting started! It's a lot of fun to play, and very intuitive, since all four sample tracks are displayed continuously. No "menu-diving" allowed!
You'll program it with CircuitPython, so first, let's prep the board for that.
CircuitPython Prep
To prep the Trellis M4 to run the sequencer code, follow these steps:
- Update the bootloader for NeoTrellis from the Trellis M4 guide
- Install the latest CircuitPython for NeoTrellis from the Trellis M4 guide
- Get the latest CircuitPython library pack, matching the version number with the major version of CircuitPython you are using, unzip it, and drag the libraries you need over into the /lib folder on CIRCUITPY. The latest library package includes support for Trellis M4.
https://github.com/adafruit/Adafruit_CircuitPython_Bundle/releases/
If you'd like to reduce the storage footprint of the lib folder (to make room for lots of sound files!) these are the only one's you'll need to keep, you can remove the rest:
- adafruit_trellism4.mpy
- adafruit_fancyled folder
- neopixel.mpy
- adafruit_matrixkeypad.mpy
- adafruit_adxl34x.mpy
- adafruit_bus_device
Prepare Audio Files
Audio files can be gathered by any means you like, but they will all need to be formatted the same way to be recognized by the Trellis M4.
See this guide on how to convert audio files.
For the Eight-Step Simple Sequencer you can use either mono or stereo files, just make sure all of your files are the same format, no mixing and matching!
Sound Packs
For your convenience and drumming pleasure, we've compiled some sound kits for you to use. Simply download this zip file, uncompress it, and you'll be able to use them on the board after copying and renaming them as outlined below.
Samples Directory
With your Trellis M4 plugged into your computer, it will show up as the CIRCUITPY USB drive. Open it up and create a new folder named samples
Copy Sounds
Copy a set of four sound files from one of the packs and paste it into the samples
folder you just made on the Trellis M4's CIRCUITPY drive.
Rename
Rename the four files like this:
- drum_cymbal_pedal.wav to voice01.wav
- drum_snare_hard.wav to voice02.wav
- elec_ping.wav to voice03.wav
- bd_haus.wav to voice04.wav
As you'll see in the code below, this name pattern: /samples/voice01.wav
through /samples/voice04.wav
is the only set of names that will be found and played.
When we code the Trellis M4 with the sequencer program, the voices (sound files) will be arrayed along the four rows as shown here.
Copy the code shown here, and then paste it into Mu. Save it to your Trellis M4 as code.py
# SPDX-FileCopyrightText: 2018 Limor Fried for Adafruit Industries # # SPDX-License-Identifier: MIT import time import board import busio import audioio import audiocore import audiomixer import adafruit_fancyled.adafruit_fancyled as fancy import adafruit_trellism4 import adafruit_adxl34x tempo = 180 # Starting BPM # You can use the accelerometer to speed/slow down tempo by tilting! ENABLE_TILT_TEMPO = True MIN_TEMPO = 100 MAX_TEMPO = 300 SAMPLE_FOLDER = "/samples/" # the name of the folder containing the samples # You get 4 voices, they must all have the same sample rate and must # all be mono or stereo (no mix-n-match!) VOICES = [SAMPLE_FOLDER+"voice01.wav", SAMPLE_FOLDER+"voice02.wav", SAMPLE_FOLDER+"voice03.wav", SAMPLE_FOLDER+"voice04.wav"] # four colors for the 4 voices, using 0 or 255 only will reduce buzz DRUM_COLOR = ((0, 255, 255), (0, 255, 0), (255, 255, 0), (255, 0, 0)) # For the intro, pick any number of colors to make a fancy gradient! INTRO_SWIRL = [fancy.CRGB(255, 0, 0), # red fancy.CRGB(0, 255, 0), # green fancy.CRGB(0, 0, 255)] # blue # the color for the sweeping ticker bar TICKER_COLOR = (255, 255, 255) # Our keypad + neopixel driver trellis = adafruit_trellism4.TrellisM4Express(rotation=90) # Our accelerometer i2c = busio.I2C(board.ACCELEROMETER_SCL, board.ACCELEROMETER_SDA) accelerometer = adafruit_adxl34x.ADXL345(i2c) # Play the welcome wav (if its there) with audioio.AudioOut(board.A1, right_channel=board.A0) as audio: try: f = open("welcome.wav", "rb") wave = audiocore.WaveFile(f) audio.play(wave) swirl = 0 # we'll swirl through the colors in the gradient while audio.playing: for i in range(32): palette_index = ((swirl+i) % 32) / 32 color = fancy.palette_lookup(INTRO_SWIRL, palette_index) # display it! trellis.pixels[(i//8, i%8)] = color.pack() swirl += 1 time.sleep(0.005) f.close() # Clear all pixels trellis.pixels.fill(0) # just hold a moment time.sleep(0.5) except OSError: # no biggie, they probably deleted it pass # Parse the first file to figure out what format its in with open(VOICES[0], "rb") as f: wav = audiocore.WaveFile(f) print("%d channels, %d bits per sample, %d Hz sample rate " % (wav.channel_count, wav.bits_per_sample, wav.sample_rate)) # Audio playback object - we'll go with either mono or stereo depending on # what we see in the first file if wav.channel_count == 1: audio = audioio.AudioOut(board.A1) elif wav.channel_count == 2: audio = audioio.AudioOut(board.A1, right_channel=board.A0) else: raise RuntimeError("Must be mono or stereo waves!") mixer = audiomixer.Mixer(voice_count=4, sample_rate=wav.sample_rate, channel_count=wav.channel_count, bits_per_sample=wav.bits_per_sample, samples_signed=True) audio.play(mixer) samples = [] # Read the 4 wave files, convert to stereo samples, and store # (show load status on neopixels and play audio once loaded too!) for v in range(4): trellis.pixels[(v, 0)] = DRUM_COLOR[v] wave_file = open(VOICES[v], "rb") # OK we managed to open the wave OK for x in range(1, 4): trellis.pixels[(v, x)] = DRUM_COLOR[v] sample = audiocore.WaveFile(wave_file) # debug play back on load! mixer.play(sample, voice=0) for x in range(4, 7): trellis.pixels[(v, x)] = DRUM_COLOR[v] while mixer.playing: pass trellis.pixels[(v, 7)] = DRUM_COLOR[v] samples.append(sample) # Clear all pixels trellis.pixels.fill(0) # Our global state current_step = 7 # we actually start on the last step since we increment first # the state of the sequencer beatset = [[False] * 8, [False] * 8, [False] * 8, [False] * 8] # currently pressed buttons current_press = set() while True: stamp = time.monotonic() # redraw the last step to remove the ticker bar (e.g. 'normal' view) for y in range(4): color = 0 if beatset[y][current_step]: color = DRUM_COLOR[y] trellis.pixels[(y, current_step)] = color # next beat! current_step = (current_step + 1) % 8 # draw the vertical ticker bar, with selected voices highlighted for y in range(4): if beatset[y][current_step]: r, g, b = DRUM_COLOR[y] color = (r//2, g//2, b//2) # this voice is enabled #print("Playing: ", VOICES[y]) mixer.play(samples[y], voice=y) else: color = TICKER_COLOR # no voice on trellis.pixels[(y, current_step)] = color # handle button presses while we're waiting for the next tempo beat # also check the accelerometer if we're using it, to adjust tempo while time.monotonic() - stamp < 60/tempo: # Check for pressed buttons pressed = set(trellis.pressed_keys) #print(pressed) for down in pressed - current_press: print("Pressed down", down) y = down[0] x = down[1] beatset[y][x] = not beatset[y][x] # enable the voice if beatset[y][x]: color = DRUM_COLOR[y] else: color = 0 trellis.pixels[down] = color current_press = pressed if ENABLE_TILT_TEMPO: # Check accelerometer tilt! tilt = accelerometer.acceleration[1] #print("%0.1f" % tilt) new_tempo = tempo if tilt < -9: new_tempo = tempo + 5 elif tilt < -6: new_tempo = tempo + 1 elif tilt > 9: new_tempo = tempo - 5 elif tilt > 6: new_tempo = tempo - 1 if new_tempo != tempo: tempo = max(min(new_tempo, MAX_TEMPO), MIN_TEMPO) print("Tempo: %d BPM" % tempo) time.sleep(0.05) # dont update tempo too fast! time.sleep(0.01) # a little delay here helps avoid debounce annoyances
Sequence Tracking Bar
When the board restarts, it will play through all four sound files, and then start running the sequence tracking bar forward
There are many ways to conceptualize an eight step sequence. I like to think of it as a single measure with 4/4 timing, meaning there are four beats to the measure and a quarter note gets the beat. So, our seqeunce is made of eight eighth notes, and the steps can be counted as:
"one-and-two-and-three-and-four-and"
Program Beat Patterns
Now, you can start making up some beats using the samples!
Kick
Try pressing the first and fifth buttons on the bottom row to start up a kick drum on the first and third beats of the measure (remember, there's a beat on every other button pad, with syncopated subdivision between them).
Snare
Now we'll add in a snare on step 3 and 8, which are the second beat and the "and" after the fourth beat as shown here.
Hi-Hats
Now let's lay in hi-hats on nearly every beat, as shown. While the Trellis M4 can play multiple sounds simultaneously, sometimes patterns sound nicer when there isn't too much going on on every step!
"Cowbell"
Lastly, we'll throw in an electronic blip sound that's reminiscent of the "cowbell" on a Roland TR-808. We'll put it on the two and then on the eighth note divisions of the three and four.
Here is what the sequence sounds like with the 808 style voices:
And here it is at a higher BPM with some genuine Adafruit warehouse sounds! You can increase and decrease the tempo just by tilting the Trellis M4 to the right or left. The Analog Devices ADXL343 accelerometer built right on the board detects the rotation and the CircuitPython code translates that data into tempo changes.
Text editor powered by tinymce.