AndroidでMicrosoft Translator V2 APIのSpeakメソッドを使う。

夏の計画停電。考えるだけでも恐ろしい。

さて、今回も例によって他人様のコードを借りまくりなのである。
そもそもAndroidMicrosoft Translator(Bing Translator)を使いたいなんて思う人が居るのかどうか疑問だが、私がそう思ってしまったんだからしょうがない。
Google Text-To-Speechで間に合えば良かったのだが、訳あって日中韓の3ヶ国語を喋らせなくてはならなかったので、Microsoft Translatorの出番となった。

まずは、Bing Translator ツール 翻訳 API - katamari.wankuma.comに書いてある通り、Bing Developer CenterでAppIDを取得する。

あとはMicrosoft Translator for Business - Microsoft Translator for Businessを見て、HTTPインターフェースでSpeakメソッドを呼ぶだけ。

としたいところなのだが、残念ながら返ってくる合成音声データはWAVE形式なので、AndroidのMediaPlayerでは再生できない。そこで、AudioTrackを使ってWAVEデータを再生する - Tech Boosterに書いてあるとおり、AudioTrackを使って再生する。

ちなみにHTTPリクエストについては、Make in HTTP request with android - stackoverflowを参考にした。

で、結果としてできあがったコピペコードがこちら。

    private void doTextToSpeech(String text) {
        String encodeText;
        String bingKey = [取得したAppId];
    	
        try {
            encodeText = URLEncoder.encode(text, "UTF-8");
            String strUrl = "http://api.microsofttranslator.com/v2/Http.svc/Speak?appId="
                        + bingKey + "&text=" + encodeText + "&language=zh-CHS";
            
            URI uri = new URI(strUrl);
            
            HttpClient httpclient = new DefaultHttpClient();
            HttpResponse response = httpclient.execute(new HttpGet(uri));
            StatusLine statusLine = response.getStatusLine();
            
            if(statusLine.getStatusCode() == HttpStatus.SC_OK){
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                response.getEntity().writeTo(out);
                out.close();
                byteData = out.toByteArray();

                // 必要となるバッファサイズを計算
                // なぜかAndroidエミュレータはサンプリングレート8kしか受け付けない。
                int bufSize = android.media.AudioTrack.getMinBufferSize(8000,
                        AudioFormat.CHANNEL_CONFIGURATION_MONO,
                        AudioFormat.ENCODING_PCM_8BIT);

                // AudioTrackインスタンス作成
                audioTrack = new AudioTrack(AudioManager.STREAM_VOICE_CALL,
                        8000, AudioFormat.CHANNEL_CONFIGURATION_MONO,
                        AudioFormat.ENCODING_PCM_8BIT, bufSize,
                        AudioTrack.MODE_STREAM);
                
                // スレッドインスタンス作成
                Thread play_thread = new Thread(this);
                play_thread.start();
                
            } else{
                // コネクションを閉じる。
                response.getEntity().getContent().close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 再生用スレッド処理
    public void run() {
        if (audioTrack != null) {
            // 再生開始
            // ノイズが入らないように127バイト目から再生しているが、何バイト目から再生するのが
            // 正しいのか分からない。
            audioTrack.play();
            audioTrack.write(byteData, 126, byteData.length - 126);
        }
    } 

うん。参考にしたソースより明らかに劣化してる。