Program to record speech audio into RAM and then play it back, moving Billy Bass's mouth in sync with the speech.

Dependencies:   mbed

Remember Big Mouth Billy Bass?

I've made a simple demo program for him using the Freescale FRDM-KL25Z board. I've hooked up the digital I/O to his motor driver transistors and pushbutton switch.

This program records 1.8 seconds of speech audio from ADC input when the pushbutton is pressed, then plays the audio back with Billy Bass's mouth controlled so that it opens during vowel sounds.

The ADC input is driven from a microphone and preamplifier, via a capacitor and into a resistor divider connected to the +3.3V supply pin to provide mid-range biasing for the ADC signals.

The DAC output is connected to his audio amplifier input (to the trace that was connected to pin 10 of the controller IC). I had to provide a DC bias using the DAC to get the single transistor amplifier biased into proper operation.

For more on the method of vowel recognition, please see the paper: http://www.mirlab.org/conference_papers/International_Conference/ICASSP%201999/PDF/AUTHOR/IC991957.PDF

Y. Nishida, Y. Nakadai, Y. Suzuki, T. Sakurai, T. Kurokawa, and H. Sato. 1999.

Voice recognition focusing on vowel strings on a fixed-point 20-MIPS DSP board.

In Proceedings of the Acoustics, Speech, and Signal Processing, 1999. on 1999 IEEE International Conference - Volume 01 (ICASSP '99), Vol. 1. IEEE Computer Society, Washington, DC, USA, 137-140. DOI=10.1109/ICASSP.1999.758081 http://dx.doi.org/10.1109/ICASSP.1999.758081

Committer:
bikeNomad
Date:
Tue May 14 17:19:45 2013 +0000
Revision:
2:5bcd2f55a294
Parent:
1:2fa375aacece
Child:
3:c04d8d0493f4
Got 7.9KHz analog sampling working

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bikeNomad 0:1ddd40d843cb 1 #include "mbed.h"
bikeNomad 1:2fa375aacece 2 #include "FastAnalogIn.h"
bikeNomad 1:2fa375aacece 3 using namespace NK;
bikeNomad 1:2fa375aacece 4
bikeNomad 1:2fa375aacece 5 // Power:
bikeNomad 1:2fa375aacece 6 // Power GND J9/14
bikeNomad 1:2fa375aacece 7 // Vin (6V) J9/16
bikeNomad 0:1ddd40d843cb 8
bikeNomad 1:2fa375aacece 9 // Digital:
bikeNomad 1:2fa375aacece 10 DigitalOut tail(PTA13); // J3/2
bikeNomad 1:2fa375aacece 11 DigitalOut mouth(PTC12); // J3/1
bikeNomad 1:2fa375aacece 12 DigitalOut head(PTC13); // J3/3
bikeNomad 1:2fa375aacece 13 DigitalIn pushbutton(PTD5); // J3/4
bikeNomad 1:2fa375aacece 14
bikeNomad 1:2fa375aacece 15 PwmOut redLED(LED_RED);
bikeNomad 1:2fa375aacece 16 PwmOut greenLED(LED_GREEN);
bikeNomad 1:2fa375aacece 17 PwmOut blueLED(LED_BLUE);
bikeNomad 0:1ddd40d843cb 18
bikeNomad 1:2fa375aacece 19 // Analog:
bikeNomad 1:2fa375aacece 20 // GND J3/14
bikeNomad 1:2fa375aacece 21 // VrefH J3/16
bikeNomad 1:2fa375aacece 22 FastAnalogIn microphone(PTB0); // J10/2
bikeNomad 1:2fa375aacece 23 AnalogOut speaker(PTE30); // J10/11
bikeNomad 1:2fa375aacece 24
bikeNomad 1:2fa375aacece 25 // Communications:
bikeNomad 1:2fa375aacece 26 // Serial uart1(PTC4, PTC3);
bikeNomad 1:2fa375aacece 27 Serial pc(USBTX, USBRX);
bikeNomad 1:2fa375aacece 28
bikeNomad 2:5bcd2f55a294 29 const unsigned SAMPLE_RATE_HZ = 7889;
bikeNomad 1:2fa375aacece 30 const unsigned SAMPLE_PERIOD_US = (1000000U / SAMPLE_RATE_HZ);
bikeNomad 2:5bcd2f55a294 31 const unsigned SAMPLE_BUFFER_SIZE = 9000;
bikeNomad 1:2fa375aacece 32
bikeNomad 1:2fa375aacece 33 Ticker sampleTicker;
bikeNomad 2:5bcd2f55a294 34 Timer timer;
bikeNomad 1:2fa375aacece 35
bikeNomad 2:5bcd2f55a294 36 uint8_t sampleBuffer[SAMPLE_BUFFER_SIZE]; // 1 second buffer
bikeNomad 1:2fa375aacece 37 uint8_t * volatile nextSample;
bikeNomad 1:2fa375aacece 38 unsigned volatile samplesRemaining;
bikeNomad 1:2fa375aacece 39
bikeNomad 1:2fa375aacece 40 extern "C"
bikeNomad 1:2fa375aacece 41 void ADC0_IRQHandler(void)
bikeNomad 0:1ddd40d843cb 42 {
bikeNomad 1:2fa375aacece 43 if (samplesRemaining) {
bikeNomad 2:5bcd2f55a294 44 *nextSample++ = microphone.read_u16_nowait() >> 8;
bikeNomad 2:5bcd2f55a294 45 microphone.start_read();
bikeNomad 1:2fa375aacece 46 samplesRemaining--;
bikeNomad 1:2fa375aacece 47 } else {
bikeNomad 1:2fa375aacece 48 microphone.disable_interrupt();
bikeNomad 2:5bcd2f55a294 49 microphone.abort_read();
bikeNomad 2:5bcd2f55a294 50 timer.stop();
bikeNomad 0:1ddd40d843cb 51 }
bikeNomad 0:1ddd40d843cb 52 }
bikeNomad 0:1ddd40d843cb 53
bikeNomad 1:2fa375aacece 54 void playAudioSample()
bikeNomad 1:2fa375aacece 55 {
bikeNomad 1:2fa375aacece 56 if (samplesRemaining) {
bikeNomad 1:2fa375aacece 57 speaker.write_u16(*nextSample++ << 8);
bikeNomad 1:2fa375aacece 58 samplesRemaining--;
bikeNomad 1:2fa375aacece 59 } else {
bikeNomad 1:2fa375aacece 60 sampleTicker.detach();
bikeNomad 2:5bcd2f55a294 61 timer.stop();
bikeNomad 1:2fa375aacece 62 }
bikeNomad 1:2fa375aacece 63 }
bikeNomad 1:2fa375aacece 64
bikeNomad 1:2fa375aacece 65 void resetSampleBuffer()
bikeNomad 1:2fa375aacece 66 {
bikeNomad 1:2fa375aacece 67 nextSample = sampleBuffer;
bikeNomad 2:5bcd2f55a294 68 samplesRemaining = SAMPLE_BUFFER_SIZE;
bikeNomad 1:2fa375aacece 69 }
bikeNomad 1:2fa375aacece 70
bikeNomad 1:2fa375aacece 71 void recordAudio()
bikeNomad 1:2fa375aacece 72 {
bikeNomad 2:5bcd2f55a294 73 pc.printf("Recording %d samples... ", SAMPLE_BUFFER_SIZE);
bikeNomad 1:2fa375aacece 74 blueLED = 0.0;
bikeNomad 1:2fa375aacece 75
bikeNomad 1:2fa375aacece 76 resetSampleBuffer();
bikeNomad 2:5bcd2f55a294 77 timer.start();
bikeNomad 1:2fa375aacece 78 microphone.enable_interrupt();
bikeNomad 2:5bcd2f55a294 79 microphone.start_read();
bikeNomad 1:2fa375aacece 80
bikeNomad 1:2fa375aacece 81 while (samplesRemaining) {
bikeNomad 2:5bcd2f55a294 82 wait_us(50000);
bikeNomad 2:5bcd2f55a294 83 blueLED.write(1.0 - (1.0 * samplesRemaining / SAMPLE_BUFFER_SIZE));
bikeNomad 1:2fa375aacece 84 }
bikeNomad 1:2fa375aacece 85
bikeNomad 2:5bcd2f55a294 86 float elapsed = timer.read();
bikeNomad 2:5bcd2f55a294 87 pc.printf("Done. %u samples in %f usec = %f samples/sec\r\n", SAMPLE_BUFFER_SIZE, elapsed * 1.0e6, SAMPLE_BUFFER_SIZE / elapsed);
bikeNomad 1:2fa375aacece 88 }
bikeNomad 1:2fa375aacece 89
bikeNomad 2:5bcd2f55a294 90 void playAudio(float duration)
bikeNomad 1:2fa375aacece 91 {
bikeNomad 2:5bcd2f55a294 92 pc.printf("Playing %d samples... ", SAMPLE_BUFFER_SIZE);
bikeNomad 1:2fa375aacece 93 greenLED = 0.0;
bikeNomad 1:2fa375aacece 94 resetSampleBuffer();
bikeNomad 2:5bcd2f55a294 95 timer.reset();
bikeNomad 2:5bcd2f55a294 96 timer.start();
bikeNomad 2:5bcd2f55a294 97 sampleTicker.attach(&playAudioSample, duration/SAMPLE_BUFFER_SIZE);
bikeNomad 1:2fa375aacece 98 while (samplesRemaining) {
bikeNomad 2:5bcd2f55a294 99 wait_us(50000);
bikeNomad 2:5bcd2f55a294 100 greenLED.write(1.0 - (1.0 * samplesRemaining / SAMPLE_BUFFER_SIZE));
bikeNomad 1:2fa375aacece 101 }
bikeNomad 2:5bcd2f55a294 102 float elapsed = timer.read();
bikeNomad 2:5bcd2f55a294 103 pc.printf("Done. %u samples in %f usec = %f samples/sec", SAMPLE_BUFFER_SIZE, elapsed * 1.0e6, SAMPLE_BUFFER_SIZE / elapsed);
bikeNomad 2:5bcd2f55a294 104 pc.printf(" (Rate %#+0.2f%%)\r\n", (duration-elapsed)*100/duration);
bikeNomad 2:5bcd2f55a294 105 }
bikeNomad 1:2fa375aacece 106
bikeNomad 0:1ddd40d843cb 107 int main()
bikeNomad 0:1ddd40d843cb 108 {
bikeNomad 1:2fa375aacece 109 pc.baud(115200);
bikeNomad 2:5bcd2f55a294 110 pc.printf("\r\n\r\nSample buffer = %u samples; rate = %u Hz; period = %u usec\r\n", SAMPLE_BUFFER_SIZE, SAMPLE_RATE_HZ, SAMPLE_PERIOD_US);
bikeNomad 1:2fa375aacece 111 redLED = 1.0;
bikeNomad 1:2fa375aacece 112 greenLED = 1.0;
bikeNomad 1:2fa375aacece 113 blueLED = 1.0;
bikeNomad 1:2fa375aacece 114
bikeNomad 1:2fa375aacece 115 recordAudio();
bikeNomad 1:2fa375aacece 116
bikeNomad 2:5bcd2f55a294 117 playAudio(timer.read());
bikeNomad 0:1ddd40d843cb 118 }