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:
Wed May 15 23:36:12 2013 +0000
Revision:
7:f0e5450449cb
Parent:
3:c04d8d0493f4
turn DAC off after playing

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bikeNomad 1:2fa375aacece 1 #ifndef __included_fast_analog_in_h
bikeNomad 1:2fa375aacece 2 #define __included_fast_analog_in_h
bikeNomad 1:2fa375aacece 3
bikeNomad 1:2fa375aacece 4 #include "mbed.h"
bikeNomad 1:2fa375aacece 5
bikeNomad 1:2fa375aacece 6 namespace NK
bikeNomad 1:2fa375aacece 7 {
bikeNomad 1:2fa375aacece 8
bikeNomad 1:2fa375aacece 9 using namespace mbed;
bikeNomad 2:5bcd2f55a294 10 extern "C" void ADC0_IRQHandler(void);
bikeNomad 1:2fa375aacece 11
bikeNomad 1:2fa375aacece 12 class FastAnalogIn: public mbed::AnalogIn
bikeNomad 1:2fa375aacece 13 {
bikeNomad 1:2fa375aacece 14 public:
bikeNomad 1:2fa375aacece 15 void start_read() {
bikeNomad 2:5bcd2f55a294 16 ADC0->SC1[0] = ADC_SC1_ADCH(_adc.adc)
bikeNomad 2:5bcd2f55a294 17 | ADC_SC1_AIEN_MASK; // enable interrupt
bikeNomad 2:5bcd2f55a294 18 }
bikeNomad 2:5bcd2f55a294 19
bikeNomad 2:5bcd2f55a294 20 void abort_read() {
bikeNomad 2:5bcd2f55a294 21 ADC0->SC1[0] = ADC_SC1_ADCH(0x1F);
bikeNomad 1:2fa375aacece 22 }
bikeNomad 1:2fa375aacece 23
bikeNomad 1:2fa375aacece 24 uint16_t read_u16() {
bikeNomad 1:2fa375aacece 25 // Wait Conversion Complete
bikeNomad 1:2fa375aacece 26 while ((ADC0->SC1[0] & ADC_SC1_COCO_MASK) != ADC_SC1_COCO_MASK);
bikeNomad 1:2fa375aacece 27
bikeNomad 1:2fa375aacece 28 // Return value
bikeNomad 1:2fa375aacece 29 return (uint16_t)ADC0->R[0];
bikeNomad 1:2fa375aacece 30 }
bikeNomad 1:2fa375aacece 31
bikeNomad 2:5bcd2f55a294 32 uint16_t read_u16_nowait() {
bikeNomad 2:5bcd2f55a294 33 return (uint16_t)ADC0->R[0];
bikeNomad 2:5bcd2f55a294 34 }
bikeNomad 2:5bcd2f55a294 35
bikeNomad 3:c04d8d0493f4 36 // 0x0000 => 0x80 (-128)
bikeNomad 3:c04d8d0493f4 37 // 0x7fff => 0xFF (-1)
bikeNomad 3:c04d8d0493f4 38 // 0x8000 => 0x00 (0)
bikeNomad 3:c04d8d0493f4 39 // 0xffff => 0x7f (127)
bikeNomad 3:c04d8d0493f4 40 int8_t read_s8_nowait() {
bikeNomad 3:c04d8d0493f4 41 int32_t val = read_u16_nowait();
bikeNomad 3:c04d8d0493f4 42 return (val + 0x80 - 0x8000) >> 8;
bikeNomad 2:5bcd2f55a294 43 }
bikeNomad 2:5bcd2f55a294 44
bikeNomad 2:5bcd2f55a294 45 FastAnalogIn(PinName pin)
bikeNomad 2:5bcd2f55a294 46 : mbed::AnalogIn(pin) {
bikeNomad 2:5bcd2f55a294 47
bikeNomad 2:5bcd2f55a294 48 NVIC_SetVector(ADC0_IRQn, (uint32_t)&ADC0_IRQHandler);
bikeNomad 2:5bcd2f55a294 49 NVIC_DisableIRQ(ADC0_IRQn);
bikeNomad 1:2fa375aacece 50
bikeNomad 2:5bcd2f55a294 51 ADC0->CFG1 = ADC_CFG1_ADLPC_MASK // Low-Power Configuration
bikeNomad 2:5bcd2f55a294 52 | ADC_CFG1_ADIV(4) // Clock Divide Select: (Input Clock)/4
bikeNomad 2:5bcd2f55a294 53 | ADC_CFG1_ADLSMP_MASK // Long Sample Time
bikeNomad 2:5bcd2f55a294 54 | ADC_CFG1_MODE(3) // (16)bits Resolution
bikeNomad 2:5bcd2f55a294 55 | ADC_CFG1_ADICLK(1); // Input Clock: (Bus Clock)/2
bikeNomad 2:5bcd2f55a294 56
bikeNomad 2:5bcd2f55a294 57 ADC0->CFG2 = 0 // ADxxA channels are selected
bikeNomad 2:5bcd2f55a294 58 | ADC_CFG2_ADACKEN_MASK // Asynchronous Clock Output Enable
bikeNomad 2:5bcd2f55a294 59 | ADC_CFG2_ADHSC_MASK // High-Speed Configuration
bikeNomad 2:5bcd2f55a294 60 | ADC_CFG2_ADLSTS(0); // Long Sample Time Select
bikeNomad 2:5bcd2f55a294 61
bikeNomad 2:5bcd2f55a294 62 ADC0->SC2 = ADC_SC2_REFSEL(0); // Default Voltage Reference
bikeNomad 2:5bcd2f55a294 63
bikeNomad 1:2fa375aacece 64 ADC0->SC3 = ADC_SC3_AVGE_MASK // Hardware Average Enable
bikeNomad 2:5bcd2f55a294 65 | ADC_SC3_AVGS(3); // 16 Samples Averaged
bikeNomad 2:5bcd2f55a294 66
bikeNomad 2:5bcd2f55a294 67 ADC0->SC1[0] = ADC_SC1_ADCH(_adc.adc)
bikeNomad 2:5bcd2f55a294 68 | ADC_SC1_AIEN_MASK; // enable interrupt
bikeNomad 1:2fa375aacece 69 }
bikeNomad 1:2fa375aacece 70
bikeNomad 1:2fa375aacece 71 void enable_interrupt() {
bikeNomad 2:5bcd2f55a294 72 NVIC_EnableIRQ(ADC0_IRQn);
bikeNomad 1:2fa375aacece 73 }
bikeNomad 1:2fa375aacece 74 void disable_interrupt() {
bikeNomad 2:5bcd2f55a294 75 NVIC_DisableIRQ(ADC0_IRQn);
bikeNomad 1:2fa375aacece 76 }
bikeNomad 1:2fa375aacece 77
bikeNomad 1:2fa375aacece 78 };
bikeNomad 1:2fa375aacece 79
bikeNomad 1:2fa375aacece 80 }
bikeNomad 1:2fa375aacece 81
bikeNomad 1:2fa375aacece 82 #endif