多媒体实验报告姓名:李浩 日期:2013.6.23作业二:十段均衡器的设计与实现一、实验任务在实现音频10 (作业一)的基础上,编程实现一个具有GUI界面的十段均衡 器小软件,实时对播放音乐进行音效调整二、 功能设计出的图形均衡器,通过调节面板上推拉键的上推或下拉,调节后便可以 直观地反映出所调出的频响曲线,各个频率的提升和衰减情况被图化的显示出 來图示均衡釆用恒定Q值(品质因数)技术,一个推拉键对应一个频点,这个 频点对应一个频段,频点为一个带通滤波器的中心频率,带通滤波器通带宽度保 持恒定,通带即为这个频段三、 设计图示均衡器由一个低通滤波器,一个高通滤波器和若干带通滤波器并联而成 的滤波器组构成这些构成均衡器的滤波器中心频率和带宽都是不变的,每个滤 波器后接一个增益调节器总输出为各个滤波器的加权求和用户通过调节每个 滤波器的输出增益,來改变均衡器的整体频响图示均衡器的整体实现框图,如下图所示:N段图示均衡器的原理框图对于10段图示均衡器,1倍频程图示均衡器的10个中心频点为:31.5Hz, 63Hz, 125Hz, 250Hz, 500Hz, 1000Hz, 2000Hz, 4000Hz, 8000Hz, 16000Hz, 依据这些频点按借频程公式计算各个频段的边界频率,然后设计各频段的滤波 器,然后级联增益调节器再并接起來就构成了 10段图示均衡器。
实现采用二阶IIR带通滤波器级联实现十段图示均衡器带通滤波器主要性能指 标包括中心频率、带宽、增益、品质因子等中心频率(CF):通带滤波器功率谱的值达到最大值时对应的频率带宽(BW):中心频率两边功率衰减3dB时,对应的两个不同频率,分别为上、 下截止频率,上、下截止频率之差为带宽增益(G):均衡器对于各种音效的实现依靠的最重要指标为增益曲线,一般以分 贝为单位表示品质因子(Q):中心频率与带宽的比值,用來表征滤波器的锐度本实验所用参数列如表1所示本实验要求预设十种常见音乐均衡风格,每 种风格对应的滤波器增益如表2所示表I十段I图示均衡器滤波器参数段号中心频率(Hz)上截止频率(Hz)下截止频率(Hz)带宽(Hz)131.5214221263428542312585170854250170339169550033967934061000679138567972000138527151357840002715543127169800053411086154301016000106812172210861表2预设均衡风格增益音乐风格预设增益Default{ 0. 0,0. 0. 0,0. 0, ()• (), 0 }Club{0. 0.0. 1.26 3.2. 1.0}Dance{ 9. & 5. 2. 1.0.・3.・4,・3. 0 }Hull Buss{ 8, 8,8, 7, 4.0, -3,-5,-7, -9 }Full Treble{・9. •& ・7.・6.・3・1.5・ 8.10.12}Pope{-2,-1,0, 2, 3, 2, 0.-2. -2.-1 }Rock{ 6. 5. Z ・2厂5厂Z 0. 3.5.6}Soft{ 2, L 0, 0.・1.0. 12 3,4}Large flail{ & 7,6 2,0,-1,-2, -1,0 }Party{4. 46 2. 0.0. 0.0.0.4}四. 核心代码BOOL CEQDlg: :OiiInitDialogQ {CDialog: :OnInitDialog();//Add M About...n menu item to system menu.J// LDM_ABOUTBOX must be in the system conunand range.ASSERT((IDM_ABOUTBOX & OxFFFO) == LDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < OxFOOO);CMenu* pSysMenu = GetSysteniMenu(FALSE);if (pSysMenu != NULL)fiCStrmg strAboutMenu; strAboutMenu.LoadStimg(IDS_ABOUTBOX);if (! str AboutMenu .IsEmptyO)p SysMenu->AppendMenu (MF_SEPARAT OR); pSysMenu->AppendMenu(MF_STRING5 IDM_ABOUTBOX, stiAboutMenu);// Set the icon for tliis dialog. The fiamework does this automatically // when the applications mam window is not a dialog// Set big icon// Set small iconSetlcon(mjilcon. TRUE);Setlcon(mjilcon. FALSE);// TODO: Add extra initialization hereCScrollBar* pSB=(CScrollBai*) GetDlgItem(IDC_SCR 1); pSB->SetScrollRange(iiMm, iiMax);pSB=(CScrollBar*) GetDlgItem(IDC_SCR2); pSB->SetScrollRange(iiMm, iiMax);pSB=(CScrollBar*) GetDlgItem(IDC_SCR3); pSB->SetScrollRange(iiMm, iiMax);pSB=(CScrollBar*) GetDlgItem(IDC_SCR4); pSB->SetScrollRange(iiMm, iiMax);pSB=(CScrollBar*) GetDlgItem(IDC_SCR5); pSB->SetScrollRange(iiMm, iiMax);pSB=(CScrollBar*) GetDlgItem(IDC_SCR6); pSB->SetScrollRange(iiMm, iiMax);pSB=(CScrollBar*) GetDlgItem(IDC_SCR7); pSB->SetScrollRange(iiMm, iiMax);pSB=(CScrollBar*) GetDlgItem(IDC_SCR8); pSB->SetScrollRange(iiMm, iiMax);pSB=(CScrollBar*) GetDlgItem(IDC_SCR9); pSB->SetScrollRange(iiMm, iiMax);pSB=(CScrollBar*) GetDlgItem(IDC_SCRl0);pSB->SetScrollRange(iiMm, iiMax); pSB=(CScrollBar*) GetDlgItem(IDC_SCRG);pSB->SetScrollRange(iiMm, iiMax);for (iiit i=0;i<10;i++) bandpow[i]=0; m_PresentEf.SetCurSel(DEFAULT); return TRUE; // return TRUE unless you set the focus to a controlvoid CEQDlg:: OnSysConmiand(UINT 11ID, LPARAM IParam)if((nED & OxFFFO) == IDM.ABOUTBOX)CAboutDlg dlgAbout; dlgAbout.DoModal();elseCDialog: :OnSysConmiand(iiID, IParam);// If you add a ininunize button to youi dialog, you will need the code below // to draw tlie icon. For MFC applications using the document/view model, // this is automatically done for you by the framework・void CEQDlg::OiiPamtQif (IsIconicQ)fiCPauitDC dc(this); // device context for paintmgSendMessage(\WJCONERASEBKGND, (WPARAM) dc.GetSafeHdcQ, 0);// Center icon in client rectanglemt cxlcon = GetSysteniNIetrics(SM_CXICON);mt cylcon = GetSysteniNIetrics(SM_CYICON);CRect rect;GetClientRect(&rect);mt x = (rect.Width() - cxlcon +1)/2;mt v = (rect.HeightQ - cylcon +1)/2;// Draw the icondc.DiawIcon(x, y, mjilcon);} elseCDialog::OiiPaint();}}H The system calls this to obtam the cursor to display while the user drags// the minimized window.HCURSOR CEQDlg: :OnQueryDragIconQ{return (HCURSOR) mjilcon;}void CEQDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) {// TODO: Add youi message handler code here and/or call default int nTempl, nTemp2;nTempl=pSciollBai->GetSciollPosO;switch(nSBCode){case SB.THUMBPOSITION:pSciollBar->SetScrollPos(iiPos);break;case SE_LINELEFT: // 左按钮 nTemp2=(iiMax-iiMm) / 24; 〃划为 12 等份 if ((nTemp 1 -nTemp2)>iiMin){ nTemp 1 -=nTemp2; }else{nTemp} pSciollBai->SetScrollPos(nTempl); break;case SB.LINERIGHT: // 右箭头按钮nTemp2=(nMax-nMm)/24;if ((nTemp l+nTemp2)