java - 在字节数组上模拟吉他放大器的失真

标签 java math audio filtering simulation

如果我(在Java中)有一个包含音频样本的double[]数组,范围从-1到1,我可以播放它,并且生成的声音就像正在演奏的吉他弦一样,有什么方法可以模拟放大器失真对这些样本的影响吗?

对于“失真”一词的模糊性,我表示歉意,但我指的是类似于将吉他放大器设置为“失真”的任何效果。我已经拥有的听起来像原声吉他,或没有失真的电吉他(设置为“干净”),那么我怎样才能改变阵列,使其听起来更像你所期望的摇滚或金属环境中的电吉他?

当前样本集使用以下方法计算:

double[] samples = new double[duration]; //duration = seconds * sampleRate
int period = (float)sampleRate / (float)frequency;
double[] buf = new double[period]; //a ring buffer used for the sound generation
int count = 0, c1 = 1, c2 = 2;
for(int i=0; i<duration; i++){
    if(count <= period)count = 0;
    if(c1 <= period)c1 = 0;
    if(c2 <= period)c2 = 0;
    if(i < period){
        buf[count] = rand.nextDouble() * 2 - 1; //rand being a Random
    }
    else{
        buff[count] = (buff[c1] + buff[c2]) / 2;
    }
    samples[i] = buff[count];
    count++;
    c1++;
    c2++;
}

最佳答案

失真主要分为三种类型:

  • 硬失真:信号的简单削波

    for (int i = 0; i < duration; i++)
    {
        double sample = samples[i] * gain_pre;
        if (sample > clip)
            sample = clip;
        else
        if (sample < -clip)
            sample = -clip;
        samples[i] = sample * gain_post;
    }
    
  • 正态失真:信号的指数平滑缩放

    double max = 1.0 / (1.0 - exp(-gain_pre));
    for (int i = 0; i < duration; i++)
    {
        double sample = samples[i] * gain_pre;
        double z = (sample < 0.0) ? (-1.0 + exp(sample)) :
                                    (1.0 - exp(-sample));   
        samples[i] = z * max * gain_post;
    }
    
  • 软失真:与上面相同,但使用反正切(可能更激进)

    double max = 1.0 / atan(gain_pre);
    for (int i = 0; i < duration; i++)
    {
        samples[i] = atan(samples[i] * gain_pre) * max * gain_post;
    }
    

变量:

  • gain_pregain_post:预增益和后增益参数
  • clip:硬失真信号的最大值
  • samples:您计算的样本序列

引用资料/更多信息:

http://cp-gfx.sourceforge.net/ (下载源代码并查看/src/effects/)

https://en.wikipedia.org/wiki/Distortion_(music)#Theory_and_circuits

关于java - 在字节数组上模拟吉他放大器的失真,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31643254/

相关文章:

java - 如何从 Gradle 调用静态 Java 方法

java - Mkdir 创建父目录(如果不存在)

c# - Math.Round 方法,从最小的小数开始

java - 在字符串集合中查找相关部分

java - 如何使用 iText 库获取 pdf 文件的给定段落内容?

javascript - 在函数参数中调用 math.rand,然后缩放并转换为 int

android - 你能解释一下(数学计算)手势示例(Levenshtein)吗?

audio - ffmpeg:如何为视频分配空配乐?

java - 不同的音频文件无法播放

ionic-framework - Ionic 4 本地通知声音在 Oreo+ 中不起作用