2013/09/28

Audacity built-in effectsを作ってみる

Windows版Audacityを使っていたときは、built-in effects の開発はマイクロソフトのVC++をコンパイル時に使うこと意味していたので、手を出す気にもなれなかった。でも最近になってUbuntu系に移行したので、ようやくチャレンジしてみようと思いはじめる。

Linux版Audacityで利用できるエフェクト開発としてはNyquistやLadspaなどがあるが、パラメータの自由度や設定ファイルの保存など問題があり、どうも好きになれない。そこでAudacityに組み込んでしまうbuilt-in effectsの出番というわけ。標準のエフェクトを見る限り、設定ファイルも保存できるし、かなりの自由度があるように思える。

作るにあたって、わかりやすいドキュメントが見当たらなかったので、既存エフェクトのソースを参考に作ってみる。いろいろ謎の定義があり、それらを理解するにはかなりの量のソースを読まないとダメそうだが、とりあえず理解した範囲でも簡単なエフェクトは実現できた。ビルドすれば下のようにちゃんと表示され利用できるようになった。

下は独自のfade-in/outを適用したもの。標準のfade-in/outが直線で減衰するので自然な減衰にしてみた。内部的にはHanning窓関数を利用している。AudacityにはNyquistのAdjustable Fadeもあって、これと似たようなカーブを描けるのだが、ダイアログが出てくるので操作が面倒。個人的に使用頻度が高いfade-in/outは、ささっと適用したいので作ってみたというわけ。式はこんな感じ。ぶっちゃけcosカーブの半周期分。
buffer[i]*(0.5+0.5*cos(i*M_PI/len));

エフェクトを作るために新たに必要なファイルは2つ。例えばこんなかんじ。
NamagiFade.h
NamagiFade.cpp
エフェクトはEffectやEffectSimpleMonoなどを継承して作るようだ。ヘッダファイルにクラスを宣言して、ソースファイルにあらかじめあるメソッドに対して、overrideで具体的な処理を書いていくという流れ。音声信号はfloatでやり取りされている。ソースはC++。

コンパイルするためには
audacity-src-2.0.4/src/effects/LoadEffects.cpp
audacity-src-2.0.4/src/Makefile.in
audacity-src-2.0.4/src/Makefile
に新しいエフェクトを書き加える必要がある。

ターミナルからmakeすることで新しいエフェクトを加えたAudacityが作られる。makeは変更のあったファイルだけ新規にオブジェクトを作るので、一度全体をmakeしてしまえば、その後は数分でビルドできる。 そして sudo make install すればインストールされる。今後は、ぼちぼちと過去に作ったエフェクトを移植してみようかと思う。その前にC++を勉強しないと。あとダイアログに必要なwxWidgetsも。

フェードインアウトのソースコード
/* NamagiFade.h */
#ifndef __AUDACITY_EFFECT_FADE_OUT__
#define __AUDACITY_EFFECT_FADE_OUT__
#include "SimpleMono.h"

class EffectNamagiFadeIn:public EffectSimpleMono{

 public:
   virtual wxString GetEffectName(){
      return wxString(_("Namagi Fade In"));
   }
   virtual wxString GetEffectIdentifier(){
      return wxString(wxT("Namagi Fade In"));
   }
   virtual wxString GetEffectAction(){
      return wxString(_("Namagi Fading In..."));
   }

 protected:
   virtual bool ProcessSimpleMono(float *buffer,
                                  sampleCount len);
};


class EffectNamagiFadeOut:public EffectSimpleMono{

 public:
   virtual wxString GetEffectName(){
      return wxString(_("Namagi Fade Out"));}
   virtual wxString GetEffectIdentifier()
      {return wxString(wxT("Namagi Fade Out"));}
   virtual wxString GetEffectAction(){
      return wxString(_("Namagi Fading Out..."));}

 protected:
   virtual bool ProcessSimpleMono(float *buffer,
                                   sampleCount len);
};
#endif

code
/* NamagiFade.cpp */
#include "NamagiFade.h"
#include <math.h>

bool EffectNamagiFadeIn::ProcessSimpleMono(float *buffer,
                                         sampleCount len){
   for (sampleCount i = 0; i < len; i++){
      buffer[i] =
        (float)(buffer[i]*(0.5+0.5*cos((float)((i*M_PI)) /
        (float)(len)+M_PI)));
   }
   return true;
}

bool EffectNamagiFadeOut::ProcessSimpleMono(float *buffer,
                                         sampleCount len){
   for (sampleCount i = 0; i < len; i++){
      buffer[i] =
        (float)(buffer[i]*(0.5+0.5*cos((float)((i*M_PI)) /
        (float)(len))));
   }
   return true;
}


Audacity 関係の記事