Make you own guitar effects using GNURadio Companion

The gnuradio guitar effect machine setup. The guitar belongs to my son, who's six years old. 
A few days ago, I wrote a post about processing ultrasound using gnuradio. This was also intended as an example for the signal processing course I'm teaching. I'm now teaching the Fourier series and needed a real life example of a rectangular waveform. I came up with the idea of using a combination of an electric guitar and a overdriven amplifier (distortion effect) to produce a rectangular waveform. A highly compressed sinusoidal signal is essentially a rectangular waveform.

How does the distortion effect work? The basic principle is quite simple. A signal is distorted if the response between input and output is not linear. A simplified model of an overdriven amplifier is the following: signal is amplified linearly up to a certain threshold amplitude. Beyond this amplitude, the signal is limited to a threshold voltage. In python, this would be modeled using the following function:

def comp(self,x):
    return(n.sign(x)*n.minimum(n.abs(self.a*x),self.b))

Here self.a is the amplification factor, and self.b is the maximum threshold amplitude. This larger self.a, the more gain. The smaller self.b, the more clipping occurs. This is illustrated by the relatively crude sketch shown below:

Overdriven clipping amplifier model. 
It is quite easy to make custom gnuradio blocks with Python, so in no time at all, I had a custom block that implemented the compression filter.  I implemented the simple clipping amplifier. This is python, so you can easily modify this and use, e.g., a spline function to model the response of your favorite guitar amplifier.

import numpy as n
import scipy.interpolate as sint
from gnuradio import gr
import matplotlib.pyplot as plt
class compress(gr.sync_block):

    def comp(self,x):
        return(n.sign(x)*n.minimum(n.abs(self.a*x),self.b))
 
    def __init__(self, a, b):
        self.a=a   #  gain
        self.b=b  # clip level

        gr.sync_block.__init__(self,
            name="compress",
            in_sig=[n.float32],
            out_sig=[n.float32])

    def work(self, input_items, output_items):
        in0 = input_items[0]
        out = output_items[0]
        # compress signal using spline function self.comp
        # limit output amplitude to 0.5
        out[:]=self.comp(in0)
        return len(output_items[0])

I then made a small gnuradio companion flowchart to allow audio input (guitar connected to microphone port on the audio card) to be fed through my filter block and played back through the audio card. The code is available on github.

GNURadio Companion based guitar effect, spectrum analyzer, and scope flowgraph.

Guitar effect in action. A demonstration of a sinusoidal signal being filtered into a rectangular waveform.

Here's an audio clip with output from gnuradio to demonstrate what the output of the filter sounds like. Initially, the signal is clean, and then the distortion is turned on. Disclaimer: I don't know how to play the guitar very well and the guitar was way out of tune.

Comments

Popular Posts