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