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

Revision:
1:2fa375aacece
Parent:
0:1ddd40d843cb
Child:
2:5bcd2f55a294
--- a/main.cpp	Fri May 10 02:15:44 2013 +0000
+++ b/main.cpp	Tue May 14 14:08:22 2013 +0000
@@ -1,53 +1,109 @@
 #include "mbed.h"
+#include "FastAnalogIn.h"
+using namespace NK;
+
+// Power:
+// Power GND  J9/14
+// Vin (6V)   J9/16
 
-Serial pc(USBTX, USBRX);
-DigitalOut tail(PTA13);
-DigitalOut mouth(PTC12);
-DigitalOut head(PTC13);
+// Digital:
+DigitalOut tail(PTA13);     // J3/2
+DigitalOut mouth(PTC12);    // J3/1
+DigitalOut head(PTC13);     // J3/3
+DigitalIn pushbutton(PTD5); // J3/4
+
+PwmOut redLED(LED_RED);
+PwmOut greenLED(LED_GREEN);
+PwmOut blueLED(LED_BLUE);
 
-void exercise_mouth(void)
+// Analog:
+// GND   J3/14
+// VrefH J3/16
+FastAnalogIn microphone(PTB0);  // J10/2
+AnalogOut speaker(PTE30);   // J10/11
+
+// Communications:
+// Serial uart1(PTC4, PTC3);
+Serial pc(USBTX, USBRX);
+
+const unsigned SAMPLE_RATE_HZ  = 7812;
+const unsigned SAMPLE_PERIOD_US     = (1000000U / SAMPLE_RATE_HZ);
+
+Ticker sampleTicker;
+
+uint8_t sampleBuffer[SAMPLE_RATE_HZ];      // 1 second buffer
+uint8_t * volatile nextSample;
+unsigned volatile samplesRemaining;
+
+extern "C"
+void ADC0_IRQHandler(void)
 {
-    for (int i = 0; i < 200; i++) {
-        mouth = true;
-        wait(0.5);
-        mouth = false;
-        wait(0.5);
+    pc.printf("irq\r\n");
+    if (samplesRemaining) {
+        *nextSample++ = microphone.read_u16() >> 8;
+        samplesRemaining--;
+    } else {
+        microphone.disable_interrupt();
     }
 }
 
+void playAudioSample()
+{
+    if (samplesRemaining) {
+        speaker.write_u16(*nextSample++ << 8);
+        samplesRemaining--;
+    } else {
+        sampleTicker.detach();
+    }
+}
+
+void resetSampleBuffer()
+{
+    nextSample = sampleBuffer;
+    samplesRemaining = sizeof(sampleBuffer);
+}
+
+void recordAudio()
+{
+    pc.printf("Recording %d samples... ", sizeof(sampleBuffer));
+    blueLED = 0.0;
+
+    resetSampleBuffer();
+    microphone.enable_interrupt();
+
+    while (samplesRemaining) {
+        wait(0.05);
+        blueLED.write(1.0 - (1.0 * samplesRemaining / sizeof(sampleBuffer)));
+    }
+
+    pc.printf("Done\r\n");
+}
+
+void playAudio()
+{
+    pc.printf("Playing %d samples... ", sizeof(sampleBuffer));
+    greenLED = 0.0;
+    resetSampleBuffer();
+    sampleTicker.attach_us(&playAudioSample, SAMPLE_PERIOD_US);
+    while (samplesRemaining) {
+        wait(0.05);
+        greenLED.write(1.0 - (1.0 *  samplesRemaining / sizeof(sampleBuffer)));
+    }
+    pc.printf("Done\r\n");
+
+}
 int main()
 {
-    pc.baud(9600);
-    pc.puts("A=1 tail on, a=1 off, same for b (mouth) and c (head); x=exercise_mouth");
-    while(true) {
-        if (pc.readable()) {
-            int c = pc.getc();
-            pc.putc(c);
-            switch (c) {
-                case 'A':
-                    tail = true;
-                    break;
-                case 'a':
-                    tail = false;
-                    break;
-                case 'B':
-                    mouth = true;
-                    break;
-                case 'b':
-                    mouth = false;
-                    break;
-                case 'C':
-                    head = true;
-                    break;
-                case 'c':
-                    head = false;
-                    break;
-                case 'x':
-                    exercise_mouth();
-                    break;
-                default:
-                    break;
-            }
-        }
-    }
+    pc.baud(115200);
+    pc.printf("Sample buffer = %u samples; rate = %u Hz; period = %u usec\r\n", sizeof(sampleBuffer), SAMPLE_RATE_HZ, SAMPLE_PERIOD_US);
+    redLED = 1.0;
+    greenLED = 1.0;
+    blueLED = 1.0;
+
+    microphone.enable_interrupt();
+    microphone.start_read();
+
+    recordAudio();
+
+    playAudio();
 }