Lab 3

Mbed Synthesizer

Mbed Synthesizer is a project that turns the Mbed board into an 8-note synthesizer that uses a PS/2 keyboard as an input.  It has octave switching using the - and + keys, and uses the keys 1 through 8 as the note inputs.  The project utilizes the PS2 libraries to interface with the keyboard, specifically the PS2 Keyboard library, found in the cookbook.

The sound is generated by sending sinusoidal waves of different frequencies directly to the analog output.  To improve sound quality and reduce lag, the waves are stored in a pre-calculated value table, and different frequencies are produced from the table by changing which and how many values are read to comprise one period of a waveform. An interrupt is used to send the values from the table to the analog output at after a set amount of time has passed.

An alternative method that has been commented out may be implemented to produce the waveform values, in which the values are calculated in real-time.  This allows the pitch of each note to be much more exact, and makes the synthesizer play an exactly just-intoned major scale.  However, this method significanly lowers the sound quality, as the number of values that comprise each sound wave must be limited to prevent lag caused by the values' real-time generation.

Setup

The keyboard is connected to a PS/2 breakout board, and consists of 6 pins: CLK, GND, DATA, PIN2, VCC, and PIN6.

PIN2 and PIN6 are left unconnected.

PS/2 Pin --> mbed Pin
CLK        --> Pin 12
GND       --> GND
DATA      --> Pin 11
VCC       --> VU

Screenshots:

Slow Frequency waveform (low note)

High Frequency Waveform (high note)

The way the synthesizer currently works causes higher notes to be played at a lower sampling rate.

Possible Future Additions

  • Store larger and multiple value tables that can be loaded from flash memory, allowing for different sounds, pitches and effects.
  • Allow for playing multiple notes at the same time by creating different real-time varables for each note and adding the waves together in the output.

Code

#include "mbed.h"
#include "math.h"
#include "PS2Keyboard.h"

#define Pi 3.14159265
#define BUFFER 7500
AnalogOut aout(p18);
PS2Keyboard ps2kb(p12, p11); // CLK, DAT
Ticker interrupt;

int ans =0;
int i;
int j=0;
int freq=16;
int oct=8;
float values[BUFFER];

void attime() {
    if (ans==1) {
        aout=values[(j/freq)*oct];
        j++;
        if (j==(BUFFER-1)) {
            j=0;
        }
    }
    else {
        aout=0;
        if (j==BUFFER-1) {
            j=0;
        } 
    }
}
int main() {
    PS2Keyboard::keyboard_event_t evt_kb;
    
    //initialize audio values table
    for (i=0; i<BUFFER; i++) {
        values[i]= 0.5 + 0.5*sin(2*Pi*0.01*i);
    }
    interrupt.attach(&attime, 0.00001);
    
    while(1) {
        
        if (ps2kb.processing(&evt_kb)) {
            switch (evt_kb.scancode[0]) {
                case 0x16:
                    ans=1;
                    //freq=0.025;
                    freq=16;
                    break;
                case 0x1E:
                    ans=1;
                    //freq=0.028125; //whole step
                    freq=14;
                    break;
                case 0x26:
                    ans=1;
                    //freq=0.03125; //whole step
                    freq=13;
                    break;
                case 0x25:
                    ans=1;
                    //freq=0.03333; //half step
                    freq=12;
                    break;
                case 0x2E:
                    ans=1;
                    //freq=0.0375; //whole step
                    freq=11;
                    break;
                case 0x36:
                    ans=1;
                    //freq=0.041667; //whole step
                    freq=10;
                    break;
                case 0x3D:
                    ans=1;
                   // freq=0.046875; //whole step
                   freq=9;
                    break;
                case 0x3E:
                    ans=1;
                    //freq=0.05; //half step
                    freq=8;
                    break;
                case 0x4E:
                    oct=oct/2;
                    break;
                case 0x55:
                    oct=oct*2;
                    break;
                case 0xF0 :
                    ans=0;
                    break;
            }
                    
         }
        /*if (ans==1) {
            for (i=0; i<20000; i++) {
                aout= 0.5 + 0.5*sin(2*Pi*freq*oct*i);
            }
            
        }
        else {
            aout=0;
        } */
    }
}


0 comments

You need to log in to post a comment