class doremi{ // 周波数hzの音をsec秒分出力する. // 開始時の位相をパラメータradで渡して,終了時の位相を返す static double sinWave(double rad,double hz,double sec){ int i; for(i=0;i< sec*44100;i++){ System.out.println(10000*Math.sin(rad)); rad=rad+2*Math.PI*hz/44100; } return rad; } // ドレミの歌 public static void main(String[] args){ double rad=0.0; // http://www.digion.com/dspark/waza/vol4/5.htm // 各音の周波数 double DO=261.6; // 小文字にすると予約語doと重なる double RE=293.6; double MI=329.6; double FA=349.2; rad=sinWave(rad,DO,0.75); // ドの音を0.75秒 rad=sinWave(rad,RE,0.25); // レの音を0.25秒 rad=sinWave(rad,MI,0.75); rad=sinWave(rad,DO,0.25); rad=sinWave(rad,MI,0.5); rad=sinWave(rad,DO,0.5); rad=sinWave(rad,MI,1.0); rad=sinWave(rad,RE,0.75); rad=sinWave(rad,MI,0.25); rad=sinWave(rad,FA,0.5); rad=sinWave(rad,MI,0.25); rad=sinWave(rad,RE,0.25); rad=sinWave(rad,FA,1.0); } }
class t1{ // 周波数hzの音をsec秒分出力する. // 開始時の位相をパラメータradで渡して,終了時の位相を返す static double sinWave(double rad,double hz,double sec){ int i; for(i=0;i< sec*44100;i++){ System.out.println(10000*Math.sin(rad)); rad=rad+2*Math.PI*hz/44100; } return rad; } // 周波数hz1, 周波数hz2の和音をsec秒分出力する. // 開始時の位相をパラメータradで渡して,終了時の位相を返す static double sinWave2(double rad1,double hz1,double hz2, double sec){ int i; double rad2=0.0; for(i=0;i< sec*44100;i++){ System.out.println(10000*(Math.sin(rad1)+Math.sin(rad2))); rad1=rad1+2*Math.PI*hz1/44100; rad2=rad2+2*Math.PI*hz2/44100; } return rad1; } public static void main(String[] args){ double rad=0.0; // http://www.digion.com/dspark/waza/vol4/5.htm // 各音の周波数 double DO=261.6; // 小文字にすると予約語doと重なる double RE=293.6; double MI=329.6; double FA=349.2; rad=sinWave2(rad,DO,MI,1); rad=sinWave2(rad,DO,FA,1); rad=sinWave(rad,RE,1); rad=sinWave2(rad,DO,MI,1); rad=sinWave2(rad,DO,FA,1); } }
前回のマンデルブロー集合の例でやってみる.以下の プログラムは「赤い」部分 以外は前回のプログラムと一緒(クラス名は違う)である.
class MandelAnimation{ // 実数を引数(パラメタ)に持つメソッド mandel の定義 static int mandel(double x, double y){ double zr=0, zi=0,new_zr; int i; for(i=0;i<50;i=i+1){ if(zr*zr+zi*zi>4.0) { // |Zi|>2.0 の時は発散と判断 return i; } // 複素数の計算 // (zr+zi*i)*(zr+zi*i)+x+y*i=(zr*zr-zi*zi+x)+(2*zr*zi+y)*i new_zr=zr*zr-zi*zi+x; zi=2*zr*zi+y; zr=new_zr; } return 50; } public static void main(String[] args){ int width=256, height=256; int frame=Integer.parseInt(args[0]); System.out.println("P3"); System.out.println(width); System.out.println(height); System.out.println(255); int i,j,count; double x, y; for(i=0;i< height;i=i+1){ for(j=0;j< width;j=j+1){ // -1.7 <= x < 0.7, -1.2 <= y < 1.2の範囲で計算 // 整数(int)から実数(double)への変換は「(double)整数式」 // のようにおこなう. x= -1.7+2.4*((double)j/(double)width)+0.1*frame; // (1) y= -1.2+2.4*((double)i/(double)height); // (2) // 0 <= r <= 50の値が返る count=mandel(x,y); int r,g,b; // r=50の時に黒(0,0,0), r=0の時にほぼ白(250,250,250)とする. r=250-count*5; // g=250-count*5; // (4) b=250-count*5; // r=Math.min(255,Math.max(0,r)); // R の範囲を0から255までに g=Math.min(255,Math.max(0,g)); // G の範囲を0から255までに b=Math.min(255,Math.max(0,b)); // B の範囲を0から255までに System.out.println(r); // R System.out.println(g); // G System.out.println(b); // B } } } }これをMandelAnimation.javaという名前で保存する.
javac MandelAnimation.javaとして,コンパイルして,
java MandelAnimation 0 > mandel0.ppm java MandelAnimation 1 > mandel1.ppm .... java MandelAnimation 9 > mandel9.ppmと実行する.なお,このような繰り返しは,
for i in 0 1 2 3 4 5 6 7 8 9; do java MandelAnimation $i > mandel$i.ppm; doneのように書くこともできる(28.8シェルスクリプト参照).この後で,
convert -loop 5 -delay 15 mandel0.ppm mandel1.ppm mandel2.ppm mandel3.ppm mandel4.ppm mandel5.ppm mandel6.ppm mandel7.ppm mandel8.ppm mandel9.ppm mandelanimation.gifを実行すると, mandelanimation.gifができる.ワイルドカードを使って,
convert -loop 5 -delay 15 mandel*.ppm mandelanimation.gifとしてもよいが,2桁以上の数字の場合は,こうすると,
mandel0.ppm mandel1.ppm mandel10.ppm mandel11.ppm .. mandel19.ppm mandel2.ppm ...のような順に並んでしまうので,
convert -loop 5 -delay 15 mandel[0-9].ppm mandel[1-9][0-9].ppm mandelanimation.gifのようにすると良い.
変更部分の簡単な説明をおこなう.java コマンド実行時のパラメータ( 12.3 パラメータ 参照) がmainメソッドのargsに文字列配列( 26.1.6.5配列登場 )として 渡されてくるので,Integer.parseInt (26.1.8.14 文字列から値へ(2)) を使って数値に変換する.
x= -0.5+2.4*((double)(j-width/2)/(double)width)*(1.0-frame*0.07); y= 0.0+2.4*((double)(i-height/2)/(double)height)*(1.0-frame*0.07);のようにすると, mandelanimation1.gifのように,どんど ん拡大していくアニメーションが作れる.
また,それに加えて(4)の行を
g=250-count*5; // (4)から,
g=(int)((250-count*5)*frame/9.0); // (4)のように変更すると,mandelanimation2.gifのように,色がマゼンタから白に変わっていくのが分かる.