Introduction: Dalek & Cyberman Voice Changer With Arduino Uno

About: I'm a software architect with an interest in Arduino, Raspberry Pi, electronics, robotics and generally making cool projects with my kids.

After building a full size Dalek in 2012, I wanted to make it talk and I didn't have the budget for the high end audio equipment that some people use and wanted to see if it would be possible to create a simple, low-cost voice changer using an Arduino.

After many different approaches, I was able to put together a simple shield for the Arduino Uno that lets you combine your voice with a sine wave to create a digital ring modulator effect. The frequency of the sine wave can be adjusted real-time with a potentiometer, so that you can change from a Dalek voice to a Cyberman voice very easily.

The main components are a 12-bit ADC for converting mic input to a digital signal, a 12-bit DAC for converting the modified digital sound back to an analog audio signal, and a low-pass filter (resistors and capacitors) for filtering out some of the noise from the signal.

In this instructable, I will explain the theory behind this board and hopefully provide enough information for building this on a breadboard.

The schema, board layout, and Arduino source code are all available for free from this git repo. I also sell kits in my Tindie store and from the Ultimate Voice Changer web site.

Step 1: How Does It Work?

The diagram above shows the overall workings of the voice changer shield.

The Arduino uses SPI to read data from the microphone and potentiometer (SPI is a high speed protocol so more than capable of audio processing).

The Arduino then manipulates the audio data by mixing it with a sine wave.

The modified audio data is then sent to the DAC over SPI. The DAC outputs an analog audio signal that passes through an RC filter (RC stands for Resister and Capacitor, by the way) which filters out some noise.

Finally the signal goes to a speaker. The signal isn't strong enough to driver a speaker directly though, so you'll need a speaker that has a built-in amplifier, like the popular "portable MP3 speakers" that you would connect to a phone or tablet.

Step 2: Schematic

At first glance, the schematic looks complex, but that is mostly because of all the headers that are broken out as convenient ways to attach inputs to the ADC.

There are really only three major areas of interest:

1. Arduino to ADC

The ADC (MPC3208) is connected to the Arduno via SPI (Arduino pins 13, 12, 11). Pin 10 is used for the Slave Select.

Note that VREF is connected to 3.3V and VDD is connected to 5V.

2. Arduino to DAC

The DAC (MPC4921) is also connected to the Arduno via SPI (Arduino pins 13, 12, 11). Pin 9 is used for the Slave Select. The DAC also has an additional connection for an LDAC latch that is conencted to Pin 8 on the Arduino.

As with the ADC, VREF is connected to 3.3V and VDD is connected to 5V.

3. High-pass and Low-pass Filter

The output of the MCP4921 DAC passes through both a low-pass and a high-pass filter, to remove some noise, before connecting to the audio jack.

The full schematic file (in Eagle PCB format) is available here.

Step 3: Board Layout

I chose this board layout in an effort to keep all of the SPI communication happening on the shortest possible path, since this is high frequency and could cause interface with the audio circuitry.

The low-pass and high-pass filters (all those capacitors and resistors) are kept close together, near to the audio jack.

There are lots of headers broken out to allow the flexibility of using all of the inputs to the ADC but so far I have only used two of them (one for the mic, and one for a potentiometer).

You can download the full board layout (in Eagle PCB format) here.

Step 4: Arduino Code

The bulk of the source code deals with SPI communication between the ADC and the DAC.

The interesting parts that I want to cover in this instructable are how the audio processing works to combine the voice with the sine wave.

This code reads a value from the Mic. This results in a number between 0 and 4095:

audio_in = read_adc(1);

The sine wave is generated in the setup method and stored in an array. The main loop then iterates over that array to pick the next value in the sine wave:

index += incr;
  if (index >= NUM_SINE_WAVE_POINTS)  {
    index -= NUM_SINE_WAVE_POINTS;
  }
  data = sineWave[index];

The audio signal and sine wave value are then multiplied together:

audio_out = 2047 + ((audio_in-2047) * ((data-127) / 127.0));

The full source code is available here.

Arduino All The Things! Contest

Participated in the
Arduino All The Things! Contest