<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            二次均衡器設計?

            相關文檔: 數字信號系統

            用Traits.UI和Chaco制作的二次均衡器的設計工具,用戶可以任意添加二次濾波器,并且調整其中心頻率、增益和Q值,并即時查看組合之后的最終頻率響應。

            _images/filter_equalizer_designer.png
            # -*- coding: utf-8 -*-
            import math
            from enthought.traits.api import Float, HasTraits, List, Array, on_trait_change, Instance, Range, Button
            from enthought.traits.ui.api import View, TableEditor, Item, Group, HGroup, VGroup, HSplit, ScrubberEditor, EnumEditor
            from enthought.traits.ui.table_column import ObjectColumn
            from enthought.chaco.api import Plot, AbstractPlotData, ArrayPlotData, VPlotContainer
            from enthought.chaco.tools.api import PanTool, ZoomTool 
            from enthought.enable.api import Component, ComponentEditor
            from enthought.pyface.api import FileDialog, OK
            import pickle
            import numpy as np
            
            SAMPLING_RATE = 44100.0 # 取樣頻率
            WORN = 1000 # 頻率響應曲線的點數
            
            # 對數圓頻率數組
            W = np.logspace(np.log10(10/SAMPLING_RATE*np.pi), np.log10(np.pi), WORN)
            
            # 對數頻率數組
            FREQS = W / 2 / np.pi * SAMPLING_RATE
            
            # 候選頻率
            EQ_FREQS = [20.0,25.2,31.7,40.0,50.4,63.5,80.0,100.8,
            	127.0,160.0,201.6,254.0,320.0,403.2,508.0,640.0,
            	806.3,1015.9,1280.0,1612.7,2031.9,2560.0,3225.4,
            	4063.7,	5120.0,	6450.8,	8127.5,	10240.0,12901.6,
            	16255.0,20480.0,]
            
            def scrubber(inc):
                '''創建不同增量的ScrubberEditor'''
                return ScrubberEditor(
                    hover_color  = 0xFFFFFF, 
                    active_color = 0xA0CD9E, 
                    border_color = 0x808080,
                    increment = inc
                )
            
            def myfreqz(b, a, w):
                '''計算濾波器在w個點的頻率響應'''
                zm1 = np.exp(-1j*w)
                h = np.polyval(b[::-1], zm1) / np.polyval(a[::-1], zm1)
                return h
            
            def design_equalizer(freq, Q, gain, Fs):
                '''設計二次均衡濾波器的系數'''
                A = 10**(gain/40.0)
                w0 = 2*math.pi*freq/Fs
                alpha = math.sin(w0) / 2 / Q
                
                b0 = 1 + alpha * A
                b1 = -2*math.cos(w0)
                b2 = 1 - alpha * A
                a0 = 1 + alpha / A
                a1 = -2*math.cos(w0)
                a2 = 1 - alpha / A
                
                return [b0/a0,b1/a0,b2/a0], [1.0, a1/a0, a2/a0]
            
            class Equalizer(HasTraits):
                freq = Range(10.0, SAMPLING_RATE/2, 1000)
                Q = Range(0.1, 10.0, 1.0)
                gain = Range(-24.0, 24.0, 0)
               
                a = List(Float, [1.0,0.0,0.0])
                b = List(Float, [1.0,0.0,0.0])
                
                h = Array(dtype=np.complex, transient = True)
            
                def __init__(self):
                    super(Equalizer, self).__init__()
                    self.design_parameter()
            
                @on_trait_change("freq,Q,gain")
                def design_parameter(self):
                    '''設計系數并計算頻率響應'''
                    try:
                        self.b, self.a = design_equalizer(self.freq, self.Q, self.gain, SAMPLING_RATE)
                    except:
                        self.b, self.a = [1.0,0.0,0.0], [1.0,0.0,0.0]
                    self.h = myfreqz(self.b, self.a, W) 
                    
                def export_parameters(self, f):
                    '''輸出濾波器系數為C語言數組'''
                    tmp = self.b[0], self.b[1], self.b[2], self.a[1], self.a[2], self.freq, self.Q, self.gain
                    f.write("{%s,%s,%s,%s,%s}, // %s,%s,%s\n" % tmp)
                    
            class Equalizers(HasTraits):
                eqs = List(Equalizer, [Equalizer()])
                h = Array(dtype=np.complex, transient = True)
                
                # Equalizer列表eqs的編輯器定義
                table_editor = TableEditor(
                    columns = [
                        ObjectColumn(name="freq", width=0.4, style="readonly"),
                        ObjectColumn(name="Q", width=0.3, style="readonly"),
                        ObjectColumn(name="gain", width=0.3, style="readonly"),
                    ],
                    deletable = True,
                    sortable = True,
                    auto_size = False,
                    show_toolbar = True,
                    edit_on_first_click = False,
                    orientation = 'vertical',
                    edit_view = View(
                        Group(
                            Item("freq", editor=EnumEditor(values=EQ_FREQS)),            
                            Item("freq", editor=scrubber(1.0)),
                            Item("Q", editor=scrubber(0.01)),
                            Item("gain", editor=scrubber(0.1)),
                            show_border=True,
                        ),
                        resizable = True
                    ),
                    row_factory = Equalizer
                )    
                
                view = View(
                    Item("eqs", show_label=False, editor=table_editor),
                    width     = 0.25,
                    height    = 0.5,        
                    resizable = True
                )
                
                @on_trait_change("eqs.h")
                def recalculate_h(self):
                    '''計算多組均衡器級聯時的頻率響應'''
                    try:
                        tmp = np.array([eq.h for eq in self.eqs if eq.h != None and len(eq.h) == len(W)])            
                        self.h = np.prod(tmp, axis=0)
                    except:
                        pass   
                        
                def export(self, path):
                    '''將均衡器的系數輸出為C語言文件'''
                    f = file(path, "w")
                    f.write("double EQ_PARS[][5] = {\n")
                    f.write("//b0,b1,b2,a0,a1 // frequency, Q, gain\n")
                    for eq in self.eqs:
                        eq.export_parameters(f)
                    f.write("};\n")
                    f.close()
                
            class EqualizerDesigner(HasTraits):
                '''均衡器設計器的主界面'''
                
                equalizers = Instance(Equalizers)
                
                # 保存繪圖數據的對象
                plot_data = Instance(AbstractPlotData)    
            
                # 繪制波形圖的容器
                container = Instance(Component)    
                
                plot_gain = Instance(Component)
                plot_phase = Instance(Component)   
                save_button = Button("Save")
                load_button = Button("Load")
                export_button = Button("Export")
                   
                view = View(
                    VGroup(
                        HGroup(
                            Item("load_button"),            
                            Item("save_button"),
                            Item("export_button"),
                            show_labels = False
                        ),
                        HSplit(
                            VGroup(
                                Item("equalizers", style="custom", show_label=False),
                                show_border=True,
                            ),
                            Item("container", editor=ComponentEditor(size=(800, 300)), show_label=False),
                        )
                    ),
                    resizable = True,
                    width = 800,
                    height = 500,
                    title = u"Equalizer Designer"
                )
                
                def _create_plot(self, data, name, type="line"):
                    p = Plot(self.plot_data)
                    p.plot(data, name=name, title=name, type=type)
                    p.tools.append(PanTool(p))
                    zoom = ZoomTool(component=p, tool_mode="box", always_on=False)
                    p.overlays.append(zoom)        
                    p.title = name
                    p.index_scale = "log"
                    return p    
                
                def __init__(self):
                    super(EqualizerDesigner, self).__init__()
                    self.plot_data = ArrayPlotData(f=FREQS, gain=[], phase=[])
                    self.plot_gain = self._create_plot(("f", "gain"), "Gain(dB)")
                    self.plot_phase = self._create_plot(("f", "phase"), "Phase(degree)")
                    self.container = VPlotContainer()
                    self.container.add( self.plot_phase )                
                    self.container.add( self.plot_gain )
                    self.plot_gain.padding_bottom = 20
                    self.plot_phase.padding_top = 20
                
                def _equalizers_default(self):
                    return Equalizers()
                    
                @on_trait_change("equalizers.h")
                def redraw(self):
                    gain = 20*np.log10(np.abs(self.equalizers.h)) 
                    phase = np.angle(self.equalizers.h, deg=1)
                    self.plot_data.set_data("gain", gain)
                    self.plot_data.set_data("phase", phase)
                    
                def _save_button_fired(self):
                    dialog = FileDialog(action="save as", wildcard='EQ files (*.eq)|*.eq')
                    result = dialog.open()
                    if result == OK:
                        f = file(dialog.path, "wb")
                        pickle.dump( self.equalizers , f)
                        f.close()
                    
                def _load_button_fired(self):
                    dialog = FileDialog(action="open", wildcard='EQ files (*.eq)|*.eq')
                    result = dialog.open()
                    if result == OK:
                        f = file(dialog.path, "rb")
                        self.equalizers = pickle.load(f)
                        f.close()
                        
                def _export_button_fired(self):
                    dialog = FileDialog(action="save as", wildcard='c files (*.c)|*.c')
                    result = dialog.open()
                    if result == OK:
                        self.equalizers.export(dialog.path)
                        
            win = EqualizerDesigner()
            win.configure_traits()
            

            上一篇文章

            FFT卷積的速度比較

            下一篇文章

            單擺擺動周期的計算

            <span id="7ztzv"></span>
            <sub id="7ztzv"></sub>

            <span id="7ztzv"></span><form id="7ztzv"></form>

            <span id="7ztzv"></span>

                  <address id="7ztzv"></address>

                      亚洲欧美在线