如何混合两个无噪音的wav文件?

时间:2016-12-02 09:53:40

标签: android audio noise-reduction

我正在混合两个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();
        }
    }
}

1 个答案:

答案 0 :(得分: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();
}