2013-02-27 13 views
5

リソースフォルダに2つのPCMサウンドファイルがあります。私はinputstreamを使用し、それらをbytearrayに変換しました。Android用のサンプルコードAudioTrack Mixing

次に、正規化してmusic1とmusic2を追加して出力し、バイト配列出力に出力しました。最後に、出力配列を配置し、それをAudioTrackに送ります。

明らかに、私は何も聞こえず、何かが間違っています。

private void mixSound() throws IOException { 

    InputStream in1=getResources().openRawResource(R.raw.cheerapp2);  
    InputStream in2=getResources().openRawResource(R.raw.buzzer2); 

    byte[] music1 = null; 
    music1= new byte[in1.available()]; 
    music1=convertStreamToByteArray(in1); 
    in1.close(); 


    byte[] music2 = null; 
    music2= new byte[in2.available()]; 
    music2=convertStreamToByteArray(in2); 
    in2.close(); 

    byte[] output = new byte[music1.length]; 

    audioTrack.play(); 

    for(int i=0; i < output.length; i++){ 

     float samplef1 = music1[i]/128.0f;  //  2^7=128 
     float samplef2 = music2[i]/128.0f; 


     float mixed = samplef1 + samplef2; 
     // reduce the volume a bit: 
     mixed *= 0.8; 
     // hard clipping 
     if (mixed > 1.0f) mixed = 1.0f; 
     if (mixed < -1.0f) mixed = -1.0f; 
     byte outputSample = (byte)(mixed * 128.0f); 
     output[i] = outputSample; 
     audioTrack.write(output, 0, i); 
     } //for loop 


     public static byte[] convertStreamToByteArray(InputStream is) throws IOException { 



    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    byte[] buff = new byte[10240]; 
    int i = Integer.MAX_VALUE; 
    while ((i = is.read(buff, 0, buff.length)) > 0) { 
     baos.write(buff, 0, i); 
    } 

    return baos.toByteArray(); // be sure to close InputStream in calling function 

} 

答えて

9

あなたのコードを試しました(自分のオーディオファイルで置き換えてみました)。私はこのようなAudioTrackインスタンスを初期化、うまくいけば、これはあなたがそれをやったかのようになります。

AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT, 44100, AudioTrack.MODE_STREAM); 

そして、それを実行してみました。それは時間がたつにつれて低くなった高い音を出しました。コードをチェックしたところ、mixSound()メソッドのループの繰り返しごとに出力バイト配列全体をaudioTrackに書き込んでいるという問題がありました。

audioTrack.write(output, 0, i); 

ニーズがループの外に移動し、あなたは一度に全部を書き、その後、出力バイト配列に一緒に両方のファイルを混在さ

audioTrack.write(output, 0, output.length); 

に変更するラインに。

ので、作業mixSoundメソッドのコードは次のようになります。

private void mixSound() throws IOException { 
    AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT, 44100, AudioTrack.MODE_STREAM); 

    InputStream in1=getResources().openRawResource(R.raw.track1);  
    InputStream in2=getResources().openRawResource(R.raw.track2); 

    byte[] music1 = null; 
    music1= new byte[in1.available()]; 
    music1=convertStreamToByteArray(in1); 
    in1.close(); 


    byte[] music2 = null; 
    music2= new byte[in2.available()]; 
    music2=convertStreamToByteArray(in2); 
    in2.close(); 

    byte[] output = new byte[music1.length]; 

    audioTrack.play(); 

    for(int i=0; i < output.length; i++){ 

     float samplef1 = music1[i]/128.0f;  //  2^7=128 
     float samplef2 = music2[i]/128.0f; 


     float mixed = samplef1 + samplef2; 
     // reduce the volume a bit: 
     mixed *= 0.8; 
     // hard clipping 
     if (mixed > 1.0f) mixed = 1.0f; 

     if (mixed < -1.0f) mixed = -1.0f; 

     byte outputSample = (byte)(mixed * 128.0f); 
     output[i] = outputSample; 

    } //for loop 
    audioTrack.write(output, 0, output.length); 

} 
+0

私はあなたの第二の音声ファイルが最初よりも短い場合に起こるかもしれないは、ArrayIndexOutOfBoundsException –

+1

のエラーを得たforloop内部。出力配列は最初のオーディオファイルの長さに初期化され、forループは出力配列の長さにわたって反復処理されます。だから、2番目のオーディオファイルの最後を過ぎて読んでしまうかもしれません。解決方法は、samplef2を読んだ場所の周りに保護を追加することです。 i> music2.lengthの場合は、sample2fを0に設定する必要があります(クリップの最後に達しています)。 – combinatorics

関連する問題