2014-02-24 3 views
1

두 개 이상의 동일한 길이의 오디오 파일로 하나의 동기식 오디오 출력 파일을 만들려고했습니다. 나는 몇 가지 조사를 수행하고이 아래 단계를 통해 달성 될 수 있다는 것을 알게했다 :두 개 이상의 mp3 파일로 구성된 오디오 파일을 만듭니다.

  1. 만 비 압축 오디오 파일은이 목적을 위해 이용 될 수있다. 즉, mp3 오디오 파일을 WAV 형식으로 변환하십시오.
  2. 2 개의 새로운 wav 파일을 믹스합니다. 나는이 방법을 따랐다 : Mix audio in android

을하지만 같은 문제가 발생, 혼합 오디오 파일이 재생되지 않습니다.

나는이 응답 Writing PCM recorded data into a .wav file (java android)에 따라 출력 파일에 유효한 헤더를 추가하려고했습니다.

public class SongMixer2 
{ 

private Context mContext; 

public SongMixer2(Context context) 
{ 
    mContext = context; 
} 

public void onCreate() 
{ 
    try 
    { 
     mixSound(); 
    } catch (IOException e) 
    { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
} 

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 = mContext.getResources().openRawResource(R.raw.brokaw); 
    InputStream in2 = mContext.getResources().openRawResource(R.raw.brokaw); 

    byte[] arrayMusic1 = null; 
    arrayMusic1 = new byte[in1.available()]; 
    arrayMusic1 = createMusicArray(in1); 
    in1.close(); 

    byte[] arrayMusic2 = null; 
    arrayMusic2 = new byte[in2.available()]; 
    arrayMusic2 = createMusicArray(in2); 
    in2.close(); 

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

    audioTrack.play(); 

    for (int i = 0; i < output.length - 1; i++) 
    { 
     float samplef1 = arrayMusic1[i]/128.0f; 
     float samplef2 = arrayMusic2[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, output.length); 
    convertByteToFile(output); 
} 

public static byte[] createMusicArray(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 

} 

public static void convertByteToFile(byte[] fileBytes) 
     throws FileNotFoundException 
{ 

    String path = Environment.getExternalStorageDirectory().getPath() + "/mixed.wav"; 
    File f=new File(path); 
    BufferedOutputStream bos = new BufferedOutputStream(
      new FileOutputStream(f)); 
    try 
    { 
     bos.write(writeHeader(fileBytes.length), 0, 44); 
     bos.write(fileBytes); 
     bos.flush(); 
     bos.close(); 
    } catch (IOException e) 
    { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
} 

private static byte[] writeHeader(int totalDataLen) 
{ 
    byte[] header = new byte[44]; 

    header[0] = 'R'; // RIFF/WAVE header 
    header[1] = 'I'; 
    header[2] = 'F'; 
    header[3] = 'F'; 
    header[4] = (byte) (totalDataLen & 0xff); 
    header[5] = (byte) ((totalDataLen >> 8) & 0xff); 
    header[6] = (byte) ((totalDataLen >> 16) & 0xff); 
    header[7] = (byte) ((totalDataLen >> 24) & 0xff); 
    header[8] = 'W'; 
    header[9] = 'A'; 
    header[10] = 'V'; 
    header[11] = 'E'; 
    header[12] = 'f'; // 'fmt ' chunk 
    header[13] = 'm'; 
    header[14] = 't'; 
    header[15] = ' '; 
    header[16] = 16; // 4 bytes: size of 'fmt ' chunk 
    header[17] = 0; 
    /* header[18] = 0; 
    header[19] = 0; 
    header[20] = 1; // format = 1 
    header[21] = 0; 
    header[22] = (byte) channels; 
    header[23] = 0; 
    header[24] = (byte) (longSampleRate & 0xff); 
    header[25] = (byte) ((longSampleRate >> 8) & 0xff); 
    header[26] = (byte) ((longSampleRate >> 16) & 0xff); 
    header[27] = (byte) ((longSampleRate >> 24) & 0xff); 
    header[28] = (byte) (byteRate & 0xff); 
    header[29] = (byte) ((byteRate >> 8) & 0xff); 
    header[30] = (byte) ((byteRate >> 16) & 0xff); 
    header[31] = (byte) ((byteRate >> 24) & 0xff); 
    header[32] = (byte) (2 * 16/8); // block align 
    header[33] = 0; 
    header[34] = RECORDER_BPP; // bits per sample 
    header[35] = 0;*/ 
    header[36] = 'd'; 
    header[37] = 'a'; 
    header[38] = 't'; 
    header[39] = 'a'; 
    /* header[40] = (byte) (totalAudioLen & 0xff); 
    header[41] = (byte) ((totalAudioLen >> 8) & 0xff); 
    header[42] = (byte) ((totalAudioLen >> 16) & 0xff); 
    header[43] = (byte) ((totalAudioLen >> 24) & 0xff); 
*/ 

return header; 
} 

} 

그리고 활동 : 여기

내 믹서 클래스입니다 'mixed.wav'은 SD 카드에이 만들어

public class SoundMixerActivity extends Activity 
{ 
protected void onCreate(Bundle savedInstanceState) 
    { 
    super.onCreate(savedInstanceState); 
    new SongMixer2(this).onCreate(); 
} 
} 

파일 만 재생할 수 없습니다 ... 아무도 도와주세요 !!

+0

@Vnay :이 문제에 대한 해결책을 찾았습니까? –

+0

@Vinay 지금까지 해결책을 찾았습니까? Plz 도와주세요 ... 나는 또한 동일하게 작업 중입니다 –

답변

2

헤더에 파일의 오디오 정렬이 4 바이트라고합니다. 이것은 16 비트 스테레오 오디오 용입니다.

그러나 createMix에서는 오디오가 16 비트가 아닌 8 비트 (바이트)라고 가정합니다. 반바지로 섞어서 연주해야합니다.

또한 각 파일의 샘플 평균을 취하는 것이 일반적입니다. ie (sample1 + sample2)/2

+0

고맙습니다, 빠른 답장을 보내 주셔서 감사합니다. 헤더를 으로 업데이트했습니다. header [16] = 32; 행운은 없지만 파일을 만들었지 만 재생할 수 없습니다. ( 목표를 달성하기위한 다른 접근 방식이 있다면 알려 주시겠습니까? – Vinay

+1

@Vinay : 느린 응답, 미안 해요. 32 비트가 아닌 36 - 16 = 20, 32가 아닌 20입니다. 또한 데이터 덩어리에서 샘플을 함께 믹싱하는 것은 실제로 잘못되었습니다 (16 비트 오디오를 원한다고 가정 할 때). – Goz

+0

@Goz이 문제에 대한 올바른 해결책 ? –