The MIDI mod wheel already controls sustain. Now pitch bending has come to the WAV Trigger! I spend the weekend implementing real-time sample-rate conversion and got it hooked up to MIDI Pitch Bend messages. At the moment, this means that a MIDI controller pitch wheel can control the playback pitch/speed of the WAV Trigger by plus or minus a fixed number of semi-tones. A firmware update with this new feature is forthcoming, after I sort out a few details of how to control this new effect.
A little background…
In the days of hardware samplers and limited/expensive memory, sample-rate conversion was used to spread a single sample over a number of MIDI keys, thereby saving memory. This meant that each voice had to have it’s own sample-rate conversion engine. With many gigabytes now available on microSD cards, this is no longer necessary, since you can afford to have an individual sample for every note on the keyboard. (I admit that this is time-consuming to set up, but you only have to do so once.) Pitch bend, on the other hand, usually affects all notes equally.
The new sample-rate conversion in the WAV Trigger occurs in the final output stage rather than on each individual voice. At the moment, all voices are affected equally, allowing you to bend chords like the pitch control on a Mellotron. I’m considering a 2-channel approach, whereby one channel will be fixed and the other processed through the sample-rate conversion engine, and tracks can be designated to play through one or the other channel. (Both channels are then mixed to the stereo output.) This would allow you to, for example, have a stereo backing track at a fixed sample rate while playing instrument samples with pitch bend along with it.
It makes sense for the MIDI pitch wheel to allow pitching up or down by a value corresponding to a whole musical interval, usually some number of semi-tones. I plan to also add control through the serial protocol, but allow setting the rate to any arbitrary value between say 0.5x and 2.0x. I’ve been thinking it would be fun to try to build a digital Theremin using an Arduino to sense hand positions and send serial volume and pitch control messages to the WAV Trigger playing a sine wave sample. That should work, right?
The Rock Band 3 keyboard happens to also be a nice battery powered MIDI keyboard controller that you can pick up on eBay for 20 bucks or so. With a WAV Trigger and a little electronic glue, which I’ll explain in this article, you can make a self-contained, velocity-sensitive, multi-bank sample playback instrument. The Rock Band 3 keyboard buttons and left hand controller allow you to re-map the keys, change sound banks and adjust note release time (sustain) on the fly. I’ll be using classic Mellotron sounds here, but you can easily create your own sample banks using a VSTi software synth.
For those of you just tuning in, the WAV Trigger is a high-fidelity polyphonic audio player. It has 14 “voices” to play and mix uncompressed, stereo, 44.1kHz wav files directly from a microSD card. Audio can be triggered either from digital inputs or serial commands, and latency averages around 8ms (12ms max). The serial control port also supports MIDI protocol, and in MIDI mode it’s velocity sensitive (MIDI velocity maps to volume) and supports adjustable release times (sustain). The mixing engine includes a voice-stealing algorithm so that new MIDI notes take precedent if all 14 voices are being used, and the oldest playing voice is “stolen” to play the new note.
Step 1: Prep your WAV Trigger. We’ll need to provide 5V to our MIDI input interface circuit, and the easiest way to do this is to close the solder jumper on the WAV Trigger that connects the on-board 5V to the serial connector. The WAV Trigger doesn’t ship from SparkFun this way, because people might connect an FTDI Basic at the same time that they’re powering the WAV Trigger from the barrel connector. I always close this jumper because it allows me to power the WAV Trigger from the FTDI basic.
I also strongly advise that you install post headers or receptacles in any WAV Trigger connector that you’re planning to use. PCB connector pads are not meant for direct soldering and I’ve seen too many pads ripped off boards because people solder directly to them and don’t provide strain relief.
While you’re at it, update your firmware from the download page. The latest firmware v1.04 contains new MIDI features that are used by the Rock Band 3 keyboard.
Step 2: Build the MIDI Input interface circuit. The RB3 keyboard has a standard 5-pin circular DIN MIDI Out port on its right side. We need to convert the output’s 20mA current loop to a logic level signal that can feed the WAV Trigger’s RX pin, and this is done with an opto-isolator. Here’s the circuit:
As you can see, it’s pretty simple – just a single 8-pin IC, one diode and two resistors – and is easy to build on a small breadboard. I used an 6N138 optoisolator, but the PC-900 works equally well. The diode is a 1N914, but any small signal diode should work. I also sacrificed a MIDI cable and soldered posts on the two wires we’ll be using to make it easy to insert into the breadboard. Here’s the completed MIDI In circuit:
Step 3: Connect the MIDI Input circuit to the WAV Trigger. There are only 3 connections required: 5V, GND and the logic level TX output of the Opto to the WAV Trigger RX. Here are the connections:
And here’s the completed assembly:
Step 4: Prepare the WAV Trigger’s microSD card. In MIDI mode, the WAV Trigger maps incoming MIDI note numbers to track numbers using an internal MIDI bank number. In the default bank 1, MIDI note number 48 maps to track “048xxx.wav” and so on. Each MIDI bank adds 100 to the track number, so that in bank 2 MIDI note number 48 maps to track “148xxx.wav”, in bank 3 MIDI note number 48 maps to track “248xxx.wav” and so on. In this way, you can have up to 10 complete sets of sample tracks for the MIDI key range of notes 0 – 99.
You can change banks in any one of 3 ways:
Change the MIDI Channel that your MIDI Controller is transmitting on. The MIDI Channel number (starting at 0) is added to the bank number.
Install buttons on two of the WAV Trigger’s trigger inputs and use the MIDI BankUp and MIDI BankDn trigger functions.
Send MIDI Program Change messages from your MIDI Controller.
We’ll use the last method here because the Rock Band 3 keyboard supports this feature using its front panel buttons. How convenient.
To get you started, here are the track files for 5 complete sets of classic Mellotron sounds, sampled from an actual Mellotron, courtesy of Leisureland, USA. The track filenames have already been assigned to map the sounds to the correct MIDI Notes in banks 1 through 5.
Copy all files to your microSD card root directory. Run the InitMaker application, enable MIDI on the serial port and save the init file to the microSD card. Install the microSD card into the WAV Trigger.
Step 5: Connect everything up and play! Plug the MIDI cable into the Rock Band 3 keyboard, connect your amp or powered speakers to the WAV Trigger’s audio out (or use the on-board mono amp with an 8-Ohm speaker), supply power to the WAV Trigger and turn on the Rock Band 3 keyboard. If all is well, you should hear the violins in bank 1 when you play the keyboard.
Here’s a quick summary of the functions available using the RB3 keyboard front panel controller buttons. First up, The 1 and B buttons shift the keyboard up and down an octave at a time, allowing access to more notes than the physical 25 keys on the controller. This function is internal to the RB3 keyboard and simply shifts the note numbers that the keyboard sends up or down 12 note numbers (one octave.)
Next, the 2 and A buttons increment and decrement the WAV Trigger’s MIDI Bank number, thereby changing the sound banks. This works because these buttons send MIDI Program Change messages.
The – button is a panic button, and tells the WAV Trigger to immediately stop all sounds. This is the same as MIDI All-Notes-Off. Technically, this button sends the MIDI RealTime Stop command (0xFC) and I’ve added code to the WAV Trigger to stop all voices when this is received.
Finally, the continuous controller on the left “handle” of the RB3 keyboard adjusts the WAV Trigger’s release time or sustain. This pad sends MIDI Mod Wheel Controller data which I’ve mapped to MIDI release time in the WAV Trigger.
That’s it. Here’s a short demo video of all this in action. (Please keep in mind that I’m a guitar player, not a keyboard player!) Please consider sharing if you create additional sound banks.
I’ve been torture testing firmware v1.00 for over two weeks now. Using an Arduino UNO and the serial control port to alternately max out with 14 voices for a period of time, then letting the WAV Trigger enter low-power sleep mode, waking it up and repeating. I’d strongly advise that everyone update to this version – there’s no reason not to and many reasons to do so.
I also just updated the InitMaker app to include support for the new low-power sleep option. After taking some actual measurements, it appears that putting the WAV Trigger into sleep mode results in a reduction of supply current from around 80mA (quiet) to around 5mA. I’m assuming that the majority of this sleep current is coming from the microSD card, which remains powered. In addition to not having hardware support for removing power, the SD initialization time would likely increase the time it takes to come out of sleep mode. So I deem this to be a reasonable trade-off.
I just posted a firmware update that adds 2 more voices for a grand total of 14 stereo voices. I think I’m getting close to what’s possible with this architecture. It’s a trade-off between microSD card access time, the amount of RAM available for buffering microSD card audio data and processor cycles. I might be able to get one more with a lot of effort, but I believe that 15 would likely be the theoretical limit.
This version also adds a low power “sleep” mode option. Adding the following line to the init file:
where N is seconds, will cause the WAV Trigger to enter a low power Sleep Mode after N seconds of inactivity. You’ll know it’s in Sleep Mode because it will blink 3 quick flashes and then “heartbeat” flash will stop completely. Any trigger activity will wake the WAV Trigger, the heartbeat will resume and it will immediately play a track if that trigger is assigned to do so. There is probably a small latency penalty paid by the trigger that does the waking, since the WAV Trigger has to restart the audio subsystem before it can play the track.
I still have to make measurements, but it’s safe to say at this point that in Sleep Mode mode, the WAV Trigger draws only about 5 milli-Amps. I’ll measure and post this spec on the product page along with the actual wake-up trigger latency.
Update: The latest version of the InitMaker (v1.04 app) now supports the #LPWR entry. Get it on the downloads page.
Just learned that the Rock Band keyboard has a MIDI out, making it a great, inexpensive candidate for a keyboard controller for the WAV Trigger.
Several people have told me that they’re using simple MIDI keyboards that don’t provide any means for switching MIDI channel numbers (the way switch between sound “banks”) or setting controller numbers (for controlling attack and release times.) Also, some of these keyboards don’t have particularly good velocity sensitivity and there’s been several requests to disable the mapping of velocity to volume.
I just posted firmware v0.87 which provides a number of new features for MIDI users. I haven’t had a chance to add these features to the InitMaker utility, so for the time being, to use them you’ll need to edit the init file by hand (using a text editor such as Notepad or TextEdit.)
1) Disabling velocity sensitivity: In the init file, change the line “#MIDI 1” to “#MIDI 3”. This will cause all MIDI notes to play as if the velocity was 127.
2) Setting the MIDI release time: This is the “fade-out” or sustain time when a note is released, set to 0 by default. A longer release time is particularly useful for making sounds such as strings sound more lush. Adding the following line to the init file: “#MREL n”, where n = 0 to 127, will set the release time between 0 and 2000ms (2 seconds) for all notes. Keep in mind that while a note is fading out, it’s still using a voice, so long release times will increase the number of voices used while playing.
3) Using trigger inputs to switch between sound banks: Two new trigger functions increment and decrement a bank number variable, which adds a multiple of 100 to the track number when playing MIDI. Until these trigger functions are added to the InitMaker utility, the easiest way to add them is as follows:
For the trigger that you want to increment the bank, set the trigger function to “Volume Up”, and for the trigger you want to decrement the bank, set the trigger function to “Volume Dn”. Save the init file and then edit. For the Volume Up trigger change the next to last parameter value from “8” to “10”, and for the Volume Dn trigger, change the next to last parameter from “9” to “11”.
Incrementing the bank number adds another 100 to the track number, on top of the 100 added by each MIDI channel number. The bank number wraps from 9 back to 0. If you plan to use the bank increment / decrement feature, I suggest leaving your MIDI keyboard set to MIDI channel 1 (which is actually 0). You’ll be starting with tracks 000 to 099, and each press of the increment trigger will add another 100 to the MIDI note number (100 to 199, 200 to 299 and so on.)
The MP3 Trigger has been out at least 5 years now, and it’s been a great product. In that time, however, many similar solutions have been introduced – all based on the VLSI MP3 decoder. Indeed, if you’re willing to spend time writing code and experimenting with Arduino libraries, you can get pretty close to the functionality of the MP3 Trigger for less money. And with the advent CPU’s faster than the lowly 8-bit PSoC, you can probably even get higher bit-rate audio. While the MP3 Trigger still may make sense if you want a practically zero-effort MP3 player solution, the truth is that there are lots of ways to play single MP3 tracks from a microSD card available today.
The problem with all VLSI-based MP3 players is that because the VLSI device is a hardware decoder, it can only process a single MP3 stream at a time. Translation: you can only play one track at a time. If you want to play a second track, you first have to stop the first. You can’t even crossfade, cause that would require playing two tracks during the overlap.
Another big problem with all MP3 player solutions is audio compression! The only reason to compress is if you have limited memory or a small pipe. With microSD cards, neither is an issue. And the overhead of decompression is a pain, requiring special hardware (VLSI) or software, as well as a license. And as soon as you want to mix even two MP3 tracks, it gets complicated fast.
Now there’s the WAV Trigger. As far as I know, there is currently nothing else like it out there. It’s the same size and price as the MP3 Trigger, but blows it (and all other VLSI MP3 players) away in terms of capability. With the most recent firmware update, it supports up to 14 simultaneous uncompressed CD quality (16-bit, 44.1kHz, stereo) tracks, with trigger latency clocking in at around 8 msecs. It has built-in support for individual track volumes, smooth fade-ins, fade-outs and cross-fades, and the ability to start and play 14 tracks in perfect sample sync. In addition to a much richer serial control protocol, its trigger inputs can be individually programmed for active high or low, level or edge triggered, contact closure or logic level control. It has a true line-level stereo output and an on-board 2W mono amp to drive a speaker directly. It has a cross-platform utility to create and generate the init file used to set many programmable options. And the serial interface even supports MIDI, enabling the WAV Trigger to be a true 14-voice polyphonic sampling instrument.
I fully anticipated that sales of the WAV Trigger would cut into those of the MP3 Trigger. Why would anyone purchase the MP3 Trigger when they could get the WAV Trigger for the same price? Other than play an MP3 track, there’s nothing an MP3 Trigger can do that the WAV Trigger can’t do better, and the WAV Trigger can do so many more things.
Yet evidently, the MP3 Trigger continues to outsell the WAV Trigger by a significant margin. I can only assume it’s that people either don’t yet know about the WAV Trigger or don’t really understand what it’s capable of. Or perhaps they just don’t need it. Maybe I misread what people are doing with embedded audio players. It’s true that you have to convert MP3 audio files to wav files, and maybe that throws people if they just want to grab MP3 files off the web and copy them to a flash card.
In any event, I hope this changes. With the power of an ARM Cortex-M4 available, there are lots of features still to add to the WAV Trigger. But the practical thing to do is to wait and see if people want it first.
For any of you anxious to be on the cutting edge, I just posted a preliminary version of the next major firmware update for the WAV Trigger. An optimized mix engine now supports 12 stereo voices by default with pretty much any microSD card – that’s a 50% speed improvement over the previous version. At the same time, the trigger latency (time from an active trigger to sound coming out) has been halved to a maximum of 12 msecs, typically 8 msecs. Check out the evidence:
In addition, the WAV Trigger now provides firmware volume faders for smooth volume transitions: fade-ins, fade-outs and crossfades between tracks. The WAV Trigger Arduino Serial Library has been updated with functions that take advantage of the new faders, making it easy to create smooth transitions between tracks without Arduino processor overhead.
Attack (fade-in) and Release (fade-out) times have been added to the MIDI implementation so that MIDI controllers can be used to dynamically change attack and release times while playing as a polyphonic sampler. This feature, along with the increased voices and reduced latency, makes the WAV Trigger even more of a musical instrument.
And wait, there’s more! Due to popular request, I’ve added a new Load Track function that allows preloading up to 12 tracks, and a new Resume All In Sync command that starts all preloaded tracks at the exact same sample, meaning that up to 12 tracks can be started and played completely sample-locked with one another.
Also, I fixed a long-standing bug with long FAT32 directories that prevented tracks from being played from cards that had a lot of deleted directory entries. (The fix, quick-reformatting the card, is no longer necessary.)
The new firmware is available on the download page, and the new serial commands have been added to the Online User Guide. Please let me know if you have any issues.
The WAV Trigger has been out for several months now, and I’ve already made a few tweaks to the firmware as a result of feedback. Overall, it’s pretty complete and stable, and I’m quite happy with it.
I’ve been working on a major firmware update that I’ll probably issue as a beta release in the coming weeks. In addition to an optimized mixing engine that simultaneously increases the number of voices/tracks (for the same speed microSD card) and even further reduces the track start latency, I’ve also implemented built-in programmable track faders, allowing for smooth attacks, releases, ramps and cross-fades. I’ve even added the attack and release time to the MIDI implementation making the WAV Trigger even more like a polyphonic MIDI hardware sampler. I’ll shortly add support for the track faders to the Arduino Serial library.
There are a number of additional features and enhancements that I’ve been contemplating, but I want to make sure that I’m working on things that customers will find useful, not just that I think are cool. To that end, here’s a list of features that I’ve been thinking about. Any feedback will help me decide which of these, if any, to do:
1) A serial command to return WAV track filenames. The thing that makes this non-trivial is support for long filenames, which involve multiple FAT directory entries and potentially long serial messages. Returning the 8-character DOS compatible filename would be much easier, but I’m not sure that’s what you’d want.
2) A mechanism for starting multiple tracks in sample-sync with one another. At present, it’s possible that closely spaced triggers or serial track start commands will result in the respective tracks being out of sync by one or more audio buffers. I’m not completely sold on the need for this, since if you want to play 2 tracks in sync with one another, why not just mix them down into a single WAV file? But I may be missing the point.
3) EQ on the output. Probably 3-band – low, mid, high – with gain settings set with an init file command as well as via real-time serial commands.
4) A playlist file. This would likely take the form of a file containing a list of track numbers, and a trigger option that would sequentially play the tracks from the list.
For those of you interested in trying to get more than 8 stereo voices, there is a so-far undocumented init file command that will let you experiment with more. “#VOIC n”, where n is desired number of voices, allows you to increase the number up to a maximum of 16. You’ll need to add this command to an existing init file using a text editor, since the WT-InitMaker app does not support it. You can confirm the setting using the WT-Remote app – the “Get Info” button reports the number of available stereo voices.
In most cases, it’s probably safe to increase the number of voices to at least 10. 8 was chosen as the default to be compatible with the slowest microSD card I’ve encountered. Without a scope, you’ll know when you’ve hit the limit for your card when you start to hear crackling or pops after layering the max number of tracks. For those of you with a scope, PC15 (pin 4 on the STM32F4) duty cycle indicates the amount of time taken by the mixer. 100% is bad.
The limiting factor for the number of voices is what I call the “access time” of the microSD media, which is different than the sustained bitrate used for the speed ratings. Unlike sequentially reading a single file, mixing WAV tracks involves reading a small number of sectors from files spread all over the FAT disk. The critical issue is the time it takes between asking for a new sector read and when the card actually starts providing that data. I’ve not found this parameter to be documented by the microSD card manufacturers, so you’ll just have to experiment with it.
UPDATE 5/18/2015: This post only applies to the original WAV Trigger version, WIG-12000, which was replaced with WIG-12897 about 8 months ago. If you have any doubts as to which version you have, see this post.
The initial run of the WAV Trigger is missing a capacitor on the input to the on-board speaker amplifier, causing a DC offset on the speaker output connector. At a minimum, this causes a click on enabling the amp and clipping for high volume output signals, and in some cases interferes with operation of the WAV Trigger when certain speakers are connected. The board design has already been updated and the fix will make it’s way into the production pipeline soon. In the meantime, for those of you utilizing the on-board speaker amp, here’s the fix. You do not need to do this if you aren’t planning to enable the on-board amplifier (it’s disabled by default.)
You’ll need to add a series 0.39uF non-polarized capacitor to the to the input of the LM4990 amp, between LOUTL and R9. The easiest way to do this is to cut a single trace on the back of the board, scrape away the solder mask from the ends of the trace near the cut, and solder the cap across the resulting gap. See photos below. I apologize for the inconsistent PCB color (green) in the second photo – I wanted to post this ASAP.
First, a photo showing the location of the trace on a production board:
And here’s a photo of the capacitor, in this case a ceramic SMT cap, soldered across the gap in the trace. If you happen to have a through-hole cap available, you can solder the leads to the vias at either end of the trace (after you cut it.)
Adding this capacitor completely fixes the issue, eliminating any popping when the amplifier is enabled or disabled, and allowing you to get the full audio volume range from your speaker.