2014-02-24 63 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; 
} 

} 

,並且活動:

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

A文件'mixed.wav'在SD卡創建的存在,但它不會玩...任何人請幫助!

+0

@Vayay:你有沒有找到這方面的解決方案? –

+0

@Vinay你到現在是否找到解決方案? Plz幫助我...我也在努力 –

回答

2

在您的頭文件中,您說該文件具有4個字節的音頻對齊。這將用於16位立體聲音頻。

但是,在您的createMix中,您認爲音頻是8位(一個字節)而不是16位。你需要用短褲進行混合。

它也通常採取每個文件的樣本的平均值。即(sample1 + sample2)/ 2.

+0

感謝Goz,爲您的快速回復。 我更新的標題爲 header [16] = 32; 但沒有運氣,該文件被創建,但不能播放:( 你能告訴我,如果有不同的方法來實現目標? – Vinay

+1

@Vinay:緩慢的反應,抱歉。爲什麼你更新你的頭到32字節?36 - 16 = 20,而不是32.另外,它的樣本混合在數據塊中真的是錯誤的(假設你想要16位音頻)。 – Goz

+0

@Goz什麼纔是正確的解決方案? –