2016-12-02 99 views
1

我混合了兩個wav文件。在輸出文件中,這兩個文件都是混合的,但有很多噪音。如何避免噪音並獲得清晰的輸出?我的標題是否已損壞或是其他內容?任何建議/幫助將不勝感激。如何在沒有噪音的情況下混合兩個wav文件?

這是代碼。 (在MainActivity中,只需調用mixSound()。rawToWave()函數爲wav文件寫入標題,我在創建混合文件後編寫標題)。

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

    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; 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); 
    File file = new File(Environment.getExternalStorageDirectory().getPath() + "/mixed.wav"); 
    rawToWave(file, file); 

} 

private void writeInt(final DataOutputStream output, final int value) throws IOException { 
    output.write(value >> 0); 
    output.write(value >> 8); 
    output.write(value >> 16); 
    output.write(value >> 24); 
} 

private void writeShort(final DataOutputStream output, final short value) throws IOException { 
    output.write(value >> 0); 
    output.write(value >> 8); 
} 

private void writeString(final DataOutputStream output, final String value) throws IOException { 
    for (int i = 0; i < value.length(); i++) { 
     output.write(value.charAt(i)); 
    } 
} 

private void rawToWave(final File rawFile, final File waveFile) throws IOException { 

    byte[] rawData = new byte[(int) rawFile.length()]; 
    DataInputStream input = null; 
    try { 
     input = new DataInputStream(new FileInputStream(rawFile)); 
     input.read(rawData); 
    } finally { 
     if (input != null) { 
      input.close(); 
     } 
    } 

    DataOutputStream output = null; 
    try { 
     output = new DataOutputStream(new FileOutputStream(waveFile)); 
     // WAVE header 
     // see http://ccrma.stanford.edu/courses/422/projects/WaveFormat/ 
     writeString(output, "RIFF"); // chunk id 
     writeInt(output, 36 + rawData.length); // chunk size 
     writeString(output, "WAVE"); // format 
     writeString(output, "fmt "); // subchunk 1 id 
     writeInt(output, 16); // subchunk 1 size 
     writeShort(output, (short) 1); // audio format (1 = PCM) 
     writeShort(output, (short) 1); // number of channels 
     writeInt(output, 8000); // sample rate 
     writeInt(output, 8000 * 2); // byte rate 
     writeShort(output, (short) 2); // block align 
     writeShort(output, (short) 16); // bits per sample 
     writeString(output, "data"); // subchunk 2 id 
     writeInt(output, rawData.length); // subchunk 2 size 
     // Audio data (conversion big endian -> little endian) 
     short[] shorts = new short[rawData.length/2]; 
     ByteBuffer.wrap(rawData).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(shorts); 
     ByteBuffer bytes = ByteBuffer.allocate(shorts.length * 2); 
     for (short s : shorts) { 
      bytes.putShort(s); 
     } 
     output.write(bytes.array()); 
    } finally { 
     if (output != null) { 
      output.close(); 
     } 
    } 
} 

回答

0

花了幾個小時後,我找到了解決方案,這就像一個魅力。

步驟1:導入musicg-1.4.2.0.jar和編譯

compile files('libs/musicg-1.4.2.0.jar') 

步驟2:創建的wav文件頭

