我正在开发一个Android应用程序,可以从麦克风中实时处理音频。采样和播放工作有效,但我很难实现第一个音频效果 - 失真。音频来自短路缓冲区,因此每次收到其中一个时,我会尝试将值映射到有符号短路的完整大小,然后在这些值高于某个级别时实际上剪切这些值。来自此的音频肯定是扭曲的,但不是理想的方式。我已经包含了我的代码来完成这个。谁能在这里看到错误?
public void onMarkerReached(AudioRecord recorder) {
// TODO Auto-generated method stub
short max = maxValue(buffers[ix]);
short multiplier;
if(max!=0)
multiplier = (short) (0x7fff/max);
else
multiplier = 0x7fff;
double distLvl =.8;
short distLvlSho = 31000;
short max2 =100;
for(int i=0;i<buffers[ix].length;i++){
buffers[ix][i]=(short) (buffers[ix][i]*multiplier);
if(buffers[ix][i]>distLvlSho)
buffers[ix][i]=distLvlSho;
else if(buffers[ix][i]<-distLvlSho)
buffers[ix][i]=(short)-distLvlSho;
buffers[ix][i]=(short) (buffers[ix][i]/multiplier);
}
缓冲区数组是一个短的二维数组,处理只在阵列中的一个数组上完成,这里是缓冲区[ix]。
答案 0 :(得分:2)
据我所知,你得到的只是一个剪辑源,剪辑阈值跟随clipThr / max(输入)= distLvlSho / 0x7fff的比例。这种方式的大部分输入基本没有变化。
如果你真的想扭曲信号,你应该对整个信号应用某种非线性函数(最后在样本最大值附近剪切以模拟模拟饱和度)
本书列出了一些简单的失真模型:http://books.google.it/books?id=h90HIV0uwVsC&printsec=frontcover#v=onepage&q&f=false
最简单的是一种simmetrical软剪辑(参见第118页)。这是使用该软剪辑功能修改的方法,看看它是否适合您对失真声音的需求(我通过在输入上组成一些正弦曲线并使用excel绘制输出来测试它)
在同一章中,您将找到一个简单的管道建模和模糊滤波器建模(这些都有一些指数,所以如果性能是一个问题,您可能想要近似那些)。
public void onMarkerReachedSoftClip(short[] buffer) {
double th=1.0/3.0;
double multiplier = 1.0/0x7fff; // normalize input to double -1,1
double out = 0.0;
for(int i=0;i<buffer.length;i++){
double in = multiplier*(double)buffer[i];
double absIn = java.lang.Math.abs(in);
if(absIn<th){
out=(buffer[i]*2*multiplier);
}
else if(absIn<2*th){
if(in>0)out= (3-(2-in*3)*(2-in*3))/3;
else if(in<0)out=-(3-(2-absIn*3)*(2-absIn*3))/3;
}
else if(absIn>=2*th){
if(in>0)out=1;
else if(in<0)out=-1;
}
buffer[i] = (short)(out/multiplier);
}
}
答案 1 :(得分:0)
如果乘以2个短整数,结果需要一个长整数或结果可能溢出。
e.g。 1000 * 1000 = 1000000,对于16位短整数来说太大了。
因此,您需要执行缩放操作(除法或右移)之前将乘法结果转换为较短的存储值。类似的东西:
result_short = (short)( ( short_op_1 * short_op_2 ) >> 16 );