I made a pronunciation training machine using Google Speech API, because it is difficult for the Japanese to distinguish "L" and "R" pronunciations.
OverviewIf you talk to the USB microphone connected to the Raspberry Pi by speaking to "right" or "light" and recognize it correctly, the servo motor points to the right when "right," and the LED lights if it is "light".
I use the Google Speech API to recognize the voice input to the microphone. I registered the API and got the key.
Raspberry Pi SettingsInstall voice processing library sox.
$ sudo apt-get install alsa-utils sox libsox-fmt-all
Python ProgramWhen recording, light the red LED. When it recognizes "right" and "light" it sends a signal to Arduino (GPIO).
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import requests
import json
import os
import commands
import time
import RPi.GPIO as GPIO
GOOGLE_APIKEY = 'Google Speech API key'
LISTEN_SECONDS = 3 #3 seconds recording
VOICE_IN_PATH = '/home/pi/tmp.flac'
#GPIO settings
GPIO.setmode(GPIO.BCM)
GPIO.setup(2, GPIO.OUT)
GPIO.setup(3, GPIO.OUT)
GPIO.setup(4, GPIO.OUT)
GPIO.output(2, 0)
GPIO.output(3, 0)
GPIO.output(4, 0)
#Audio input (voice -> sound data)
def listen(seconds):
print 'lestening...'
cmdline = 'AUDIODEV=hw:1 rec -c 1 -r 17000 ' + VOICE_IN_PATH + \
' trim 0 ' + str(seconds)
os.system(cmdline)
return os.path.getsize(VOICE_IN_PATH)
#Voice recognition (sound data -> text)
def recognize():
print('recognizing...')
f = open(VOICE_IN_PATH, 'rb')
voice = f.read()
f.close()
#English lang=en-US
url = 'https://www.google.com/speech-api/v2/recognize?xjerr=1&client=chromium&'\
'lang=en-US&maxresults=10&pfilter=0&xjerr=1&key=' + GOOGLE_APIKEY
hds = {'Content-type': 'audio/x-flac; rate=17000'}
try:
reply = requests.post(url, data=voice, headers=hds).text
except IOError:
return '#CONN_ERR'
except:
return '#ERROR'
objs = reply.split(os.linesep)
for obj in objs:
if not obj:
continue
alternatives = json.loads(obj)['result']
if len(alternatives) == 0:
continue
return alternatives[0]['alternative'][0]['transcript']
return ""
def current_milli_time():
return int(round(time.time() * 1000))
if __name__ == '__main__':
#first time record will be failed.
listen(1)
no_word = 0
wifi_err = 0
try:
while True:
#Audio input
t0 = current_milli_time()
GPIO.output(2, 1) #Rec LED on
size = listen(LISTEN_SECONDS)
GPIO.output(2, 0) #Rec LED off
t = current_milli_time() - t0
if (t < 2000):
print 'USB microphone not available'
time.sleep(10)
continue
print 'listened:' + str(t) + 'ms'
print 'voice data size=' + str(size)
#Voice recognition
t0 = current_milli_time()
message = recognize().encode('utf-8')
print 'recognized:' + str(current_milli_time() - t0) + 'ms'
if (message == '#CONN_ERR'):
print 'internet not available'
time.sleep(10)
continue
elif (message == '#ERROR'):
print 'voice recognize failed'
time.sleep(10)
continue
print 'Result: ' + message
#Discrimination Discrimination between "right" and "light"
if 'right' in message:
print 'right'
GPIO.output(3, 1) #Servo turns the right
GPIO.output(4, 0) #Neopixel LED off
time.sleep(3)
elif 'light' in message:
print 'light'
GPIO.output(3, 0) #Servo turns to the orignal
GPIO.output(4, 1) #Neopixel LED on
time.sleep(3)
else:
print 'non'
except KeyboardInterrupt:
GPIO.cleanup()
pass
Arduino IDE ProgramThe library for NeoPixel is below.
https://github.com/adafruit/Adafruit_NeoPixel
Code to receive the signal from the Raspberry Pi and control the servo and the NeoPixel ring.
#include <Servo.h>
#include <Adafruit_NeoPixel.h>
int GPIO3 = 3;
int GPIO4 = 4;
int servo, LED;
Servo myservo;
Adafruit_NeoPixel strip = Adafruit_NeoPixel(12, 6, NEO_GRB + NEO_KHZ800);
void setup() {
Serial.begin(9600);
// make the pushbutton's pin an input:
pinMode(GPIO3, INPUT);
pinMode(GPIO4, INPUT);
myservo.attach(9);
myservo.write(0);
myservo.detach();
strip.begin();
strip.show(); // Initialize all pixels to 'off'
}
void loop() {
//Read GPIO
servo = digitalRead(GPIO3);
LED = digitalRead(GPIO4);
Serial.print(servo); Serial.print("\t");
Serial.println(LED);
//Servo
myservo.attach(9);
delay(100);
if(servo == 1){
myservo.write(0);
}else{
myservo.write(90);
}
myservo.detach();
delay(100);
//LED
int bright = 20;
if(LED == 1){
for(uint16_t i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, strip.Color(bright, bright, bright));
}
strip.show();
}else{
strip.clear();
strip.show();
}
}
Operation
Comments