Here’s something I’ve been working on for a while. It’s a digital guitar effects processor based on a PIC32MX.
It started with a conversation with my brother John. We were playing with my mini drum-machine, using the tune mode to mash the hell out of the samples whilst running it though his bass guitar amp with some heavy feedback. It sounded pretty cool, very NIN and got us onto the idea of making a digital effects pedal using the same microprocessor. The PIC32MX is a pretty capable device running at up to 50Mhz with loads of built-in peripherals including a 10bit ADC. Definitely possible I thought.
The tricky part was going to be handling the analogue input. That needed some research, as I had no idea what sort of voltage range to expect from a Guitar. Wikipedia indicates that the range could be from 100mV to 1V rms with peaks of +/-10V if you’re really going for it! That’s not something I’ve dealt with before, so a bit more Google-ing lead me to the Stomp Shield from open music labs. This is an Arduino shield aimed precisely at what I wanted. It provides the analogue front-end to condition the incoming audio signal for the ADC and uses an interesting arrangement of two PWM DACs to get a high-resolution audio output. It also provides low-pass filters on the input and output stages (“3-pole anti-aliasing filters for the inputs and outputs (10kHz cutoff)” from the wiki), twiddly potentiometers to control the input gain, the wet/dry mix, analogue feedback and the final output volume. Plus a general purpose rotary encoder for the UI. Nice!
The shield layout is intended for a “real” Arduino so It’s a bit of a mess in this state but it works pretty well.
The DP32 is a simple prototyping platform for the Microchip PIC32MX250F128B which is the USB capable twin of the chip I’ve been using in the drum-machine. Same 32Kb RAM and 128Kb flash but with hardware USB built-in.
The DP32 is an Arduino compatible platform and comes with the Chipkit bootloader pre-loaded on the PIC. I’ve never really used Arduino before but I thought that this might be fun to give it a go. At the very worst case I could drop it and just use my trusty Pickit 3 and MPLABX.
For me the Arduino environment has one really big bonus in for this application; The USB bootloader.
I’m building the thing but my brother is the guitarist who’ll be using it. A USB bootloader means he can upload new firmware without having to have any special hardware. This is going to be very handy as I’m in Spain and he’s in the UK. There are other USB bootloaders for the PIC, but Arduino has the ease-of-use end of things sewn up, certainly from a novice users perspective. The IDE is terrible and the lack of debugging is painful but having a really simple way of loading new code really wins this one.
It’s also nice to try C++ for a change, certainly makes cribbing from all those Arduino libraries easier.
The Stomp Shield has example code… in assembler… for an AVR. Fair enough but not at all useful in this instance.
So, I start from scratch on my first Arduino C++ adventure. It’s a bit of a mess as my understanding of how to structure a C++ project is a bit limited.
The application split into three routines; the “real-time” sampling/processing/output, the input handling and finally the UI.
The sampling/processing/output routine
This routine runs as an ISR (Interrupt service routine) triggered off a timer at 44.1Khz. It grabs the next ADC sample – 10bit signed integer – multiplies it by 64 (16bits), stores it in a signed 32 bit integer and passes it to the first effect which passes its output to the next effect and so on finally clipping the result back to 16bits and sending the resultant 16bit sample to the DAC. The DAC is made from two output compare modules configured for 8bit PWM at 156kHz. One module gets the high byte, the other the low byte. The Stomp Shield mixes these two signals at 1:256 ratio giving the final 16bit DAC. Very clever. Using two “small” PWMs rather than one “large” one means you can run them at a high frequency – 156Khz for 8bit – which is very easy to filter out of the final audio signal. Whereas a “large” PWM like I use on my drum-machine would run at a much lower frequency which is much closer to the frequency content of the audio signal and subsequently harder to filter out successfully.
Each of the effects is a self contained module with it’s own sample processing routine called from the ISR as well as it’s own input handling and display methods which are called from the UI routine. They receive an input sample and return an output sample modified by their own internal processing routine. They can have their own independent settings and can be enabled/disabled/modified independently from the other effects. The idea being to try and model each effect as being it’s own separate device.
The input handling also runs as an ISR. It triggers on change of state of any of the buttons or rotary encoder inputs. It runs at a lower priority than the processing ISR and is very brief just grabbing the input state and storing it for use by the UI. The idea being to keep it as short as possible so as not to effect the processing or UI routines.
Finally the UI runs in the main() code with a refresh rate of around 25Hz giving a nice fluid display on the OLED. It processes the input results stored by the input routine and handles the interface to the adjusting the different settings inside each effect. It also updates the screen as necessary and displays a simple VU/Level meter of the audio input/output of the system.
I’m using a heavily bastardised version of the Adafruit OLED and GFX libraries to drive the screen. This OLED uses a different driver chip (SH1106) than the Adafruit library is written for and I also wanted to use the PIC’s hardware SPI so I had to hack things around a lot. I also worked in proportional font handling in place of the simpler fixed width fonts which makes for a much nicer display and also make much better use of the screen space available. The typeface is a hand tweaked version of Liberation Sans – 10pt and is stored in the format generated by a handy tool called The Dot Factory.
I’d really like to work this OLED driver, hardware SPI and the proportional fonts back into the original library but my understanding of Arduino libraries is not so great at the moment so for now it’s a hacked – but working – mess.
So what does it do?
Right now I have implemented the following effects;
Combine this with the analogue feedback on the stomp shield for quite a nice echo.
It uses a delay line of 4096 samples (uint16) that is actually running at 1/8th the rate of the main routine. That means it’s storing a low pass filtered, down-sampled version of the input at 5.5Khz sample rate. There’s a single adjustable tap with a maximum delay of 740mS. It sounds a lot better than you’d think considering the effective sample rate.
“wobbles” the sound using a delay line and adjustable frequency sweep. The delay line is 2000 (uint16) samples running at the full sample rate of 44.1Khz.
Modulates amplitude of the incoming sound with an adjustable frequency and amplitude sine wave.
Reduces the quality and distorts the incoming sound in a sonically interesting way by reducing the sample rate and the sample resolution. Sample rate is adjustable from 1:1 (44.1khz) down to 64:1 (689Hz), resolution is adjustable from 16bits down to 1bit.
All of which can be run at the same time which can lead to some quite messy and interesting sounds. Especially when combined with the analogue feedback of the stomp shield.
I’m working on implementing a simple pitch-shift and also some sort of digital eq. filter based on IIR or FIR but at the moment they don’t work so well.
I had thought that the PIC’s 10bit ADC was going to be really limiting factor for the overall sound quality – after all garbage-in, garbage-out – but in actual fact it sounds very good. The PIC is running at 40Mhz which give lots of headroom to run the effects processing routines at 44Khz. Each active effect needs time to do its thing in the processing ISR, some take more time than others depending on what they’re doing. So I might experiment with dropping the sample rate a lower value, say 30kHz or 20Khz or something else to allow more time for more, or more complex effects.
I’ve spent long evenings writing the firmware whilst listening to Spotify on my headphones with the signal passed through it so I can attest to the quality.
So, where is the firmware? Good question. It’s coming. Once I have it tidied up I’ll publish it on Github.
The next step?
Thankfully both the DP32 and the Stomp Shield makers have been kind enough to provide Eagle CAD files for their boards. So I’ve spent my time in Eagle, welded them together and sent my PCB designs off to Dangerous Prototype’s new Dirty Cheap PCBs service.
Lets see how they turn out!