音频均衡器,在影音方面,是指对声频信号各个频段的补偿作用。对于不同的频率,有着不同的增益,这便形成了不同的音乐效果。
1.均衡器的调整方法:
超低音:20Hz-40Hz,适当时声音强而有力。能控制雷声、低音鼓、管风琴和贝司的声音。过度提升会使音乐变得混浊不清。
低音:40Hz-150Hz,是声音的基础部份,其能量占整个音频能量的70%,是表现音乐风格的重要成份。
适当时,低音张弛得宜,声音丰满柔和,不足时声音单薄,150Hz,过度提升时会使声音发闷,明亮度下降,鼻音增强。
中低音:150Hz-500Hz,是声音的结构部分,人声位于这个位置,不足时,演唱声会被音乐淹没,声音软而无力,适当提升时会感到浑厚有力,提高声音的力度和响度。提升过度时会使低音变得生硬,300Hz处过度提升3-6dB,如再加上混响,则会严重影响声音的清晰度。
中音:500Hz-2KHz,包含大多数乐器的低次谐波和泛音,是小军鼓和打击乐器的特征音。适当时声音透彻明亮,不足时声音朦胧。过度提升时会产生类似电话的声音。
中高音:2KHz-5KHz,是弦乐的特征音(拉弦乐的弓与弦的摩搡声,弹拔乐的手指触弦的声音某)。不足时声音的穿透力下降,过强时会掩蔽语言音节的识别。
高音:7KHz-8KHz,是影响声音层次感的频率。过度提升会使短笛、长笛声音突出,语言的齿音加重和音色发毛。
极高音:8KHz-10KHz
合适时,三角铁和立叉的金属感通透率高,沙钟的节奏清晰可辨。过度提升会使声音不自然,易烧毁高频单元。
2.平衡悦耳的声音应是:
150Hz以下(低音)应是丰满、柔和而富有弹性;
150Hz-500Hz(中低音)应是浑厚有力百不混浊;
500Hz-5KHz(中高音)应是明亮透彻而不生硬;
5KHz以上(高音)应是纤细,园顺而不尖锐刺耳。
整个频响特性平直时:声音自然丰满而有弹性,层次清晰园顺悦耳。频响多峰谷时:声音粗糙混浊,高音刺耳发毛,无层次感扩声易发生反馈啸叫。
3.频率的音感特征:
30~60Hz 沉闷 如没有相当大的响度,人耳很难感觉。
60~100Hz 沉重 80Hz附近能产生极强的“重感”效果,响度很高也不会给人舒服的感觉,可给人以强烈的刺激作用。
100~200Hz 丰满
200~500Hz 力度 易引起嗡嗡声的烦闷心理。
500~1KHz 明朗 800Hz附近如提升10dB,会明显产生一种嘈杂感,狭窄感。
1K~2KHz 透亮 2800Kz附近明亮感关系最大。
2K~4Kz 尖锐 6800Hz形成尖啸,锐利的感觉。
4K~8Kz 清脆 3400Hz易引起听觉疲劳。
8K~16Kz 纤细 >7.5KHz音感清彻纤细。
4.设计方案:
(1)前置放大电路:
a. 小信号电压放大倍数不小于400倍(输入正弦信号电压有效值小于10mV)。
b. -1dB通频带为20Hz~20kHz。
c. 输出电阻为600。
(2)应用数字信号处理技术,对语音信号(20Hz~20kHz)进行幅频均衡。要求:
a. 输入电阻为600。
b.
经过数字幅频均衡处理后,以10kHz时输出信号电压幅度为基准,通频带20Hz~20kHz内的电压幅度波动在1.5dB以内。
(前置电路采用AD603设计,MCU采样STM32,图略)
(在此感谢 何彪胜同学 提供技术支持)
5.主体部分程序:
/************************************
*函数名:void Init_Gain(void)
*功 能:初始化
*输 入:void
*返 回:void
*注 备:
*************************************/
void Init_FIR(void)
{
DAC_OUT_Init(); //DAC初始化,输出0电平,AD603衰减0dB
Init_ADC_DC(); //初始化AD为直流模式
// TIM1_Configuration(); //初始化
}
/************************************
*函数名:void DAC_out(void)
*功 能:DAC 直流输出
*输 入:u16 volt_mv
*返 回:void
*注 备:输入单位为mv
为了校准在需要输出的电压上减去3mv
*************************************/
void DAC_out(u32 volt_mv)
{
// u16 DA_Code;
//为了校准在需要输出的电压上减去3mv
// DA_Code =
(u16)((volt_mv)*4096/2500); //计算相应码值
// DAC_SetChannel1Data(DAC_Align_12b_R,
DA_Code); //送恒流源参考电压
DAC_SetChannel1Data(DAC_Align_12b_R,
(u16)volt_mv); //送恒流源参考电压
DAC_SoftwareTriggerCmd(DAC_Channel_1, ENABLE);
}
/************************************
*函数名:void DAC_OUT_Init(void)
*功 能:DAC 直流输出初始化
*输 入:void
*返 回:void
*注 备:
*************************************/
void DAC_OUT_Init(void)
{
DAC_InitTypeDef DAC_InitStructure;
/* DAC Periph clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC,
ENABLE);
/* DAC channel1 Configuration */
DAC_InitStructure.DAC_Trigger =
DAC_Trigger_Software; //DAC软件触发
DAC_InitStructure.DAC_WaveGeneration =
DAC_WaveGeneration_None; //禁用噪声或三角波发生
DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude =
DAC_TriangleAmplitude_4095;
DAC_InitStructure.DAC_OutputBuffer =
DAC_OutputBuffer_Disable;
DAC_Init(DAC_Channel_1, &DAC_InitStructure);
/* DAC channel2 Configuration */
DAC_Init(DAC_Channel_2, &DAC_InitStructure);
/* Enable DAC Channel1: 当使能DAC通道1后, PA.04 自动连接到DAC转换器
*/
DAC_Cmd(DAC_Channel_1, ENABLE);
/* Enable DAC Channel2: 当使能DAC通道2后, PA.05 自动连接到DAC转换器
*/
DAC_Cmd(DAC_Channel_2, ENABLE);
/* Set DAC dual channel DHR12RD register
*/ //数据12位右对齐,DAC通道2,通道1
DAC_SetDualChannelData(DAC_Align_12b_R, 0, 0);
//通道1~0.15V f6
DAC_SoftwareTriggerCmd(DAC_Channel_1, ENABLE);
DAC_SoftwareTriggerCmd(DAC_Channel_2, ENABLE);
}
/************************************
*函数名:u16 Get_AD_value(void)
*功 能:软件触发AD使能
*输 入:void
*返 回:u16 AD_value
*注 备:
*************************************/
u16 Get_AD_value(void)
{
u16 AD_value=0;
//舍去第一次采样值
/* ADC_SoftwareStartConvCmd(ADC1, ENABLE);
while(ADC_GetCalibrationStatus(ADC1)); //等待转换完成
AD_value = ADC_GetConversionValue(ADC1);
*/
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
while(ADC_GetCalibrationStatus(ADC1)); //等待转换完成
AD_value = ADC_GetConversionValue(ADC1);
return AD_value;
}
/************************************
*函数名:void Init_ADC_DC(void)
*功 能:初始化ADC1为直流,软件触发方式
*输 入:void
*返 回:void
*注 备:
*************************************/
void Init_ADC_DC(void)
{
ADC_InitTypeDef ADC_InitStructure;
/* ADC1 configuration
------------------------------------------------------*/
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
//ADC 工作模式 ADC1 ADC2 单独工作
ADC_InitStructure.ADC_ScanConvMode =
DISABLE; //多通道扫描模式
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
//是否启用连续转换模式ENABLE
ADC_InitStructure.ADC_ExternalTrigConv =
ADC_ExternalTrigConv_None; //软件触发方式
ADC_InitStructure.ADC_DataAlign =
ADC_DataAlign_Right; //数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = 1; //ADC规则转换通道数量
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channel8 configuration */ //配置转换规则 PB0
ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1,
ADC_SampleTime_1Cycles5);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE); //使能ADC1
/* Enable ADC1 DMA */
ADC_DMACmd(ADC1, ENABLE);
/* Enable Vrefint channel17 */
// ADC_TempSensorVrefintCmd(ENABLE);
/* Enable ADC1 reset calibaration register */
ADC_ResetCalibration(ADC1);
/* Check the end of ADC1 reset calibration register */
while(ADC_GetResetCalibrationStatus(ADC1));
/* Start ADC1 calibaration */
ADC_StartCalibration(ADC1);
/* Check the end of ADC1 calibration */
while(ADC_GetCalibrationStatus(ADC1));
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //开启ADC
}
//Step3.TIM1模块设置
void TIM1_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_BaseInitStructure;
// TIM_OCInitTypeDef TIM_OCInitStructure;
//TIM1 使用内部时钟
//TIM_InternalClockConfig(TIM1);
//TIM1基本设置
//设置预分频器分频系数71,即APB2=72M, TIM1_CLK=72/72=1MHz
//TIM_Period(TIM1_ARR)=1000,计数器向上计数到1000后产生更新事件,计数值归零
//向上计数模式
//TIM_RepetitionCounter(TIM1_RCR)=0,每次向上溢出都产生更新事件
TIM_BaseInitStructure.TIM_Period = 1800;
TIM_BaseInitStructure.TIM_Prescaler = 0;
TIM_BaseInitStructure.TIM_ClockDivision = 0;
TIM_BaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_BaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1, &TIM_BaseInitStructure);
//清中断,以免一启用中断后立即产生中断
TIM_ClearFlag(TIM1, TIM_FLAG_Update);
//使能TIM1中断源
TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);
//TIM1总开关:开启
TIM_Cmd(TIM1, ENABLE);
}
//64HZ低通
u16 IIR_LPF_64Hz(void)
{
static long long buf_64Hzn=0,buf_64Hzn_1=0,buf_64Hzn_2=0;
s16 xn,yn;
xn = Get_AD_value();
buf_64Hzn = (xn-2048)*16 + (19844*buf_64Hzn_1 -
9845*buf_64Hzn_2)/10000;
yn = 3*(buf_64Hzn + 2*buf_64Hzn_1 + buf_64Hzn_2)/100000 +
32768;
buf_64Hzn_2 = buf_64Hzn_1;
buf_64Hzn_1 = buf_64Hzn;
return yn;
}
//125Hz带通
u16 IIR_BPF_125Hz(void)
{
static long long
buf1_125_n=0,buf1_125_n_1=0,buf1_125_n_2=0;
static long long
buf2_125_n=0,buf2_125_n_1=0,buf2_125_n_2=0;
s16 xn,y1n,y2n;
xn = Get_AD_value(); //获取AD采样值
//第一级
buf1_125_n = xn + 1.9932*buf1_125_n_1 -
0.9936*buf1_125_n_2;
// y1n = 0.00391612*(buf1_125_n -
buf1_125_n_2); //**** 加上会失真 +
32768
y1n = 78*(buf1_125_n - buf1_125_n_2)/1000000 +2048;
buf1_125_n_2 = buf1_125_n_1;
buf1_125_n_1 = buf1_125_n;
//第二级
buf2_125_n = y1n + (2045*buf2_125_n_1 -
1022*buf2_125_n_2)>>10;
y2n = 0.00391612*(buf2_125_n - buf2_125_n_2) + 2048;
//
// y2n = 257*(buf2_125_n - buf2_125_n_2)>>16 +
2048; //
buf2_125_n_2 = buf2_125_n_1;
buf2_125_n_1 = buf2_125_n;
return y2n;
}
//1k带通
u16 IIR_BPF_1k(void)
{
static long long
buf1_1k_n=0,buf1_1k_n_1=0,buf1_1k_n_2=0;
static long long
buf2_1k_n=0,buf2_1k_n_1=0,buf2_1k_n_2=0;
s16 xn,y1n,y2n;
xn = Get_AD_value(); //获取AD采样值
//第一级
buf1_1k_n = xn + (1958*buf1_1k_n_1 -
979*buf1_1k_n_2)/1000;
y1n = 3*(buf1_1k_n - buf1_1k_n_2)/1000;
//**** 加上会失真 + 32768
buf1_1k_n_2 = buf1_1k_n_1;
buf1_1k_n_1 = buf1_1k_n;
//第二级
buf2_1k_n = y1n + (1949*buf2_1k_n_1 -
977*buf2_1k_n_2)/1000;
y2n = 816*(buf2_1k_n - buf2_1k_n_2)/10000 + 2048;
//
buf2_1k_n_2 = buf2_1k_n_1;
buf2_1k_n_1 = buf2_1k_n;
return y2n;
}
//2k带通 偏移
u16 IIR_BPF_2k(void)
{
static long long
buf1_2k_n=0,buf1_2k_n_1=0,buf1_2k_n_2=0;
static long long
buf2_2k_n=0,buf2_2k_n_1=0,buf2_2k_n_2=0;
s16 xn,y1n,y2n;
xn = Get_AD_value(); //获取AD采样值
//第一级
buf1_2k_n = xn + (1889*buf1_2k_n_1 - 979*buf1_2k_n_2)/1000
;
y1n = 155*(buf1_2k_n - buf1_2k_n_2)/10000;
// 加上会失真 + 32768
buf1_2k_n_2 = buf1_2k_n_1;
buf1_2k_n_1 = buf1_2k_n;
//第二级
buf2_2k_n = y1n + (1874*buf2_2k_n_1 - 977*buf2_2k_n_2)/1000
;
y2n = 155*(buf2_2k_n - buf2_2k_n_2)/10000 + 2048;
//
buf2_2k_n_2 = buf2_2k_n_1;
buf2_2k_n_1 = buf2_2k_n;
return y2n;
}
//8K FIR 高通 定点
u32 FIR_HPF_8k(void)
{
static s32 xn_1=0,xn_2=0,xn_3=0,xn_4=0;
s32 xn;
s32 yn;
xn = Get_AD_value()-2048; //获取AD采样值
//*1024倍
// yn = -135.8181910486016*(xn + xn_4) -
187.696123738624*(xn_1 + xn_3) + 803.9252064246784*xn_2;
yn = -136*(xn + xn_4) - 187*(xn_1 + xn_3) + 804*xn_2
; //*1024倍
xn_4 = xn_3;
xn_3 = xn_2;
xn_2 = xn_1;
xn_1 = xn;
//加上偏置2048*1024
yn = (yn + 2097152)>>10; //DA_value =
yn[22:10] 即:yn>>10
return yn;
}