Java 在没有剪辑的情况下,向音频样本中添加音频样本的正确方法是什么

Java 在没有剪辑的情况下,向音频样本中添加音频样本的正确方法是什么,java,signal-processing,audio-processing,Java,Signal Processing,Audio Processing,我以不同频率生成声音样本(sin/saw/triangle生成器),作为双值数组[-1…1]​​(1-最大振幅)。我想把所有信号合并成一个信号 1) 如果我添加(组合使用normalize)并最终将其规格化为[-1…1]——声音质量很好,但信号太安静 2) 如果我使用线性(CombinewithlineynarangeCompression)或对数(CombinewithlineynarangeCompression)压缩进行添加-信号更响亮,但质量很差(金属声音)。 我做错了什么?我想我错过了

我以不同频率生成声音样本(sin/saw/triangle生成器),作为双值数组[-1…1]​​(1-最大振幅)。我想把所有信号合并成一个信号

1) 如果我添加(组合使用normalize)并最终将其规格化为[-1…1]——声音质量很好,但信号太安静

2) 如果我使用线性(CombinewithlineynarangeCompression)或对数(CombinewithlineynarangeCompression)压缩进行添加-信号更响亮,但质量很差(金属声音)。 我做错了什么?我想我错过了处理步骤。 在创建最终文件时,添加来自多个源wav文件的音频信号的一般可接受的算法是什么(雅马哈等合成器使用哪些方法来实现此目的)

附加内容

-我生成的音频(组合两个示例:顶部-组合与规格化,底部-组合与同步压缩)。顶部信号是安静的,但正确。底部-声音更大,但很可怕。

-Java代码(草稿,未优化):

//将样本和线性规格化添加到[-1,1]
公共静态双[]组合与规范化(双[]音频){
if(audio.length==0)返回null;
如果(audio.length==1)返回音频[0];
int maxIdx=0;
//寻找最长的样本
用于(双[]arr:音频)
如果(arr.length>maxIdx)maxIdx=arr.length;
//将0添加到短样本的末尾
对于(int i=0;inormalizer)
归一化器=res;
}
//规范化rezult
双系数=1.0/标准化器;
如果(标准化器!=1.0)
对于(int i=0;i=1 | | threshold<0)返回null;
如果(audio.length==1)返回音频[1];
int maxIdx=0;
//寻找最长的样本
用于(双[]arr:音频)
如果(arr.length>maxIdx)maxIdx=arr.length;
//将0添加到短样本的末尾
对于(int i=0;imaxIdx)maxIdx=arr.length;
//将0添加到短样本的末尾
对于(int i=0;i结果[j]=(absRes我还没有测试您的代码,但我将与您分享一些一般提示:

“我以不同频率生成声音样本(sin/saw/triangle生成器)”

因此,您有一些字节数组中的PCM样本。假设16位,每个
[i]
保存样本的振幅
[i]
。其中
[i]
是您在总样本量中的位置

…“作为一个双值数组”

对于数字声音(PCM),您应该使用
浮点数
。您的输入声音是否为16位格式?您可以稍后转换为16位值整数(或短整数)

另请检查另一个答案:

关于这个问题

“在没有剪辑的情况下,向音频样本中添加音频样本的正确方法是什么?”

使用
+
进行添加有什么问题

final_sample[i] = ( sourceA[i] /2 ) + ( sourceB[i] /2 ); //divide by 2 to halve amplitudes
我们除以2将每个源的振幅减半。这样,即使每个
源的样本值(振幅)为
1.0
,在混合过程中,它们也会给出
0.5
作为其最大值。
混合的
最终样本
现在总计为
1.0
。希望没有剪辑

1)如果我添加(
与规范化组合),并最终规范化为
[-1…1]

结果:音质良好,但信号太安静。”

尝试通过将采样值相乘来增强信号。例如:
signal*2.0//double volume

PS:检查本文和其他堆栈交换答案,了解任何想法:

(1)(尝试相同的逻辑,代码很容易理解)

(2)

(3)

(4)


(5)

谢谢你的回答。也许我写不正确。主要问题:信号a和b的振幅在[-1,1],a+b的最大电平为[-2,2]。如果你使用(sourceA[I]/2)+(sourceB
final_sample[i] = ( sourceA[i] /2 ) + ( sourceB[i] /2 ); //divide by 2 to halve amplitudes