public class MyWaveHeader { 

private static final String TAG = "WaveHeader"; 

private static final int HEADER_LENGTH = 44; 

/** Indicates PCM format. */ 
public static final short FORMAT_PCM = 1; 
/** Indicates ALAW format. */ 
public static final short FORMAT_ALAW = 6; 
/** Indicates ULAW format. */ 
public static final short FORMAT_ULAW = 7; 

private short mFormat; 
private short mNumChannels; 
private int mSampleRate; 
private short mBitsPerSample; 
private int mNumBytes; 

public MyWaveHeader(short format, short numChannels, int sampleRate, short bitsPerSample, int numBytes) { 
    mFormat = format; 
    mSampleRate = sampleRate; 
    mNumChannels = numChannels; 
    mBitsPerSample = bitsPerSample; 
    mNumBytes = numBytes; 
} 

private static void readId(InputStream in, String id) throws IOException { 
    for (int i = 0; i < id.length(); i++) { 
     if (id.charAt(i) != in.read()) throw new IOException(id + " tag not present"); 
    } 
} 

private static int readInt(InputStream in) throws IOException { 
    return in.read() | (in.read() << 8) | (in.read() << 16) | (in.read() << 24); 
} 

private static short readShort(InputStream in) throws IOException { 
    return (short)(in.read() | (in.read() << 8)); 
} 

public int write(OutputStream out) throws IOException { 
    /* RIFF header */ 
    writeId(out, "RIFF"); 
    writeInt(out, 36 + mNumBytes); 
    writeId(out, "WAVE"); 

    /* fmt chunk */ 
    writeId(out, "fmt "); 
    writeInt(out, 16); 
    writeShort(out, mFormat); 
    writeShort(out, mNumChannels); 
    writeInt(out, mSampleRate); 
    writeInt(out, mNumChannels * mSampleRate * mBitsPerSample/8); 
    writeShort(out, (short)(mNumChannels * mBitsPerSample/8)); 
    writeShort(out, mBitsPerSample); 

    /* data chunk */ 
    writeId(out, "data"); 
    writeInt(out, mNumBytes); 

    return HEADER_LENGTH; 
} 

private static void writeId(OutputStream out, String id) throws IOException { 
    for (int i = 0; i < id.length(); i++) out.write(id.charAt(i)); 
} 

private static void writeInt(OutputStream out, int val) throws IOException { 
    out.write(val >> 0); 
    out.write(val >> 8); 
    out.write(val >> 16); 
    out.write(val >> 24); 
} 

private static void writeShort(OutputStream out, short val) throws IOException { 
    out.write(val >> 0); 
    out.write(val >> 8); 
} 

@Override 
public String toString() { 
    return String.format(
      "WaveHeader format=%d numChannels=%d sampleRate=%d bitsPerSample=%d numBytes=%d", 
      mFormat, mNumChannels, mSampleRate, mBitsPerSample, mNumBytes); 
}} 

步驟3:寫功能混合兩種WAV聲音。

private void mixSound() throws IOException { 

    InputStream in1 = getResources().openRawResource(R.raw.music1_mono_low); 
    InputStream in2 = getResources().openRawResource(R.raw.rec1_mono_low); 

    Wave w1 = new Wave(in1); 
    short[] music1 = w1.getSampleAmplitudes(); 

    in1.close(); 


    Wave w2 = new Wave(in2); 
    short[] music2 = w2.getSampleAmplitudes(); 
    in2.close(); 

    byte[] output = new byte[(music1.length > music2.length) ? music2.length 
      : music1.length]; 

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

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

     float mixed = (samplef1 + samplef2)/2; 

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

    } // for loop 


    File f = new File("/mnt/sdcard/mixed_sound.wav"); 
    if (f.exists()) { 
     f.delete(); 
    } 

    FileOutputStream fo = new FileOutputStream(f); 

    WaveHeader wh = w2.getWaveHeader(); 
    MyWaveHeader mwh = new MyWaveHeader((short) wh.getAudioFormat(), 
      (short) wh.getChannels(), wh.getSampleRate(), 
      (short) wh.getBitsPerSample(), output.length); 
    mwh.write(fo); 

    fo.write(output); 
    fo.flush(); 
    fo.close(); 

    //For playing the sound immediately after mixing 
    // MusicPlayer 
    MediaPlayer mp = new MediaPlayer(); 
    // Listeners 
    mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { 

     @Override 
     public void onCompletion(MediaPlayer mp) { 
      // TODO Auto-generated method stub 

     } 
    }); // Important 

    mp.reset(); 

    mp.setDataSource("/mnt/sdcard/mixed_sound.wav"); 
    mp.setAudioStreamType(AudioManager.STREAM_MUSIC); 

    mp.prepare(); 
    mp.start(); 
} 
相關問題