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のように,色がマゼンタから白に変わっていくのが分かる.