Androidでシンプルなディレイ・エフェクト

この文章は前回と同様、Victor Lazzariniのブログを翻訳したものです。前回、マイクからの音をスピーカーで鳴らしました。今回はその間にエフェクトを挟んで音を変えます。
>>>それでは本文

原文 http://goo.gl/eK2hG


前回の私の記事で書いたコードだが、音声処理アプリケーションをどう書いたらいいかと感じている人もいるかも知れない。この点について、明らかにしていく。実際、再利用を念頭において、OpenSLモジュールを設計しておいた。だから、モジュールに触れることなく、君のプロジェクトにそのまま加えればいい。

前回のブログから、NDKプロジェクトの置き方について知ってるはずです。君はそれをコピーし、コードを修正し始める。opensl_example.cとopensl_example.hファイルを編集することだけすればいい。このファイルにいくつかの処理能力を追加していく。

くし形フィルタをベースにした、エコー効果を追加しよう。そのためにインフラを構築しよう。データ構造(データメンバ)とエコーを操作する関数(メソッド)を基礎にして、C言語の簡単なクラスを作る。以下のコードを、C言語のソースの一番上に加えます。

typedef struct delayline_t {
 float *delay; // delayline
 int size;     //  length  in samples
 int rp;       // read pointer
 float fdb;    // feedback amount
} DELAYLINE;

DELAYLINE *delayline_create(float delay, float fdb) {
 // allocate memory and set feedback parameter
 DELAYLINE *p = (DELAYLINE *)
                      calloc(sizeof(float), delay*SR);
 p->fdb = fdb > 0.f ? 
               (fdb < 1.f ? fdb : 0.99999999f) : 0.f ;
 return p;
}

void delayline_process(DELAYLINE *p,float *buffer,
                                           int size) {
 // process the delay, replacing the buffer
 float out, *delay = p->delay, fdb = p->fdb;
 int i, dsize = p->size, *rp = &(p->rp);
 for(i = 0; i < size; i++){
 out = delay[*rp];
 p->delay[(*rp)++] = buffer[i] + out*fdb;
 if(*rp == dsize) *rp = 0;
 buffer[i] = out;
 }
}

決まったところにこいつを置いて、やるべきことは、ディレイラインを使うためにメインプロセスを修正することだけ。メイン処理関数(start_processからmain_processにリネーム)に2つの引数を加えることで、Javaのコードからフィードバックとディレイタイムの量をセットできるようにする。

void main_process(float delay, float fdb) {
 OPENSL_STREAM *p;
 int samps, i;
 float buffer[VECSAMPS];
 DELAYLINE *d;
 p = android_OpenAudioDevice(SR,1,1,BUFFERFRAMES);
 if(p == NULL) return;
 d = delayline_create(delay, fdb);
 if(d == NULL) {
  android_CloseAudioDevice(p);
  return;
 }

 on = 1;
 while(on) {
   samps = android_AudioIn(p,buffer,VECSAMPS);
   delayline_process(d,buffer,samps);
   android_AudioOut(p,buffer,samps);
 }
 android_CloseAudioDevice(p);
}

もう、やり残しているのは2つだけで、opensl_example.hヘッダーファイルを編集し、start_process()をmain_process(float delay, float fdb)のプロトタイプで置き換える。

#ifdef __cplusplus
extern "C" {
#endif
 void main_process(float delay, float fdb);
 void stop_process();
#ifdef __cplusplus
};
#endif

そして、この新しい関数を呼ぶためにJavaコードを修正する。

t = new Thread() {
 public void run() {
   setPriority(Thread.MAX_PRIORITY);
   opensl_example.main_process(0.5f, 0.7f);
 }
};

これでいいだろう!。

>>>以上本文、以下修正など

(3/10修正メンバ)変数ー>データメンバ