2013-02-27 2 views
5

리소스 폴더에 두 개의 PCM 사운드 파일이 있습니다. 나는 inputstream을 사용하여 bytearray로 변환했다.Android AudioTrack 믹싱 샘플 코드

그런 다음 정규화 된 다음 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 루프는 출력 배열의 길이를 반복합니다. 따라서 두 번째 오디오 파일의 마지막 부분을 읽는 것으로 끝날 수도 있습니다. 해결책은 samplef2를 읽는 위치 주변에 보호 기능을 추가하는 것입니다. i> music2.length 인 경우 sample2f를 0으로 설정해야합니다 (클립의 끝까지 도달했습니다). – combinatorics