ã¿ãªããããã«ã¡ã¯ïŒ CïŒã§ã®VSTã·ã³ã»ãµã€ã¶ãŒã®äœæã«é¢ããèšäºã®ç¬¬3éšãèªãã§ããŸãã åã®ããŒãã§ã¯ã VSTãã©ã°ã€ã³ãäœæããããã®SDKãšã©ã€ãã©ãªãæ€èšããä¿¡å·æ¯å¹
ãå¶åŸ¡ããããã®ãªã·ã¬ãŒã¿ãŒãšADSRãšã³ãããŒãã®ããã°ã©ãã³ã°ãæ€èšããŸããã
ãã®ããŒãã§ã¯ãã·ã³ã»ãµã€ã¶ãŒãã§ããªãåšæ³¢æ°ãã£ã«ã¿ãŒã®èšç®ãšã³ãŒãã£ã³ã°ã®æ¹æ³ã説æããŸãã ãŸããã€ã³ã©ã€ã¶ãŒããªããã°ããµãŠã³ãåŠçã¯èããããŸããã
ãœãŒã¹ã³ãŒããšã NAudioã©ã€ãã©ãªïŒ.NETã®ãµãŠã³ããæäœããããã®ã©ã€ãã©ãªïŒã®ã€ã³ã©ã€ã¶ãŒã®äœ¿çšã«ã€ããŠæ€èšããŸãã
泚æ-å€ãã®ãã¿ã³ããããŸã -ãã£ã«ã¿ãŒä¿æ°ã®åŒãèšç®ããŸãã
ç§ã®ã·ã³ã»ãµã€ã¶ãŒã®ãœãŒã¹ã³ãŒãã¯GitHubã§å
¥æã§ããŸã ã
VSTã€ã³ã©ã€ã¶ãŒãã©ã°ã€ã³Fab Filter Pro Qã®ã¹ã¯ãªãŒã³ã·ã§ãã
èšäºã®ãµã€ã¯ã«
- CïŒWPFã§VSTiã·ã³ã»ãµã€ã¶ãŒãçè§£ããŠèšè¿°ããŸã
- ADSRä¿¡å·ãšã³ãããŒã
- ãã¿ã¯ãŒã¹åšæ³¢æ°ãã£ã«ã¿ãŒ
- é
å»¶ãæªã¿ãããã³ãã©ã¡ãŒã¿ãŒå€èª¿
ç®æ¬¡
- ã€ã³ã©ã€ã¶ãŒ
- ããŒãªãšå€æãã£ã«ã¿ãªã³ã°
- ããžã¿ã«ãã£ã«ã¿ãŒ
- ãã¿ãŒã¯ãŒã¹ãã£ã«ã¿ãŒã䜿çšããçç±
- LFãã£ã«ã¿ãŒåŒåºå
- ãã€ãã¹ãã£ã«ã¿ãŒãšãã³ããã¹ãã£ã«ã¿ãŒã®åŒã®å°åº
- åŸãããåŒã«åŸã£ããã¿ã¯ãŒã¹ãã£ã«ã¿ãŒããã°ã©ãã³ã°
- NAudio Libraryã®ãã³ãã€ã³ã©ã€ã¶ãŒ
- ãã£ã«ã¿ãŒãèšç®ããããã®ããã°ã©ã
- åç
§è³æ
ã€ã³ã©ã€ã¶ãŒ
å€ãã®å ŽåããµãŠã³ããåŠçãããšãã¯ããã®ãã£ã©ã¯ã¿ãŒ/è²/é³è²ã倿ŽããŸãã é³ãããäœé³ã«ããããé«åšæ³¢æ°ãåé€ãããããã®éãè¡ã£ããããŠãé³ããéæãã«ããŠãäžå€®ãšäžéšã®ã¿ãæ®ããŸãã ãµãŠã³ãåŠçã«æºãã£ãŠããªã人ã®å€ãã¯ã ã€ã³ã©ã€ã¶ãŒãäœã§ããããç¥ã£ãŠãããšç¢ºä¿¡ããŠããŸããã¹ããŒã«ãŒããã¥ãŒãžãã¯ã»ã³ã¿ãŒãããŒãã¬ã³ãŒããŒããã¬ãŒã€ãŒãªã©ããããŸãã ã€ã³ã©ã€ã¶ãŒã¯ãã£ã«ã¿ãŒã®ã»ããã§ããããããéžæããåšæ³¢æ°åž¯åã®ä¿¡å·ã®æ¯å¹
ã倿ŽããŸãã å®¶åºçšã¹ããŒã«ãŒã§ã¯ãããã¯éåžž2ã3åã®ããã§ããäœåšæ³¢æ°ãäžé³ãäžé³ãåºå®åšæ³¢æ°åž¯åã§ãã
Winampã€ã³ã©ã€ã¶ãŒã«ã¯10åã®å®çŸ©æžã¿ãã³ããæ¢ã«ãããŸãã
Winamp Equalizerã¹ã¯ãªãŒã³ã·ã§ãã
ãµãŠã³ãåŠçã®äžçã§ã¯ãããããå³ãšè²ã«å¯Ÿå¿ããå€ãã®ã€ã³ã©ã€ã¶ãŒãã©ã°ã€ã³ããããŸãã Fab Filter Pro Qãã©ã°ã€ã³ïŒèšäºã®åé ã®ã¹ã¯ãªãŒã³ã·ã§ããïŒã¯ã倿°ã®ãã³ããäœæããŠãã©ã¡ãŒã¿ãŒãç·šéã§ããã°ã©ãã£ãã¯ã€ã³ã©ã€ã¶ãŒã§ãã
ã€ã³ã©ã€ã¶ãŒã®å垯åã¯ãå®éã«ã¯åšæ³¢æ°ãã£ã«ã¿ãŒã§ãã åšæ³¢æ°ãã£ã«ã¿ãŒã¯ãä¿¡å·ã®é³è²/åšæ³¢æ°å¿çã倿ŽããŸãã ãšã¬ã¯ãããã¯ã¹ã§ã¯ãå€ãã®çš®é¡ãšãã£ã«ã¿ãŒã®åé¡ãããã察å¿ããç¹æ§ãšãã©ã¡ãŒã¿ãŒããããŸã- ãŠã£ãããã£ã¢ãèŠãŠãã ãã ã
æãåçŽãªãã£ã«ã¿ãŒã§ããããŒãã¹ããã€ãã¹ããã³ããã¹ãã£ã«ã¿ãŒãæ€èšããããã°ã©ã ããŸãã
ããŒãªãšå€æãã£ã«ã¿ãªã³ã°
çè«çã«ã¯ãä¿¡å·ã䜿çšããŠé¢æ£ããŒãªãšå€æãè¡ããåšæ³¢æ°ãåŠçããŠããé倿ãè¡ãããšãæ°ã«ãã人ã¯ããŸããã
DFTã®å®è£
ã«ã€ããŠèããªãå Žåã¯ããã®ã¢ãããŒããéåžžã«çŽæçã§ç°¡åã«ããã°ã©ãã³ã°ã§ãããšæããŸãïŒããã§ããDFTãäœããã®çš®é¡ã®ãã®ããèªåã§ã³ãŒãã£ã³ã°ããªãå ŽåïŒã
ã¢ãããŒãã®çæ-æåã«ãDFTã¯ããµã€ãºã2ã®ã¹ãä¹ã§ãããµã³ãã«ã®é
åããå
¥åãåãåããŸãã ããã¯ãåºåä¿¡å·ããã§ã«é
å»¶ããŠããããšãæå³ããŸãã æ¬¡ã«ã512çªç®ã®ãµã³ãã«ããšã«ãDFTãä¿¡å·åšæ³¢æ°åŠçãéDFTãšããã¢ã«ãŽãªãºã ãäœæããŸãã ãããã¯å°ããªèšç®ã§ã¯ãããŸããã 第äžã«ãããžã¿ã«ä¿¡å·åŠçã®æ¯æè
ãç¥ã£ãŠããããŸã çæãšåŸ®åŠãããããŸãã
DFTã®äœ¿çšã¯èæ
®ããŸããããããžã¿ã«ãã£ã«ã¿ãŒã®çè«ãèŠãŠã¿ãŸãããã ãµã³ãã«å€ãåŠçããå
¥åãµã³ãã«é
åã®é·ãã«å¿ããŠç·åœ¢èšç®ã®è€éããæã€ãã£ã«ã¿ãŒãäœæããŸãããã
ããžã¿ã«ãã£ã«ã¿ãŒ
ç§ã¯æ¬ã®ããžã¿ã«ä¿¡å·åŠçïŒå®çšçãªã¢ãããŒãããã»ãšãã©ã®æ
å ±ãšåŒã®æŽŸçç©ãåããŸãã-ç§ã¯ããã匷ããå§ãããŸããããã¯ãã·ã¢èªçã§ãã- ããžã¿ã«ä¿¡å·åŠçã§ãã å®çšçãªã¢ãããŒã ãèå³ã®ããæ¹ã¯ãŠã§ãäžã§PDFãèŠã€ããã§ãããã
éèŠãªãã€ã³ããè¿°ã¹ããã ãã£ã«ã¿ãŒã®æ§ç¯ãšèšç®ã®ãããã¯ã¯æ¬åœã«éåžžã«è€éã§ãå€ãã®åŸ®åŠããšãã¥ã¢ã³ã¹ãå«ãŸããŠãããçè«ã®ç¥èãšçè§£ãå¿
èŠã§ãã ãã®èšäºã§ã¯ãèªè
ããããã®åŒã®ç±æ¥ãçè§£ã§ããããã«ããã¿ãŒã¯ãŒã¹ãã£ã«ã¿ãŒã®åŒãèšç®ããæ¹æ³ã瀺ããŸãã ãããããªããã®ãããªåæã®åŒããªãæ£ç¢ºã«ãã®ãããªçœ®æãå¿
èŠãªã®ãã¯ãããžã¿ã«ä¿¡å·åŠçã®æ·±å±€çè«ã«çªå
¥ããããšã«ãã£ãŠã®ã¿çè§£ã§ããŸãã
ãã£ã«ã¿ãŒã³ãŒããã°ãŒã°ã«ã§èª¿ã¹å§ãããšããããã«çè§£ã§ããªãæ°åŠçã³ãŒããããããèŠã€ããã®ã§ããã®ãããªèšç®åŒãã©ãããæ¥ãã®ããå°ãªããšãå°ãç¥ããããšæããŸããã ãªã·ã¬ãŒã¿ãŒããšã³ãããŒããé
å»¶-ãããã®ã³ã³ããŒãã³ãã®åäœãå人çã«çè§£ããŠããã°ã©ãã³ã°ããããšã¯ãç§ã«ã¯çŽæçã§ããããã£ã«ã¿ãŒã§ã¯ãããŸããã ãã®èšäºã§ã¯ãããžã¿ã«ä¿¡å·åŠçãžã®é¢å¿ãåèµ·ãããã§ãïŒãã®ãããã¯ãããå®å
šã«çè§£ããããšãã顿ãããã°å¬ããã§ãã
ç³ã¿èŸŒã¿ ã ãã£ã«ã¿ãŒã®ã€ã³ãã«ã¹å¿çããã£ã«ã¿ãŒã® äŒé颿°ãªã©ã®çšèªãïŒå°ãªããšãå°ãïŒç¥ãå¿
èŠããããŸã ã
çæ³çãªãã£ã«ã¿ãŒã®åšæ³¢æ°å¿çã®è¿äŒŒïŒãœããšãã®æç§æžã®åçããœãŒã¹ãèŠã€ãããŸããã§ããïŒ
ãã£ã«ã¿ãŒã¯ä¿¡å·ã倿Žããéžæãããåšæ³¢æ°ããé€å»ãããŸãã æ¢åã®ãã£ã«ã¿ãŒã¯å®å
šã§ã¯ãããŸããã 垯åå¹
-ãã£ã«ã¿ãŒãã圱é¿ããªããåšæ³¢æ°ã®åž¯åïŒäžéšãããŸã
倿Žã¯ãäžå®å
šãªãã£ã«ã¿ãŒã®æ©èœã§ãïŒã æå¶åž¯å-äžèŠãªåšæ³¢æ°ã®åž¯åã é·ç§»åž¯åã§ã¯ãåšæ³¢æ°ã®äœäžãçºçããŸãã åœç¶ããã£ã«ã¿ãŒã¯ãéé垯åã®æªã¿ãã©ãã ãå°ãããæå¶åž¯åã®åšæ³¢æ°ãã©ãã ãæå¶ããé·ç§»åž¯åãã©ãã ãçããã«ãã£ãŠããçæ³çãªããã£ã«ã¿ãŒã«è¿ããªããŸãã ãã£ã«ã¿ãŒã«ã¯ããŸããŸãªãè¿äŒŒãããããŸã-ãã§ãã·ã§ãããã¿ãŒããããã£ã«ã¿ãŒãªã©-æ¬ããããã¯ãŒã¯ã®ãªãŒãã³ã¹ããŒã¹ã«ãããŸãã
ãã¿ãŒã¯ãŒã¹ãã£ã«ã¿ãŒã䜿çšããçç±
ãã¹ãŠãéåžžã«åçŽã§ããã¿ã¯ãŒã¹ãã£ã«ã¿ãŒã®åšæ³¢æ°å¿çã¯éé垯ååšæ³¢æ°ã§å¯èœãªéãæ»ããã§ã-ç§èŠãæãéèŠãªããšã¯ãéé垯åã®ä¿¡å·ãæãªãããšã§ã¯ãããŸããã
ç°ãªã次æ°ã®ãã¿ãŒã¯ãŒã¹ããŒãã¹ãã£ã«ã¿ãŒã®å¯Ÿæ°åšæ³¢æ°å¿çïŒãŠã£ãããã£ã¢ããã®ã¹ã¯ãªãŒã³ã·ã§ããïŒ
så¹³é¢äžã®ãã¿ãŒã¯ãŒã¹ãã£ã«ã¿ãŒã®äŒé颿°ã¯ã次ã®åŒã§èšè¿°ãããŸãã
å¶æ°nãš
奿°n
ããã§ãnã¯ãã£ã«ã¿ãŒã®æ¬¡æ°ã§ããã«ãããªãåšæ³¢æ°wã§ã®æ¯å¹
ã¯-3n dBã§ãããæ¯å¹
åšæ³¢æ°å¿çã¯ãªã¯ã¿ãŒãããšã«-6n dBæžè¡°ããŸãã
ããã¿èŸŒã¿ä¿æ°ãååŸããã«ã¯ã次ã®åœ¢åŒã§zå¹³é¢ã®äŒé颿°ãååŸããå¿
èŠããããŸãã
2次ãã£ã«ã¿ãŒã®äŒé颿°ïŒãªã¯ã¿ãŒãããã-6 dBã®æžè¡°ïŒãèŠã€ããHïŒsïŒn = 2ã®åŒã«ä»£å
¥ããŸãã
次ã«ããã£ã«ã¿ãŒã®ç³ã¿èŸŒã¿ã¯æ¬¡ã®ããã«ãªããŸãã
ã«ãããªãåšæ³¢æ°wïŒä¿¡å·æ¯å¹
ã-3 dBã«ãªãïŒãšFcã«ãµã³ããªã³ã°åšæ³¢æ°ïŒ1ç§ãããã®ãµã³ãã«æ°ïŒããã«ãåäœã§äžããŠã¿ãŸãããã
åŒã§ã¯ã鿣èŠååšæ³¢æ°ã䜿çšããå¿
èŠããããŸãã 眮ãæããè¡ããŸãïŒãã³ããã¹ãã£ã«ã¿ãŒã«ã¯ãéé垯åãæ±ºå®ãã2ã€ã®åšæ³¢æ°w1ãšw2ããããŸãïŒã
ããŒãã¹ãã£ã«ã¿ãŒãèšç®ããå Žåã¯ã倿ãè¡ãå¿
èŠããããŸããäŒé颿°ã®ãã©ã¡ãŒã¿ãŒsã眮ãæããŸãã
ä»ã®ã¿ã€ãã®ãã£ã«ã¿ãŒïŒãã€ãã¹ããã³ããã¹ããããïŒãèšç®ããã«ã¯ãä»ã®çœ®æãè¡ãå¿
èŠããããŸãã ãããã¯ã ããžã¿ã«ä¿¡å·åŠçã®æ¬ã§è°è«ãããŠããŸãã ããŒã8.8.2以éã®èšäºã®å®çšçãªã¢ãããŒã ã
次ã«ãzãã¬ãŒã³ã«ç§»åããã«ã¯ã倿Žãè¡ããŸãã
åæèšç®ã«ã¯ãMathematicaããã±ãŒãžã䜿çšããŸããã
zã®å€é
åŒã®åœ¢ã§ååãšåæ¯ãååŸããå¿
èŠããããŸãã 忝HïŒzïŒã®é
ãå
±éåæ¯ã«æžãããŸãã ãããè¡ãã«ã¯ã忝é
ã®æå€§å
¬çŽæ°ïŒGCDïŒãèŠã€ããå
ã®é¢æ°HïŒzïŒã®ååãšåæ¯ãããã«åå²ããŸãã
CoefficientList颿°ã䜿çšããŠãçµæã®å€é
åŒã®ã¹ãä¹ã§ä¿æ°ãèŠã€ããŸãã
ãã¹ãŠãæ£çŽã«è¡ãããå Žåãæ¡ä»¶ã«ãããa0ã¯1ã«çãããªããŸã-ãã¹ãŠã®ä¿æ°ãa0ã§é€ç®ããŸãïŒã³ãŒãã£ã³ã°ã§ã¯ãé€ç®ããã«åã®åŒã䜿çšããŸãïŒã
ãã€ãã¹ãã£ã«ã¿ãŒã®åŒã®å°åºã¯ã倿ãç°ãªãããŒãã¹ãã£ã«ã¿ãŒã«äŒŒãŠããŸãã
ãã³ããã¹ãã£ã«ã¿ãŒã®åŒãå°åºããããã«ã倿ãé©çšãããŸãã
眮æãè¡ããšãHïŒzïŒã®ååãšåæ¯ã®å€é
åŒã®æ¬¡æ°ã2åã«ãªãããïŒçœ®æã«ã¯s ^ 2ããããŸãïŒããã£ã«ã¿ãŒã®æ¬¡æ°ã¯2åã«ãªããŸãã ãããã£ãŠãæåã¯n = 1ã«å¯ŸããŠé¢æ°HïŒsïŒã䜿çšããŸãã
ãã£ã«ã¿ãŒã«ã¯ããã£ã«ã¿ãŒã¿ã€ãïŒããŒãã¹ããã€ãã¹ããã³ããã¹ïŒãšã«ãããªãåšæ³¢æ°wã®2ã€ã®ãã©ã¡ãŒã¿ãŒããããŸãã ãã³ããã¹ãã£ã«ã¿ãŒã§ã¯ãã«ãããªãåšæ³¢æ°ãéé垯åã®äžå€®ã®åšæ³¢æ°ãšèŠãªããŸãã éé垯åã¯ãåšæ³¢æ°éé[w-w / 4ãw + w / 4]ãšããŠå®çŸ©ãããŸãïŒããã§ãããè€éã§è«ççãªå¯Ÿæ°ã®æ³åãèªç±ã«éžæã§ããŸãïŒã
èšç®ãããåŒã䜿çšããŠãä¿æ°b0ãb1ãb2ãa1ãa2ïŒæ¡ä»¶ã«ãã£ãŠa0ã¯1ã«çããïŒã決å®ãããšããŸãã ãã£ã«ã¿ãŒæäœã¢ã«ãŽãªãºã ã¯ç³ã¿èŸŒã¿ã«çž®å°ããããµã³ãã«ããšã«é çªã«å®è¡ãããŸãã
yïŒnïŒã¯ãèšç®ãããæ°ãããµã³ãã«å€ã§ãã xïŒnïŒã¯ãµã³ãã«ã®çŸåšã®å€ãyïŒn-1ïŒãšyïŒn-2ïŒã¯åã®2ã€ã®èšç®ããããµã³ãã«ãxïŒn-1ïŒãšxïŒn-2ïŒã¯ãµã³ãã«ã®åã®å
¥åå€ã§ãã
以åã®ãµã³ãã«ã®èšæ¶ãæŽçããå¿
èŠããããŸãã 埪ç°ãããã¡ãŒã§ã¯è³¢ããªããåçŽã§æç¢ºã«ããïŒ3ã€ã®èŠçŽ ã®2ã€ã®é
åã æ°ããå€ããã®é
åã«ãããã·ã¥ããããã³ã«ããµã³ãã«ã®å€ãå€ãé çªã«ã³ããŒããŸãã
åçŽãªã¯ã©ã¹ãååŸããŸãã
class BiquadConvolutionTable { public double B0, B1, B2, A1, A2; private readonly double[] _x = new double[3]; private readonly double[] _y = new double[3]; public double Process(double s) {
ãã£ã«ã¿ãŒã®ã¯ã€ã€ãŒãã¬ãŒã ã¯ã©ã¹ãèšè¿°ããŸãããïŒ æåã®èšäºã®ã·ã³ã»ãµã€ã¶ãŒã¢ãŒããã¯ãã£ãåç
§ ïŒã BiquadConvolutionTableã¯ã©ã¹ã¯ãåäžã®ä¿¡å·ã§åäœããŸãã 1ã€ã®ãã£ãã«ã§-ã¢ãã©ã«ã ãããã£ãŠãå·Šå³ã®ãã£ãã«çšã«2ã€ã®BiquadConvolutionTableãå¿
èŠã§ãã
ãã£ã«ã¿ãŒãæ£ããé©çšããã«ã¯ãçä¿¡ã·ãŒã±ã³ã¹ã®ãã¹ãŠã®ãµã³ãã«ã«BiquadConvolutionTable.Process颿°ãé£ç¶ããŠé©çšããçµæã®ãµã³ãã«é
åã«å
¥åããå¿
èŠããããŸãã
BiquadConvolutionTableã®ä¿æ°ã®èšç®ã¯ã颿°CalculateCoefficientsã«ãã£ãŠå®è¡ãããŸãã
public enum EFilterPass { None, LowPass, HiPass, BandPass } public class ButterworthFilter : SyntageAudioProcessorComponentWithParameters<AudioProcessor>, IProcessor { private readonly BiquadConvolutionTable _tablel; private readonly BiquadConvolutionTable _tabler; public EnumParameter<EFilterPass> FilterType { get; private set; } public FrequencyParameter CutoffFrequency { get; private set; } public ButterworthFilter(AudioProcessor audioProcessor) : base(audioProcessor) { _tablel = new BiquadConvolutionTable(); _tabler = new BiquadConvolutionTable(); } public override IEnumerable<Parameter> CreateParameters(string parameterPrefix) { FilterType = new EnumParameter<EFilterPass>(parameterPrefix + "Pass", "Filter Type", "Filter", false); CutoffFrequency = new FrequencyParameter(parameterPrefix + "Cutoff", "Filter Cutoff Frequency", "Cutoff"); return new List<Parameter> {FilterType, CutoffFrequency}; } public void Process(IAudioStream stream) { if (FilterType.Value == EFilterPass.None) return; var count = Processor.CurrentStreamLenght; var lc = stream.Channels[0]; var rc = stream.Channels[1]; for (int i = 0; i < count; ++i) { var cutoff = CutoffFrequency.Value; CalculateCoefficients(cutoff); var ls = _tablel.Process(lc.Samples[i]); lc.Samples[i] = ls; var rs = _tabler.Process(rc.Samples[i]); rc.Samples[i] = rs; } } private void CalculateCoefficients(double cutoff) { ... } }
颿°CalculateCoefficientsã¯ã«ãŒãå
ã§æ¯ååŒã³åºãããŸã-ãªãã§ããïŒ æ¬¡ã®èšäºã§ã¯ããã©ã¡ãŒã¿ãŒã®å€èª¿ïŒæéã®å€åïŒã«ã€ããŠèª¬æããŸãããããã£ãŠãã«ãããªãåšæ³¢æ°ãå€åããå¯èœæ§ããããŸããã€ãŸããä¿æ°ãåèšç®ããå¿
èŠããããŸãã ãã¡ãããæ¥ãã§ãã«ãããªãåšæ³¢æ°ã®å€åã«ãµãã¹ã¯ã©ã€ãããããã»ããµã«æ¢ã«ããä¿æ°ãèšç®ããå¿
èŠããããŸãã ãããããããã®èšäºã§ã¯æé©åãæ±ããŸãããç®æšã¯ãã£ã«ã¿ãŒãã³ãŒãã£ã³ã°ããããšã§ãã
ä¿æ°ã®èšç®åŒã«åŸã£ãŠé¢æ°CalculateCoefficientsãã³ãŒãã£ã³ã°ããŸãã
鿣èŠåãããåšæ³¢æ°ã䜿çšããå¿
èŠãããããšãæãåºããŠãã ããã 亀æïŒ
ä¿æ°b0ãb1ãb2ãa0ãa1ãa2ã®ãã¹ãŠã®åŒãæžãçããŸãã èšç®åŸãa0ã1ã«ãªãããã«ãã¹ãŠã®ä¿æ°ãa0ã§é€ç®ããå¿
èŠããããŸãã
private double TransformFrequency(double w) { return Math.Tan(Math.PI * w / Processor.SampleRate); } private void CalculateCoefficients(double cutoff) { double b0, b1, b2, a0, a1, a2; switch (FilterType.Value) { case EFilterPass.LowPass: { var w = TransformFrequency(cutoff); a0 = 1 + Math.Sqrt(2) * w + w * w; a1 = -2 + 2 * w * w; a2 = 1 - Math.Sqrt(2) * w + w * w; b0 = w * w; b1 = 2 * w * w; b2 = w * w; } break; case EFilterPass.HiPass: { var w = TransformFrequency(cutoff); a0 = 1 + Math.Sqrt(2) * w + w * w; a1 = -2 + 2 * w * w; a2 = 1 - Math.Sqrt(2) * w + w * w; b0 = 1; b1 = -2; b2 = 1; } break; case EFilterPass.BandPass: { var w = cutoff; var d = w / 4;
å®å
šãªButterworthFilterã¯ã©ã¹ã³ãŒã public enum EFilterPass { None, LowPass, HiPass, BandPass } public class ButterworthFilter : SyntageAudioProcessorComponentWithParameters<AudioProcessor>, IProcessor { private class BiquadConvolutionTable { public double B0, B1, B2, A1, A2; private readonly double[] _x = new double[3]; private readonly double[] _y = new double[3]; public double Process(double s) { // "" _x[2] = _x[1]; _x[1] = _x[0]; _x[0] = s; _y[2] = _y[1]; _y[1] = _y[0]; // _y[0] = B0 * _x[0] + B1 * _x[1] + B2 * _x[2] - A1 * _y[1] - A2 * _y[2]; return _y[0]; } } private readonly BiquadConvolutionTable _tablel; private readonly BiquadConvolutionTable _tabler; public EnumParameter<EFilterPass> FilterType { get; private set; } public FrequencyParameter CutoffFrequency { get; private set; } public ButterworthFilter(AudioProcessor audioProcessor) : base(audioProcessor) { _tablel = new BiquadConvolutionTable(); _tabler = new BiquadConvolutionTable(); } public override IEnumerable<Parameter> CreateParameters(string parameterPrefix) { FilterType = new EnumParameter<EFilterPass>(parameterPrefix + "Pass", "Filter Type", "Filter", false); CutoffFrequency = new FrequencyParameter(parameterPrefix + "Cutoff", "Filter Cutoff Frequency", "Cutoff"); return new List<Parameter> {FilterType, CutoffFrequency}; } public void Process(IAudioStream stream) { if (FilterType.Value == EFilterPass.None) return; var count = Processor.CurrentStreamLenght; var lc = stream.Channels[0]; var rc = stream.Channels[1]; for (int i = 0; i < count; ++i) { var cutoff = CutoffFrequency.Value; CalculateCoefficients(cutoff); var ls = _tablel.Process(lc.Samples[i]); lc.Samples[i] = ls; var rs = _tabler.Process(rc.Samples[i]); rc.Samples[i] = rs; } } private double TransformFrequency(double w) { return Math.Tan(Math.PI * w / Processor.SampleRate); } private void CalculateCoefficients(double cutoff) { double b0, b1, b2, a0, a1, a2; switch (FilterType.Value) { case EFilterPass.LowPass: { var w = TransformFrequency(cutoff); a0 = 1 + Math.Sqrt(2) * w + w * w; a1 = -2 + 2 * w * w; a2 = 1 - Math.Sqrt(2) * w + w * w; b0 = w * w; b1 = 2 * w * w; b2 = w * w; } break; case EFilterPass.HiPass: { var w = TransformFrequency(cutoff); a0 = 1 + Math.Sqrt(2) * w + w * w; a1 = -2 + 2 * w * w; a2 = 1 - Math.Sqrt(2) * w + w * w; b0 = 1; b1 = -2; b2 = 1; } break; case EFilterPass.BandPass: { var w = cutoff; var d = w / 4; // [w * 3 / 4, w * 5 / 4] var w1 = Math.Max(w - d, CutoffFrequency.Min); var w2 = Math.Min(w + d, CutoffFrequency.Max); w1 = TransformFrequency(w1); w2 = TransformFrequency(w2); var w0Sqr = w2 * w1; // w0^2 var wd = w2 - w1; // W a0 = -1 - wd - w0Sqr; a1 = 2 - 2 * w0Sqr; a2 = -1 + wd - w0Sqr; b0 = -wd; b1 = 0; b2 = wd; } break; default: throw new ArgumentOutOfRangeException(); } _tablel.B0 = _tabler.B0 = b0 / a0; _tablel.B1 = _tabler.B1 = b1 / a0; _tablel.B2 = _tabler.B2 = b2 / a0; _tablel.A1 = _tabler.A1 = a1 / a0; _tablel.A2 = _tabler.A2 = a2 / a0; } }
NAudio Libraryã®ãã³ãã€ã³ã©ã€ã¶ãŒ
ãµãŠã³ãã.NETã®ããŸããŸãªåœ¢åŒã®ãµãŠã³ããã¡ã€ã«ãæäœããããã®åªããNAudioã©ã€ãã©ãªããããŸãã
ããã«ã¯ããã£ã«ã¿ãªã³ã°ã ç³ã¿èŸŒã¿ ã ã²ãŒã ã ãšã³ãããŒã ã FFTãªã©ã®è峿·±ãæ©èœãåããNAudio.Dspåå空éãå«ãŸããŠããŸãã
Equalizerã¯ã©ã¹ïŒäŸã®NAudioWpfDemo.EqualizationDemoåå空éããïŒãèããŠãã ãããããã«ãããä¿¡å·ãã€ã³ã©ã€ãºã§ããŸãã ãã®ã¯ã©ã¹ã¯ISampleProviderãå®è£
ããŸããISampleProviderã¯ãèªã¿åã颿°ïŒfloat []ãããã¡ãŒãintãªãã»ãããintã«ãŠã³ãïŒã§ãããã¡ãŒãµã³ãã«ã®é
åãåŠçïŒå€æŽïŒããŸãã
ã³ã³ã¹ãã©ã¯ã¿ãŒã¯ãã€ã³ã©ã€ã¶ãŒã®ããã³ãããèšè¿°ããEqualizerBandæ§é äœã®é
åãåãå
¥ããŸãã
class EqualizerBand { public float Frequency { get; set; } public float Gain { get; set; } public float Bandwidth { get; set; } }
ããã§ãFrequencyã¯ãQãã©ã¡ãŒã¿ãŒïŒåž¯åå¹
ã ãã£ã«ã¿ãŒåè³ªä¿æ° ïŒãã²ã€ã³Gain dBãæã€åž¯åã®äžå¿åšæ³¢æ°ã§ãã
å®è£
ãèŠããšãEqualizerBandã®åãã³ãã¯ãããŒãã³ã°ãã£ã«ã¿ãŒãšããŠäœ¿çšãããBiQuadFilterã¯ã©ã¹ã«å¯Ÿå¿ããŠããŸãã ãã¹ãŠã®ãã£ã«ã¿ãŒã¯ãé£ç¶ããŠäœ¿çšãããä¿¡å·ã倿ŽããŸãã
EqualizerBandã¯ã©ã¹ã¯ãã¿ãŒã¯ãŒã¹ãã£ã«ã¿ãŒã®å®è£
ã§ããããã£ã«ã¿ãŒã¿ã€ããšãã©ã¡ãŒã¿ãŒã®éžæè¢ãè±å¯ã§ãã å®è£
ãèŠããšãåæ§ã®åŒãšä¿æ°ãèŠãããšãã§ããŸãã
Equalizerã¯ã©ã¹ã®äœ¿çšäŸã¯ãEqualizationDemoViewModelã¯ã©ã¹ã®NAudioWpfDemoãããžã§ã¯ãã«ãããŸãã
ãã£ã«ã¿ãŒãèšç®ããããã®ããã°ã©ã
ããžã¿ã«ãã£ã«ã¿ãŒã®å
é§è
ã¯ã¢ããã°ãã£ã«ã¿ãŒã§ããã ã¢ããã°åè·¯ãšã¢ããã°ä¿¡å·åŠçã®çè«ã¯ãåŸã«ããžã¿ã«ä¿¡å·åŠçã®çè«ã«æé·ããŸããã
èæ
®ããããã¿ã¯ãŒã¹ãã£ã«ã¿ãŒãšä¿æ°ã®èšç®åŒã«ã€ããŠã¯ãã¢ããã°åè·¯ãçµã¿ç«ãŠãããšãã§ããŸãã
åè·¯ããããã®èŠçŽ ã®ãã©ã¡ãŒã¿ãŒãããŸããŸãªãã£ã«ã¿ãŒã®ç³ã¿èŸŒã¿ä¿æ°ãèšç®ããã³æ§ç¯ããããã®å€ãã®ããã°ã©ã ããããŸãã
ããã£ã«ã¿ãŒèšç®ãœãããŠã§ã¢ãã§ã°ãŒã°ã«æ€çŽ¢ã§ããŸãã
ã¢ã€ãªã¯ãã«ãºãœãããŠã§ã¢RFãã£ã«ã¿ãŒãã¶ã€ããŒ
次ã®èšäºã§ã¯ããã©ã¡ãŒã¿ã®é
å»¶ ã æªã¿ ãå€èª¿ã®å¹æã«ã€ããŠèª¬æããŸãã
ãã¹ãŠã«è¯ãïŒ ããã°ã©ãã³ã°ã§é 匵ã£ãŠãã ããïŒ
åç
§è³æ
以åã®èšäºã®èšäºãšæ¬ã®ãªã¹ããå¿ããã«èŠãŠãã ããã
- ããžã¿ã«ä¿¡å·åŠçïŒå®çšçãªã¢ãããŒã ã ãã·ã¢èªç- ããžã¿ã«ä¿¡å·åŠçã å®çšçãªã¢ãããŒã ã
- Habrã®èšäºãããŒãªãšå€æã«é¢ããç°¡åãªèšèã§ã
- Wikiã®ãã¿ãŒã¯ãŒã¹ãã£ã«ã¿ãŒ
- ãã¿ãŒã¯ãŒã¹ãã£ã«ã¿ãŒèšç®ã³ãŒãã䜿çšããGithubãªããžããª
- 颿£ä¿¡å·ãšã·ã¹ãã ã第7ç« ãFIRããã³IIRãã£ã«ã¿ãŒ
- ããŒãã¹ãã£ã«ã¿ãŒã¯ããã°ã©ã ã§ã©ã®ããã«æ©èœããŸããïŒ ïŒdsp.stackexchange.com/ïŒ
- ããžã¿ã«ãã¿ãŒã¯ãŒã¹ãã£ã«ã¿ãŒãšãã§ãã·ã§ããã£ã«ã¿ãŒã®èšèš
- ãªãŒãã£ãªEQã¯ãã¯ããã¯
- ã¢ã€ãªã¯ãã«ãºãœãããŠã§ã¢-ããžã¿ã«ããã³ã¢ããã°ãã£ã«ã¿ãŒ