2013-02-27 58 views
5

我在資源文件夾中有兩個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異常 – 2013-02-27 22:37:19

+1

的一個錯誤,如果你的第二個音頻文件比你的第一個短於可能發生的for循環裏面。輸出數組被初始化爲第一個音頻文件的長度,for循環遍歷輸出數組的長度。所以你最終可能會讀完第二個音頻文件的末尾。解決方法是在讀取samplef2的地方添加保護。如果我> music2.length,你應該設置sample2f爲0(你已經到達了剪輯的結尾)。 – combinatorics 2013-02-27 22:47:36