在Java/Android中添加两个音频信号

在Java/Android中添加两个音频信号,java,audio,echo,Java,Audio,Echo,我在试着做我自己的回声垫,事实上在回声部分之前一切都很顺利 起初我从声音创作开始,它很棒,但当我开始添加回声效果时,它听起来很愚蠢 代码 package com.echo; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.A

我在试着做我自己的回声垫,事实上在回声部分之前一切都很顺利

起初我从声音创作开始,它很棒,但当我开始添加回声效果时,它听起来很愚蠢

代码

package com.echo;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;

public class WavePlay {

    private final static float duration = 1f; // seconds
    private final static int sampleRate = 44100;
    private final static int numSamples = (int) (duration * sampleRate);
    private final static double sample[] = new double[numSamples];

    private static SourceDataLine line = null;
    private static int freqOfTone = 30;

    private static byte[] original;

    public static void main(String[] args) {

        AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
                sampleRate, 8, 1, 1, sampleRate, true);

        DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);

        try {
            line = (SourceDataLine) AudioSystem.getLine(info);
            line.open(format);
        } catch (LineUnavailableException e) {
            e.printStackTrace();
        }

        for (int i = 0; i < numSamples; ++i) {
            sample[i] = 255 * Math.sin(2 * Math.PI * i
                    / (sampleRate / freqOfTone));

        }

        final byte generatedSnd[] = new byte[100000];

        original = new byte[generatedSnd.length];

        for (int i = 0; i < 20000; i++) {

            generatedSnd[i] = (byte) (sample[i % sample.length] + 1);

            original[i] = generatedSnd[i];

        }

        // Echo

        int delaySamples = 10000;

        float decay = 0.3f;

        for (int j = 0; j < 5; j++) {
            for (int i = 0; i < generatedSnd.length; i++) {

                if (i < delaySamples * (j + 1)) {
                    continue;
                }

                generatedSnd[i] += (byte) (original[i - delaySamples * (j + 1)] * decay);

            }

            decay *= 0.4;
        }

        // play

        InputStream source = new ByteArrayInputStream(generatedSnd);

        int numRead = 0;
        byte[] buf = new byte[line.getBufferSize()];

        line.start();
        // read and play chunks of the audio
        try {
            while ((numRead = source.read(buf, 0, buf.length)) >= 0) {
                int offset = 0;
                while (offset < numRead)
                    offset += line.write(buf, offset, numRead - offset);
            }
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }

        line.drain();
        line.stop();
        line.close();

        System.exit(0);
    }

}
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;

public class WavePlay {

    public static void main(String[] args) {

        float duration = 1f; // seconds
        int sampleRate = 44100;
        int numSamples = (int) (duration * sampleRate);
        double sample[] = new double[numSamples];

        SourceDataLine line = null;
        int freqOfTone = 300;

        double[] original;

        AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
                sampleRate, 8, 1, 1, sampleRate, true);

        DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);

        try {
            line = (SourceDataLine) AudioSystem.getLine(info);
            line.open(format);
        } catch (LineUnavailableException e) {
            e.printStackTrace();
        }

        double increment = 2 * Math.PI * freqOfTone / sampleRate;
        double angle = 0;

        for (int i = 0; i < numSamples; ++i) {
            sample[i] = (Math.sin(angle)) * Byte.MAX_VALUE;
            angle += increment;
        }

        final double generatedSnd[] = new double[200000];

        original = new double[generatedSnd.length];

        for (int i = 0; i < 20000; i++) {
            generatedSnd[i] = sample[i % sample.length];

            original[i] = generatedSnd[i];

        }

        // Echo

        int delaySamples = 20000;

        float decay = 0.8f;

        double maxValue = Byte.MAX_VALUE;

        for (int j = 0; j < 10; j++) {
            for (int i = 0; i < generatedSnd.length; i++) {

                if (i < delaySamples * (j + 1)) {
                    continue;
                }

                generatedSnd[i] += original[i - delaySamples * (j + 1)] * decay;
                if(generatedSnd[i] > maxValue){
                    maxValue = generatedSnd[i]; 
                }

            }

            decay *= 0.5;
        }

        //scale to fit byte length (8 bit)
        byte[] out = new byte[generatedSnd.length];

        for (int i = 0; i < out.length; i++) {
            out[i] = (byte)(Byte.MAX_VALUE * generatedSnd[i] / maxValue);
        }

        // play

        InputStream source = new ByteArrayInputStream(out);

        int numRead = 0;
        byte[] buf = new byte[line.getBufferSize()];

        line.start();
        // read and play chunks of the audio
        try {
            while ((numRead = source.read(buf, 0, buf.length)) >= 0) {
                int offset = 0;
                while (offset < numRead)
                    offset += line.write(buf, offset, numRead - offset);
            }
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }

        line.drain();
        line.stop();
        line.close();

        System.exit(0);
    }

}
package com.echo;
导入java.io.ByteArrayInputStream;
导入java.io.IOException;
导入java.io.InputStream;
导入javax.sound.sampled.AudioFormat;
导入javax.sound.sampled.AudioSystem;
导入javax.sound.sampled.DataLine;
导入javax.sound.sampled.LineUnavailableException;
导入javax.sound.sampled.SourceDataLine;
公共类波浪游戏{
私有最终静态浮动持续时间=1f;//秒
私人最终静态int采样器=44100;
私有最终静态int numSamples=(int)(持续时间*采样器);
私有最终静态双样本[]=新双样本[numSamples];
私有静态SourceDataLine=null;
专用静态int频率=30;
私有静态字节[]原始;
公共静态void main(字符串[]args){
AudioFormat格式=新的AudioFormat(AudioFormat.Encoding.PCM_签名,
采样器,8,1,1,采样器,真);
DataLine.Info=newdataline.Info(SourceDataLine.class,格式);
试一试{
line=(SourceDataLine)AudioSystem.getLine(info);
行。打开(格式);
}捕获(LineUnavailableException e){
e、 printStackTrace();
}
对于(int i=0;i=0){
整数偏移=0;
while(偏移量
请运行代码并告诉我是否有任何问题


提前多谢了

事实上有几个错误,下面的代码通过这些更改生成了更清晰的结果:

  • 写入缓冲区中的值必须小于Byte.MAX_值(如果在支持短数组的android上写入,则偏移量将短于.MAX_值)

  • 示例创建是以更简洁的方式实现的

代码

package com.echo;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;

public class WavePlay {

    private final static float duration = 1f; // seconds
    private final static int sampleRate = 44100;
    private final static int numSamples = (int) (duration * sampleRate);
    private final static double sample[] = new double[numSamples];

    private static SourceDataLine line = null;
    private static int freqOfTone = 30;

    private static byte[] original;

    public static void main(String[] args) {

        AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
                sampleRate, 8, 1, 1, sampleRate, true);

        DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);

        try {
            line = (SourceDataLine) AudioSystem.getLine(info);
            line.open(format);
        } catch (LineUnavailableException e) {
            e.printStackTrace();
        }

        for (int i = 0; i < numSamples; ++i) {
            sample[i] = 255 * Math.sin(2 * Math.PI * i
                    / (sampleRate / freqOfTone));

        }

        final byte generatedSnd[] = new byte[100000];

        original = new byte[generatedSnd.length];

        for (int i = 0; i < 20000; i++) {

            generatedSnd[i] = (byte) (sample[i % sample.length] + 1);

            original[i] = generatedSnd[i];

        }

        // Echo

        int delaySamples = 10000;

        float decay = 0.3f;

        for (int j = 0; j < 5; j++) {
            for (int i = 0; i < generatedSnd.length; i++) {

                if (i < delaySamples * (j + 1)) {
                    continue;
                }

                generatedSnd[i] += (byte) (original[i - delaySamples * (j + 1)] * decay);

            }

            decay *= 0.4;
        }

        // play

        InputStream source = new ByteArrayInputStream(generatedSnd);

        int numRead = 0;
        byte[] buf = new byte[line.getBufferSize()];

        line.start();
        // read and play chunks of the audio
        try {
            while ((numRead = source.read(buf, 0, buf.length)) >= 0) {
                int offset = 0;
                while (offset < numRead)
                    offset += line.write(buf, offset, numRead - offset);
            }
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }

        line.drain();
        line.stop();
        line.close();

        System.exit(0);
    }

}
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;

public class WavePlay {

    public static void main(String[] args) {

        float duration = 1f; // seconds
        int sampleRate = 44100;
        int numSamples = (int) (duration * sampleRate);
        double sample[] = new double[numSamples];

        SourceDataLine line = null;
        int freqOfTone = 300;

        double[] original;

        AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
                sampleRate, 8, 1, 1, sampleRate, true);

        DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);

        try {
            line = (SourceDataLine) AudioSystem.getLine(info);
            line.open(format);
        } catch (LineUnavailableException e) {
            e.printStackTrace();
        }

        double increment = 2 * Math.PI * freqOfTone / sampleRate;
        double angle = 0;

        for (int i = 0; i < numSamples; ++i) {
            sample[i] = (Math.sin(angle)) * Byte.MAX_VALUE;
            angle += increment;
        }

        final double generatedSnd[] = new double[200000];

        original = new double[generatedSnd.length];

        for (int i = 0; i < 20000; i++) {
            generatedSnd[i] = sample[i % sample.length];

            original[i] = generatedSnd[i];

        }

        // Echo

        int delaySamples = 20000;

        float decay = 0.8f;

        double maxValue = Byte.MAX_VALUE;

        for (int j = 0; j < 10; j++) {
            for (int i = 0; i < generatedSnd.length; i++) {

                if (i < delaySamples * (j + 1)) {
                    continue;
                }

                generatedSnd[i] += original[i - delaySamples * (j + 1)] * decay;
                if(generatedSnd[i] > maxValue){
                    maxValue = generatedSnd[i]; 
                }

            }

            decay *= 0.5;
        }

        //scale to fit byte length (8 bit)
        byte[] out = new byte[generatedSnd.length];

        for (int i = 0; i < out.length; i++) {
            out[i] = (byte)(Byte.MAX_VALUE * generatedSnd[i] / maxValue);
        }

        // play

        InputStream source = new ByteArrayInputStream(out);

        int numRead = 0;
        byte[] buf = new byte[line.getBufferSize()];

        line.start();
        // read and play chunks of the audio
        try {
            while ((numRead = source.read(buf, 0, buf.length)) >= 0) {
                int offset = 0;
                while (offset < numRead)
                    offset += line.write(buf, offset, numRead - offset);
            }
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }

        line.drain();
        line.stop();
        line.close();

        System.exit(0);
    }

}
import java.io.ByteArrayInputStream;
导入java.io.IOException;
导入java.io.InputStream;
导入javax.sound.sampled.AudioFormat;
导入javax.sound.sampled.AudioSystem;
导入javax.sound.sampled.DataLine;
导入javax.sound.sampled.LineUnavailableException;
导入javax.sound.sampled.SourceDataLine;
公共类波浪游戏{
公共静态void main(字符串[]args){
浮动持续时间=1f;//秒
int-sampleRate=44100;
int numSamples=(int)(持续时间*取样器);
双样本[]=新的双样本[numSamples];
SourceDataLine=null;
int频率=300;
双[]原件;
AudioFormat格式=新的AudioFormat(AudioFormat.Encoding.PCM_签名,
采样器,8,1,1,采样器,真);
DataLine.Info=newdataline.Info(SourceDataLine.class,格式);
试一试{
line=(SourceDataLine)AudioSystem.getLine(info);
行。打开(格式);
}捕获(LineUnavailableException e){
e、 printStackTrace();
}
双增量=2*Math.PI*频率/采样器;
双角度=0;
对于(int i=0;imaxValue){
maxValue=generatedSnd[i];
}
}
衰减*=0.5;
}
//缩放以适应字节长度(8位)
byte[]out=新字节[generatedSnd.length];
for(int i=0;i