English Pronunciation Training Machine
I made a pronunciation training machine using Google Speech API, because it is difficult for the Japanese to distinguish “L” and “R” pronunciations.
目次
Overview
If 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”.
Parts
-
-
- Mike uses the camera on Wed
- Raspberry Pi 3
- Microcomputer Arduino uno
- Neopixel Ring – 12 consecutive full color serial leds
- Servo motor SG90
- Mike uses the camera on Wed
-
Raspie settings
Install voice processing library sox.
1 |
$ sudo apt-get install alsa-utils sox libsox-fmt-all |
Python programs
When recording, light the red LED. When it recognizes “right” and “light” it sends a signal to Arduino (GPIO).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
#!/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 Program
The 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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
#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(); } } |