Androidでノイズとローパスフィルタなど

風邪引きまして少し手抜きで。前回はオシレータを4つ作りまして今回はフィルタとノイズです。

ノイズ行きます。

    class Noise extends Snd{
    	public double amp;
    	public Noise(double a){
    		amp = a;
    	}
    	public double updata(){
    		return (2*Math.random() - 1) * amp;
    	}
    }

randomが0から1までで、それを2倍して1を引けば-1から1までのランダムを生成できます。

さあフィルタです。

説明
・ローパスフィルタは高い周波数のサウンドを遮断します、ローをパスするわけですから。
・ハイパスフィルタは低い周波数のサウンドを遮断する。
・バンドパスは指定した周波数付近のサウンドだけを通過させます。
実装
・ローパスは単純に言うと今現在の音波の1点と1つ前に通過した1点を足し算する。
・ハイパスはその引き算
・バンドパスは上2つを融合したものと考えればいいでしょう。

本当は前の音波の1点と今の点をどのような割合で足すとかあるわけですが、これらは先人がどういう割合がいいかなど研究されていますので、以下のサイトを参考にします。
http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
http://www.geidai.ac.jp/~marui/matlab/node8.html

ローパスフィルタですが、それらが継承するクラスを作ります。

    class Filter extends Snd{
    	public double b0 = 0;
    	public double b1 = 0;
    	public double b2 = 0;
    	public double a0 = 0;
    	public double a1 = 0;
    	public double a2 = 0;
    	
    	public Snd input;
    	public double cf;
    	public double q;
    	public Snd addcf = new Snd();
    	public Snd addq = new Snd();
    	
    	public double forder = 0;
    	public double sorder = 0;
    	public Filter(Snd ii, double cc, double qq){
    		input = ii;
    		cf = cc;
    		q = qq;
    	}
    	public Filter(Snd ii, double cc, double qq, Snd ac){
    		input = ii;
    		cf = cc;
    		q = qq;
    		addcf = ac;
    	}
    	public Filter(Snd ii, double cc, double qq, Snd ac, Snd aq){
    		input = ii;
    		cf = cc;
    		q = qq;
    		addcf = ac;
    		addq = aq;
    	}
    	public void connect(Snd n){
    		input = n;
    	}   	
    }

b0からa2の変数ですがこれは前の音波の1点と今の1点の割合になるものです。cfはカットオフ周波数で、その周波数付近から例えばローパスなら高い周波数を遮断します。qが高くなると共振します。分かりづらいかもしれないのでsynth tvを見てください。cfのdddスライダーでqはeeeです。雰囲気つかめますかね。 addcfやaddqはここでモジュレーションです。1つ前の音波の1点がforderでもう1つ前のsorderとなります。今と以前だけじゃなくもう一つ前も計算するということです。複雑です。

    class LowPass extends Filter{
    	//improve (http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt)
    	public LowPass(Snd ii, double cc, double qq){
    		super(ii, cc, qq);
    	}
    	public LowPass(Snd ii, double cc, double qq, Snd ac){
    		super(ii, cc, qq, ac);
    	}
    	public LowPass(Snd ii, double cc, double qq, Snd ac, Snd aq){
    		super(ii, cc, qq, ac, aq);
    	}
    	public void calc(){
    		double omega = 2 * Math.PI * (cf + addcf.updata()) / sampleRate;
    		double alpha = Math.sin(omega) / (2 * (q + addq.updata()));
    		double cs = Math.cos(omega);
    		b0 = (1 - cs) / 2;
    		b1 = 1 -cs;
    		b2 = (1 - cs) / 2;
    		a0 = 1 + alpha;
    		a1 = -2 * cs;
    		a2 = 1 - alpha;
    	}
    	public double updata(){
    		calc();
    		double temp = (b0/a0)*input.updata() + 
                          (b1/a0)*forder +
                          (b2/a0)*sorder -
                          (a1/a0)*forder -
                          (a2/a0)*sorder;
    		sorder = forder;
    		forder = temp;
    		return temp;
    	}
    }
    class HighPass extends Filter{
    	//improve (http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt)
    	public HighPass(Snd ii, double cc, double qq){
    		super(ii, cc, qq);
    	}
    	public HighPass(Snd ii, double cc, double qq, Snd ac){
    		super(ii, cc, qq, ac);
    	}
    	public HighPass(Snd ii, double cc, double qq, Snd ac, Snd aq){
    		super(ii, cc, qq, ac, aq);
    	}
    	public void calc(){
    		double omega = 2 * Math.PI * (cf + addcf.updata()) / sampleRate;
    		double alpha = Math.sin(omega) / (2 * (q + addq.updata()));
    		double cs = Math.cos(omega);
    		b0 = (1 + cs) / 2;
    		b1 = -(1 + cs);
    		b2 = (1 + cs) / 2;
    		a0 = 1 + alpha;
    		a1 = -2 * cs;
    		a2 = 1 - alpha;
    	}
    	public double updata(){
    		calc();
    		double temp = (b0/a0)*input.updata() + 
                          (b1/a0)*forder +
                          (b2/a0)*sorder -
                          (a1/a0)*forder -
                          (a2/a0)*sorder;
    		sorder = forder;
    		forder = temp;
    		return temp;
    	}
    }
    class BandPass extends Filter{
    	//improve (http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt)
    	public BandPass(Snd ii, double cc, double qq){
    		super(ii, cc, qq);
    	}
    	public BandPass(Snd ii, double cc, double qq, Snd ac){
    		super(ii, cc, qq, ac);
    	}
    	public BandPass(Snd ii, double cc, double qq, Snd ac, Snd aq){
    		super(ii, cc, qq, ac, aq);
    	}
    	public void calc(){
    		double omega = 2 * Math.PI * (cf + addcf.updata()) / sampleRate;
    		double alpha = Math.sin(omega) * Math.sinh(Math.log(2) / 2 *(q + addq.updata()) * omega / Math.sin(omega));
    		double cs = Math.cos(omega);
    		b0 = alpha;
    		b1 = 0;
    		b2 = -alpha;
    		a0 = 1 + alpha;
    		a1 = -2 * cs;
    		a2 = 1 - alpha;
    	}
    	public double updata(){
    		calc();
    		double temp = (b0/a0)*input.updata() + 
                          (b1/a0)*forder +
                          (b2/a0)*sorder -
                          (a1/a0)*forder -
                          (a2/a0)*sorder;
    		sorder = forder;
    		forder = temp;
    		return temp;
    	}
    }

、、、、。ぐ、具合が悪くなってきたのでこの辺で逃げます。コードとにらめっこしてください。
エンベロープ、オシレータ、フィルタと作ったので次は安いシンセぐらいはいけそうです。