870920 Menu

SwingCoder之数字音频与DSP编程基础·3

DSP基本处理

标准化(Normalized):振幅最大化。示例:
float maxValue = 0.0f;
for (int i = 0; i < samplesNum; ++i) // 先查找最大值
maxValue = samples[i] > maxValue ? samples[i] : maxValue;
if (maxValue == 1.0f || maxValue <= 0.0f) return;
for (int i = 0; i < samplesNum; ++i) // 所有采样值除以最大值后赋值给自身
samples[i] /= maxValue;

混合信号(Mixer):
两个或多个信号的同一个时间点的采样值相加。需注意:反相归零;相位漂移;音高掩盖。
缩放振幅(Scaling):
每个采样值乘以一个百分比值(缩放因子,增益/衰减比率,大于1为增益,小于1为衰减)。
DC偏移(Offset):
每个采样值加上一个常量(偏移量),注意要进行振幅缩放,以防止过载。可生成单极信号。
环形调制(Ring Modulation):将两个不同音高频率的信号的采样值逐个相乘。调制后的振幅和音高频率为:0.5 × (两个信号的音高频率之和 + 两个信号的音高频率之差)
傅里叶级数(Fourier Series):某个音高频率(基频)所构成的单周期正弦波可解构为多个不同频率的正弦波所混合的结果。这些不同的正弦波的音高频率为基频的整数倍,可以生成的新的正弦波的个数可以计算出来:基频反复乘以从2开始递增的整数,只要结果频率小于采样率/2即可。此时,递增的次数即为可生成的新正弦波的最大个数,由这些频率所构成的数列即为傅里叶级数。
延迟(Delays):将当前采样值衰减后与后面的采样值相加,相当于同一信号的不同时间点的采样值错位混合。回声、混响、延迟等音频效果处理中均用到此技术。示例:
// delayTime为延迟的秒数,sampleRate为采样率,delays为延迟的采样个数
int delays = delayTime * sampleRate;
float ampRatio = 0.5f; // 延迟采样的振幅衰减比例
for (int i = 0; i < samplesNum; ++i)
samples[i] += (delats < i) ? samples[i – delaatSamples] * ampRatio : 0.0f;
 线性声像
/** 计算线性声像模式下,左右通道的增益比率。
1参:当前声像位置:-1.0为极左,1.0为极右,0为居中。
2参:所传入的左通道增益值,本函数将修改之
3参:所传入的右通道增益值,本函数将修改之 */
void MainContentComponent::getLinerPanRatio (const double& panValue,
double& leftFactor,
double& rightFactor) const {
leftFactor = (panValue <= 0) ? 1.0 : 1.0 – panValue;
rightFactor = (panValue <= 0) ? 1.0 + panValue : 1.0;
}
 线性插值
每个采样值均有两个属性,相当于坐标系中的一个点,x坐标对应该采样所位于的时间点,y坐标对应振幅(值)。现已知开始点的时间和值、结束点的时间和值,给出两者之间任意一个时间点,算出该点的值。这个值,就称为“插值”。换一种说法:该值不是利用三角函数或其它波形合成公式计算出来的,而是根据开始点、结束点、所位于的时间点这三个要素“插”进来的。计算过程:
1、首先判断插值点的时间是否大于等于结束点的时间,如果是,则直接返回结束点的值
2、而后判断开始点和结束点的时间(x坐标)是否一致,如果一致,返回结束点的值
3、计算插值比率,公式:frac = (插值时间 – 开始时间) / (结束时间 – 开始时间)
4、根据插值比率算出插值点的值,公式:value = 开始值 + (结束值 – 开始值) * 差值比率
线性插值不仅常用于音频和DSP领域,其它领域运用的也非常广泛,比如图像处理等。
 指数衰减:对一批连续的采样值进行指数增益或衰减,增益(衰减)率计算公式为:
增益/衰减率 = pow(结束值 / 开始值, 1.0 / 采样数)
通常,如果是从零增益至最大振幅,开始值设为0.0001(1.0E-4,约-80dB),不能是0。可在计算后,再将第一个采样值置为0。同理,如果是衰减,结束值也同样设为0.0001(只能是无限逼近0,却永远不会等于0,这是指数函数的本质,可参见指数函数的坐标图),计算后再将最后一个采样值置零。
 振幅(采样值)转换为分贝值的公式:
// 参数必须大于0。如果是最小振幅,则可置为1.0E-4
double dB = 20.0 * log10(sampleValue);
满刻度振幅1.0f对应0dB,0.5f对应-6dB。振幅每*0.5f,分贝值下降6dB。
可导出,分贝值转换为振幅(采样值)的对应公式:振幅 = pow (10, dB / 20)
 将采样值转换为屏幕绘制所需的y坐标(此处必须用绘制区域的高度减去转换后的y坐标,因为计算机屏幕绘制的坐标系y轴与笛卡尔坐标系的y轴是相反的):
y = 绘制区域的高度-(samples[i] * y轴方向上的半径(振动高度)+y轴方向上的圆心坐标)
每个采样所对应的绘制x坐标,由该采样所对应的时间点来确定。
 采样率、采样帧数、采样个数、时值的转换公式:
采样个数 = 采样帧数 * 通道数
采样帧数 = 采样率 * 时值(秒数)
时值(秒数) = 采样帧数 / 通道数 / 采样率
实际使用中,所谓的采样个数,其实指的是采样帧数。因为每个通道均有自己的采样值,同一个通道的所有采样个数加到一起,才是采样帧数。