00001 
00002 
00003 
00004 """Copyright (c) 2016 Xu Zhihao (Howe).  All rights reserved.
00005 This program is free software; you can redistribute it and/or modify
00006 This programm is tested on kuboki base turtlebot."""
00007 
00008 from pyaudio import PyAudio, paInt16
00009 import json
00010 import base64
00011 import os
00012 import sys
00013 import requests
00014 import wave
00015 import rospy
00016 import numpy as np 
00017 import array
00018 import chunk
00019 
00020 
00021 class recoder():
00022 
00023  def __init__(self):
00024   if_continue=''
00025   while not rospy.is_shutdown() and if_continue == '':
00026   
00027    self.define()
00028 
00029    self.recode()
00030   
00031    self.reg()
00032    
00033    
00034    
00035    if_continue = raw_input('pls input ENTER to continue')
00036 
00037  def reg(self):
00038  
00039   
00040   requestData = {       "grant_type":           self.Grant_type, 
00041                         "client_id":            self.Api_Key, 
00042                         "client_secret":        self.Secrect_Key}
00043   
00044   result = requests.post(url = self.Token_url, data = requestData)
00045   
00046   token_data = json.loads(result.text)
00047   
00048   
00049   
00050   if 'access_token' in token_data:  
00051    token = token_data['access_token']  
00052    rospy.loginfo('token success\n')
00053   else:
00054    rospy.loginfo('token failed\n')
00055    
00056   
00057   
00058   
00059   str_voice=self.conventor(self.Voice_String)
00060   
00061   speech = base64.b64encode(str_voice)
00062 
00063   size = len(str_voice)
00064 
00065   
00066   RegData = {   "format":       self.FORMAT,
00067                 "rate":         self.SAMPLING_RATE,
00068                 "channel":      self.nchannel,
00069                 "cuid":         self.USER_ID,
00070                 "token":        token,
00071                 "len":          size,
00072                 "speech":       speech,
00073                 "lan":          self.LAN}
00074                 
00075   HTTP_HEADER=          {  'Content-Type':      'audio/%s;rate=%s'%(self.FORMAT,self.SAMPLING_RATE),
00076                            'Content-length':    len(json.dumps(RegData))}
00077 
00078   r = requests.post(url = self.Reg_url, data = json.dumps(RegData, sort_keys=True), headers=HTTP_HEADER)
00079   
00080 
00081   rospy.loginfo( 'response')
00082   self.Print_Response(r.headers)
00083   result = json.loads(r.text)
00084   self.Print_Response(result)
00085   rospy.loginfo( 'result: %s \n'%result['err_msg'])
00086   rospy.loginfo( 'response\n')
00087   
00088   if result[u'err_msg']=='success.':
00089    word = result['result'][0].encode('utf-8')
00090    if word!='':
00091     if word[len(word)-3:len(word)]==',':
00092      rospy.loginfo('cog. result: %s \n'%word[0:len(word)-3])
00093      return word[0:len(word)-3]
00094     else:
00095      rospy.loginfo(word)
00096      return word
00097    else:
00098     rospy.loginfo("音频文件不存在或格式错误\n")
00099     return '音频文件不存在或格式错误'
00100   else:
00101    rospy.loginfo(self.error_reason[result[u'err_no']])
00102    return  self.error_reason[result[u'err_no']]
00103    
00104   rospy.sleep(2)
00105    
00106    
00107  def define(self):
00108   self.error_reason={3300:      '输入参数不正确',
00109                      3301:      '识别错误',
00110                      3302:      '验证失败',
00111                      3303:      '语音服务器后端问题',
00112                      3304:      '请求 GPS 过大,超过限额',
00113                      3305:      '产品线当前日请求数超过限额'}
00114  
00115   if rospy.has_param('~REG_NUM_SAMPLES'):
00116    pass
00117   else:
00118    rospy.set_param('~REG_NUM_SAMPLES', 2000)
00119   
00120   if rospy.has_param('~REG_SAMPLING_RATE'):
00121    pass
00122   else:
00123    rospy.set_param('~REG_SAMPLING_RATE', 8000)
00124   
00125   if rospy.has_param('~REG_UPPER_LEVEL'):
00126    pass
00127   else:
00128    rospy.set_param('~REG_UPPER_LEVEL', 5000)
00129 
00130   if rospy.has_param('~REG_LOWER_LEVEL'):
00131    pass
00132   else:
00133    rospy.set_param('~REG_LOWER_LEVEL', 500) 
00134    
00135   if rospy.has_param('~REG_COUNT_NUM'):
00136    pass
00137   else:
00138    rospy.set_param('~REG_COUNT_NUM', 20)
00139    
00140   if rospy.has_param('~REG_SAVE_LENGTH'):
00141    pass
00142   else:
00143    rospy.set_param('~REG_SAVE_LENGTH', 8)
00144    
00145   if rospy.has_param('~REG_TIME_OUT'):
00146    pass
00147   else:
00148    rospy.set_param('~REG_TIME_OUT', 60)
00149    
00150   if rospy.has_param('~REG_NO_WORDS'):
00151    pass
00152   else:
00153    rospy.set_param('~REG_NO_WORDS', 6)
00154    
00155   if rospy.has_param('~REG_Api_Key'):
00156    pass
00157   else:
00158    rospy.set_param('~REG_Api_Key', "pmUzrWcsA3Ce7RB5rSqsvQt2")
00159    
00160   if rospy.has_param('~REG_Secrect_Key'):
00161    pass
00162   else:
00163    rospy.set_param('~REG_Secrect_Key', "d39ec848d016a8474c7c25e308b310c3")
00164    
00165   if rospy.has_param('~REG_Grant_type'):
00166    pass
00167   else:
00168    rospy.set_param('~REG_Grant_type', "client_credentials")
00169    
00170   if rospy.has_param('~REG_Token_url'):
00171    pass
00172   else:
00173    rospy.set_param('~REG_Token_url', "https://openapi.baidu.com/oauth/2.0/token")
00174    
00175   if rospy.has_param('~REG_Reg_url'):
00176    pass
00177   else:
00178    rospy.set_param('~REG_Reg_url', "http://vop.baidu.com/server_api")
00179 
00180   if rospy.has_param('~REG_USER_ID'):
00181    pass
00182   else:
00183    rospy.set_param('~REG_USER_ID', "8168466")
00184    
00185   if rospy.has_param('~REG_FORMAT'):
00186    pass
00187   else:
00188    rospy.set_param('~REG_FORMAT', "wav")
00189    
00190   if rospy.has_param('~REG_LAN'):
00191    pass
00192   else:
00193    rospy.set_param('~REG_LAN', "zh")
00194    
00195   if rospy.has_param('~REG_nchannel'):
00196    pass
00197   else:
00198    rospy.set_param('~REG_nchannel', 1)
00199 
00200    
00201   self.NUM_SAMPLES = rospy.get_param('~REG_NUM_SAMPLES') 
00202   
00203 
00204   self.SAMPLING_RATE = rospy.get_param('~REG_SAMPLING_RATE')  
00205   
00206 
00207   self.UPPER_LEVEL = rospy.get_param('~REG_UPPER_LEVEL') 
00208   
00209 
00210   self.LOWER_LEVEL = rospy.get_param('~REG_LOWER_LEVEL') 
00211   
00212 
00213   self.COUNT_NUM = rospy.get_param('~REG_COUNT_NUM') 
00214   
00215 
00216   self.SAVE_LENGTH = rospy.get_param('~REG_SAVE_LENGTH') 
00217   
00218 
00219   self.TIME_OUT = rospy.get_param('~REG_TIME_OUT') 
00220   
00221 
00222   self.NO_WORDS = rospy.get_param('~REG_NO_WORDS') 
00223   
00224 
00225   self.Api_Key = rospy.get_param('~REG_Api_Key') 
00226   
00227 
00228   self.Secrect_Key = rospy.get_param('~REG_Secrect_Key') 
00229   
00230 
00231   self.Grant_type = rospy.get_param('~REG_Grant_type') 
00232   
00233 
00234   self.Token_url = rospy.get_param('~REG_Token_url') 
00235   
00236 
00237   self.Reg_url = rospy.get_param('~REG_Reg_url') 
00238   
00239 
00240   self.USER_ID = rospy.get_param('~REG_USER_ID') 
00241   
00242 
00243   self.FORMAT = rospy.get_param('~REG_FORMAT') 
00244   
00245 
00246   self.LAN = rospy.get_param('~REG_LAN') 
00247   
00248 
00249   self.nchannel = rospy.get_param('~REG_nchannel') 
00250   
00251 
00252   self.Voice_String =        []
00253   
00254   
00255  
00256   
00257   
00258   
00259  def Print_Response(self, data):
00260   for i in data:
00261    print ' ', i , ': ' , data[i]
00262    
00263 
00264  def recode(self):
00265   pa = PyAudio() 
00266   stream = pa.open(format=paInt16, channels=self.nchannel, rate=self.SAMPLING_RATE, input=True, frames_per_buffer=self.NUM_SAMPLES) 
00267   save_count = 0 
00268   save_buffer = [] 
00269   time_out = self.TIME_OUT
00270   NO_WORDS=self.NO_WORDS
00271   
00272   while True and NO_WORDS:
00273    time_out -= 1
00274    print 'time_out in', time_out 
00275    string_audio_data = stream.read(self.NUM_SAMPLES) 
00276    audio_data = np.fromstring(string_audio_data, dtype=np.short) 
00277 
00278    
00279    NO_WORDS -= 1
00280    if np.max(audio_data) > self.UPPER_LEVEL:
00281     NO_WORDS=self.NO_WORDS
00282    print 'self.NO_WORDS ', NO_WORDS
00283    print 'np.max(audio_data) ', np.max(audio_data)
00284 
00285    
00286    large_sample_count = np.sum( audio_data > self.LOWER_LEVEL )
00287    
00288    
00289    if large_sample_count > self.COUNT_NUM:
00290     save_count = self.SAVE_LENGTH 
00291    else: 
00292     save_count -= 1
00293    
00294    
00295    
00296    if save_count < 0:
00297     save_count = 0 
00298    elif save_count > 0 : 
00299     save_buffer.append( string_audio_data ) 
00300    else:
00301     pass
00302     
00303    
00304    if len(save_buffer) > 0 and NO_WORDS==0: 
00305     self.Voice_String = save_buffer
00306     save_buffer = [] 
00307     rospy.loginfo( "Recode a piece of voice successfully!")
00308     
00309     
00310    elif len(save_buffer) > 0 and time_out==0: 
00311     self.Voice_String = save_buffer
00312     save_buffer = [] 
00313     rospy.loginfo( "Recode a piece of voice successfully!")
00314     
00315    else: 
00316     pass
00317    
00318 
00319 
00320  def conventor(self, Data_to_String):
00321   Voice_data=str()
00322   for Data in Data_to_String:
00323    Voice_data_h=array.array('b',Data)
00324    
00325    Voice_data_h.byteswap()
00326    
00327    Voice_data_s=Voice_data_h.tostring()
00328    Voice_data+=Voice_data_s
00329   return Voice_data
00330   
00331  def print_data_len(self,data):
00332   print len(data)
00333   n=0
00334   for i in data:
00335    n+=1
00336    print n
00337 
00338   
00339   
00340   
00341    
00342  def savewav(self,filename):
00343   rospy.loginfo('存储音频')
00344   file_path='/home/turtlebot/xu_slam/src/simple_voice/src'
00345   WAVE_FILE = '%s/%s.wav'%(file_path,filename)
00346   wf = wave.open(WAVE_FILE, 'wb') 
00347   wf.setnchannels(1) 
00348   wf.setsampwidth(2) 
00349   wf.setframerate(self.SAMPLING_RATE) 
00350   wf.writeframes("".join(self.Voice_String)) 
00351   wf.close() 
00352   rospy.loginfo('音频数据已存')
00353       
00354 if __name__=="__main__":
00355  rospy.init_node('simple_voice')
00356  rospy.loginfo("initialization system")
00357  recoder()
00358  rospy.loginfo("process done and quit")