コンピュータを楽しもう!!

今、自分が面白くていろいろやってみたことを書き綴りたいと思います。連絡先はtarosa.yでgmail.comです。

AudioTrackで音を鳴らす(修正2)

2011年3月2〜3日に、AudioTrackで音を鳴らすというブログを書いていますが、意外に検索してヒットしている方が多いので、更に修正したものをアップしておきます。
現在のLuarida 1.69Betaには、このバージョンが使われています。

修正した箇所は、onMarkerReached()にtry{}catch{}を追加しただけです。ここでエラーが出て落ちいてたので、エラーが出たときにはリリースするように修正しました。これでいいのかどうかは分かりません・・・(^^;。

//*************************************************
//
// ビープ音を鳴らすクラスを作ってみました
//
//*************************************************
public class BeepCommand {
  private static double prRegion = 0.5;    //振幅の幅 -0.5 から 0.5
  private byte[] prSoundData = null;       //波形データ
  private static int prSampleRate = 20000; // サンプリング周波数20kHz
  private AudioTrack prAudioTrack = null;

  //*************************************************
  //
  // ビープ音を鳴らします
  //
  //*************************************************
  public void start(float sec, float hz){
    int framecount = 800; //minFrameCountエラーが出るので、仮に800を入れるように修正した
    int dsu = (int)( (long)(sec*1000.0f)*5000L/250L);
    prSoundData = new byte[dsu];
    for (int i = 0; i < dsu; i++) {
      double d = prRegion * Math.sin(2.0 * Math.PI * hz*sec * i /dsu);
      prSoundData[i] = (byte)(d * 127.0);
    }

    if( prAudioTrack!=null ){ prAudioTrack.release();	}
    if( prSoundData.length>framecount ){
      framecount = prSoundData.length;
    }
    try{
      prAudioTrack = new AudioTrack(
                         AudioManager.STREAM_MUSIC,
                         prSampleRate,                           //サンプリング周波数
                         AudioFormat.CHANNEL_CONFIGURATION_MONO, //モノラル
                         AudioFormat.ENCODING_PCM_8BIT,          //量子化ビット8ビット
                         framecount,                             //データ長
                         AudioTrack.MODE_STATIC
                         );

      prAudioTrack.setPlaybackPositionUpdateListener(
                   new AudioTrack.OnPlaybackPositionUpdateListener() {
                     public void onPeriodicNotification(AudioTrack track) {
                     }
                     // 再生完了時のコールバック
                     public void onMarkerReached(AudioTrack track) {
                       try{
                         if(track.getPlayState()==AudioTrack.PLAYSTATE_PLAYING){
                           track.stop();// 再生完了したので発声停止
                         }
                       }
                       catch(Exception e){
                         //Log.e("Err",e.toString());
                         prAudioTrack.release();
                       }
                     }
                   }
                   );

      prAudioTrack.reloadStaticData();                                // stop()後に再び再生するときに必要
      prAudioTrack.write(prSoundData, 0, prSoundData.length);         // ここで再生するデータをセット
      prAudioTrack.setNotificationMarkerPosition(prSoundData.length); // コールバックするタイミングを指定(再生データの最後)
      prAudioTrack.play();
    }catch (Exception e) {
      //Log.e("Err",e.toString());
    }
  }

  //*************************************************
  //
  // ビープ音を止めます
  //
  //*************************************************
  public void stop(){
    if( prAudioTrack!=null ){
      if(prAudioTrack.getPlayState()==AudioTrack.PLAYSTATE_PLAYING){
        prAudioTrack.stop();// 発声中なら停止
      }
      prAudioTrack.release();
    }
  }
}