Analysing some audio data recorded using the dsPIC

In my previous post, I used LTspice to do some simulation analysis on a simple audio amplifier circuit that can be used to connect a microphone to the analog input of a microcontroller. What I didn’t get around to saying in that post was that I also constructed the amplifier on a breadboard using an LM358 op-amp and we used it during today’s Robotics lecture to record some audio data with a dsPIC30F4011 microcontroller.

The C code shown below was used on the dsPIC to record audio from the microphone and transmit it to the PC via the PICkit 2 programmer. This code performs the following steps repeatedly:

  1. Record a 200-sample frame of audio at a sampling frequency of 10kHz,
  2. Transmits the 200 samples to the PC via a serial link as plain text,
  3. Wait for 1 second.

Here’s the code:

//
// dsPIC30F4011 audio example
// Written by Ted Burke
// Last updated 5-11-2013
//

#include <xc.h>
#include <stdio.h>
#include <libpic30.h>

// Configuration settings
_FOSC(CSW_FSCM_OFF & FRC_PLL16); // Fosc=16x7.5MHz, Fcy=30MHz
_FWDT(WDT_OFF);                  // Watchdog timer off
_FBORPOR(MCLR_DIS);              // Disable reset pin

// Function prototypes
unsigned int read_analog_channel(int);

int main()
{
    // Setup UART
    U1BRG = 48;            // 38400 baud @ 30 MIPS
    U1MODEbits.UARTEN = 1; // Enable UART
    
    // Configure AN0-AN8 as analog inputs
    ADCON3bits.ADCS = 15;
    ADCON1bits.ADON = 1;

    int n, s[200]; // audio buffer (20ms @ Fs=10kHz)
    while(1)
    {
        // Record 200 samples into the buffer
        for (n=0 ; n<200 ; ++n)
        {
            s[n] = read_analog_channel(0);
            __delay32(3000); // 100us gives Fs = 10kHz
        }
        
        // Send samples to PC
        for (n=0 ; n<200 ; ++n)
        {
            printf("%d ", s[n]); // print one sample
        }
        printf("\n\n"); // blank line between frames
        
        __delay32(30000000); // 1 second between frames
    }
        
    return 0;
}

// This function reads a single sample from the specified
// analog input. It should take less than 5us when the
// microcontroller is running at 30 MIPS.
// The dsPIC30F4011 has a 10-bit ADC, so the value
// returned is between 0 and 1023 inclusive.
unsigned int read_analog_channel(int channel)
{
    ADCHS = channel;          // Select the requested channel
    ADCON1bits.SAMP = 1;      // Start sampling
    __delay32(30);            // 1us delay @ 30 MIPS
    ADCON1bits.SAMP = 0;      // Start Converting
    while (!ADCON1bits.DONE); // Should take 12 * Tad = 3.2us
    return ADCBUF0;
}

As usual, I used the following very simple build script to compile my program using Microchip’s XC16 C compiler (save the C code above as “main.c” and save this build script as “build.bat” in the same folder):

xc16-gcc main.c -mcpu=30F4011 -Wl,--script=p30F4011.gld
if errorlevel 0 xc16-bin2hex a.out

During the lecture, we recorded some snippets of audio. The example shown in the graphs below was the sound of a high-pitched whistle close to the microphone (thanks Aron!). The incoming data (transmitted from the dsPIC to the PC) was captured using the UART tool in the PICkit 2 application. I simply copied the list of 200 numbers representing one frame of audio and pasted it into Notepad++ where I saved it as a plain text file called “data.txt”. It looked like this:

Audio data pasted into Notepad++ to be saved as a plain text file

I used Octave to load the frame of raw audio data from the file “data.txt” and display the following plot:

One 200-sample frame of audio data recorded using the dsPIC microcontroller

The strong oscillation caused by the whistling sound is clearly visible throughout the entire frame of audio. There is a lot else going on too. Unfortunately, we ran short of time at the end of class, but what I was trying to produce was the following magnitude spectrum of the frame of audio, in which the whistle has produced a single dominant peak at approximately 2kHz.

Magnitude spectrum of one 200-sample frame of audio data recorded using a dsPIC microcontroller

I filtered out the large DC component before plotting, but there are still large values present at very low frequencies (especially the second bin – 50Hz). This is not surprising since a large low frequency drift seems to underlie the entire frame. This kind of very low frequency drift is most likely to manifest itself primarily in the first bin above DC (50Hz in this case). Ignoring the first few frequency bins, the peak caused by the whistle clearly dominates the spectrum and would be very easy to detect automatically.

I used Octave to plot the graphs shown above, but the same code should also work in MATLAB. This is the complete M-file:

%
% audiospectrum.m
% written by Ted Burke - 5-11-2013
% Load a frame of audio data from a plain
% text file, plot the waveform and plot
% the magnitude spectrum of the signal.
%

% Load audio data from file
x = load('data.txt');

% Set frame / sampling properties
Fs = 10000; % sampling frequency (samples / second)
N = length(x); % frame length in samples

% Plot the audio waveform in digital units
figure;
plot(x);
title('One frame of audio signal (200 samples, Fs=10kHz)');
xlabel('Sample number, n');
ylabel('ADC value [du] - 10-bit unsigned integer');

% Subtract out the DC component (the 3V bias voltage)
x = x - mean(x);

% Calculate the magnitude spectrum
X = fft(x); % Get DFT of audio data
X = X(1:N/2); % spectrum is symmetrical - just use half
P = abs(X); % convert from complex values to magnitudes
f = [0:(N/2)-1] * (Fs / N); % create a list of frequencies

% Plot the magnitude spectrum
figure;
plot(f,P);
title('Magnitude spectrum of audio frame');
xlabel('Frequency [Hz]');
ylabel('Magnitude');

In a future post, I’ll explain how to use interrupts to do the sampling and how to analyse the audio data on the dsPIC to identify some useful features (e.g. amplitude, zero crossings, frequency content).

Advertisements
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s