N.Yamazaki's blog

主に音声合成について思ったことを書いてみようと思います。
<< AquesTalk Android β版リリース | main | Excel デフォルトのセルの書式を"文字列"に設定する >>
Androidで音声再生(サウンド出力) プログラム
先に、Android上でメモリ上の音声データをファイル経由せずに、直接再生する方法がわからないと書きましたが、その方法を教えていただいたので、簡単に使い方をまとめておきます。

MediaPlayerでなく、AudioTrackを使うのがミソ。
困ったことに、再生が終了(指定のデータの長さを出力)しても、AudioTrackのstatusはずっとPLAYSTATE_PLAYINGのままである。
どうやら、stop()やpause()を呼び出さないかぎり、statusが変わらない模様。
そこで、下のサンプルコードでは、setNotificationMarkerPosition()を呼び出し、再生データの長さの再生が終わった時点で、onMarkerReached()が呼ばれるようにして、この中でstop()するようにしている。


1. インポート
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
2. インスタンス生成
    AudioTrack audioTrack;

    @Override
    public void onCreate(Bundle savedInstanceState) {
            ・
            ・
            ・
        audioTrack = new AudioTrack(
                AudioManager.STREAM_MUSIC,
                8000,//サンプリング周波数
                AudioFormat.CHANNEL_CONFIGURATION_MONO,//モノラル
                AudioFormat.ENCODING_PCM_16BIT,//16bitPCM
                8000*2*10,    // バッファサイズ、ここでは最大10秒としている
                AudioTrack.MODE_STATIC);
       
        audioTrack.setPlaybackPositionUpdateListener(
            new AudioTrack.OnPlaybackPositionUpdateListener() {
                public void onPeriodicNotification(AudioTrack track) {
                }
                // 再生完了時のコールバック
                public void onMarkerReached(AudioTrack track) {
                    if(track.getPlayState()==AudioTrack.PLAYSTATE_PLAYING){
                        track.stop();// 再生完了したので発声停止
                    }
                }
            }
        );
   
3. 再生開始
音声データの長さは、AudioTrackインスタンス生成時に指定したバッファサイズを超えて指定すると例外が発生するので注意する必要がある。
    short[]    wav=......... //出力する音声データを指定
    audioTrack.reloadStaticData(); // stop()後に再び再生するときに必要
    audioTrack.write(wav, 0, wav.length); // ここで再生するデータをセット
    audioTrack.setNotificationMarkerPosition(wav.length);// コールバックするタイミングを指定(再生データの最後)
    audioTrack.play();

3. 再生停止
if(audioTrack.getPlayState()==AudioTrack.PLAYSTATE_PLAYING){
           audioTrack.stop();// 発声中なら停止
       }


4. 終了処理
    @Override
    public void onDestroy() {
        super.onDestroy();
        audioTrack.release();
    }


なお、AquesTalkで生成する音声データは、wavフォーマットなので、先頭に44バイトのヘッダが含まれている。また、返すデータも、short[]でなく、byte[]である。そこで、write()部分は下記のようにして、再生音の頭にノイズが含まれるのを防ぐ必要がある。
    byte[] wav = aquestalk.syntheWav("こんにちわ。", 100);
    audioTrack.write(wav, 44, wav.length-44);
    audioTrack.setNotificationMarkerPosition((wav.length-44)/2); //byteサイズでなくshortサイズで指定するので1/2する


| AquesTalk | 17:12 | - | - |
PROFILE
Follow
CATEGORIES
LATEST ENTRIES
SEARCH THIS SITE
RECOMMEND
RECOMMEND
RECOMMEND
RECOMMEND
RECOMMEND
RECOMMEND
RECOMMEND
SONY MDR-CD900ST
SONY MDR-CD900ST (JUGEMレビュー »)

普段これで開発しています。
RECOMMEND
RECOMMEND
RECOMMEND
RECOMMEND