作曲において偶然性という概念はモーツアルトのダイスによる作曲法から、コイントスまで様々な方法が試みられてきましたがコンピュータの出現以降、偶然性は乱数という形でいっそう積極的に作曲家達にもてはやされてきました。このページでは様々な乱数の生成法、利用法などを解説します。
様々な乱数
ダイスやコイントスとコンピュータアルゴリズムによる決定的な違いは何でしょう。無作為にデータを得られるという特徴は同じです。例えば、野球の試合を想像してみましょう。チームは強いチームもあれば弱いチームもあり、勝率も異なります。我々は弱いチームと強いチームの勝負の予想をするとき、強いチームが勝つ確率と弱いチームが勝つ確率を共に1/2とは考えません。当然強いチームのほうが勝つ確率が高いと予想するでしょう。過去の勝負からどちらが強いか推測が出来るからです。ダイスやコイントスを使ってもこのような予測は立てることはできません。出現確率に重みを付けることができるのがコンピュータによるアルゴリズムとダイス、コインの違いなのです。
乱数の生成には以下のアルゴリズムが有効です。これはコンパイルしmxjオブジェクトから読み込むことでmax/mspで利用可能です。max/mspのパッチングだけでは面倒なアルゴリズムはjavaやjavascriptを積極的に利用することをおすすめします。
一様乱数
一様乱数は全ての値の出現頻度が同等の乱数で、いわばホワイトノイズと同じような現象です。
import com.cycling74.max.*; import java.util.Random; public class uniRandom extends MaxObject { long seed = Long.MAX_VALUE; Random r = new Random(); public uniRandom(Atom[] args) { declareAttribute("seed", null, "setSeed"); } public void setSeed(int i) { seed = (long)i; r.setSeed(seed); } public void bang() { outlet(0,r.nextFloat()); outlet(1,r.nextFloat()); } }
dowonload
線形分布
y=axもしくはy=-ax+1のグラフのように直線的に出現頻度が分布した乱数です。
import com.cycling74.max.*; import java.util.Random; public class linRandom extends MaxObject { float r_1; float r_2; float rand; long seed = Long.MAX_VALUE; Random r = new Random(); public linRandom(Atom[] args) { declareAttribute("seed", null, "setSeed"); } public void bang() { r_1 = r.nextFloat(); r_2 = r.nextFloat(); if(r_1 < r_2){ rand = r_1; } else{ rand = r_2; } outlet(0,rand); } }
指数分布
指数関数的な分布を持つ乱数です。
import com.cycling74.max.*; import java.util.Random; public class expRandom extends MaxObject { float x; float rand; float y; float lambda=0.5f; long seed = Long.MAX_VALUE; Random r = new Random(); public expRandom(Atom[] args) { declareAttribute("seed", null, "setSeed"); declareAttribute("lambda"); } public void setSeed(int i) { seed = (long)i; r.setSeed(seed); } public void bang() { x = r.nextFloat(); rand = (float)Math.log(x)/lambda*-1; outlet(0,rand); } }
三角分布
中心付近になるほど出現頻度が増す乱数のアルゴリズムです。
import com.cycling74.max.*; import java.util.Random; public class convexRandom extends MaxObject { float r_1; float r_2; float rand; long seed = Long.MAX_VALUE; Random r = new Random(); public convexRandom(Atom[] args) { declareAttribute("seed", null, "setSeed"); } public void setSeed(int i) { seed = (long)i; r.setSeed(seed); } public void bang() { r_1 = r.nextFloat(); r_2 = r.nextFloat(); rand=(float)0.5*(r_1+r_2); outlet(0,rand); } }
正規分布
正規分布、ガウス分布の乱数を生成するアルゴリズムです。平均のmeanと分散のstdという属性付きのフロートナンバーを送ることで分布をリアルタイムに変化させることが可能です。
import com.cycling74.max.*; import java.util.Random; public class gaussRandom extends MaxObject { float mean = 0.0f; float std = 0.5f; long seed = Long.MAX_VALUE; Random r = new Random(); public gaussRandom(Atom[] args) { declareAttribute("mean"); declareAttribute("std"); declareAttribute("seed", null, "setSeed"); } public void setSeed(int i) { seed = (long)i; r.setSeed(seed); } public void bang() { outlet(0, mean + std * (float)r.nextGaussian()); } }
weibullRandom分布
weibullRandom分布に基づいた乱数生成アルゴリズムです。sとtの変数を変化させることで劇的に分布を変化させることが可能です。
import com.cycling74.max.*; import java.util.Random; public class weibullRandom extends MaxObject { float u; float a; float tinv; float s = 0.3f; float t = 3f; float rand; long seed = Long.MAX_VALUE; Random r = new Random(); public weibullRandom(Atom[] args) { declareAttribute("seed", null, "setSeed"); declareAttribute("t"); declareAttribute("s"); } public void bang() { tinv = t/1; do{ u = r.nextFloat(); }while(u == 0 | u == 1); a = 1/(1-u); rand = s*(float)Math.pow((float)Math.log(a),tinv); outlet(0,rand); } }
Beta分布
Beta分布の生成アルゴリズムです。a,bの変数で分布をコントロールすることが可能です。
import com.cycling74.max.*; import java.util.Random; public class betaRandom extends MaxObject { float u1; float u2; float y1; float y2; float sum; float ainv; float binv; float a = 0.2f; float b = 0.3f; float rand; long seed = Long.MAX_VALUE; Random r = new Random(); public betaRandom(Atom[] args) { declareAttribute("seed", null, "setSeed"); declareAttribute("a"); declareAttribute("b"); } public void bang() { ainv=1/a; binv=1/b; do{ do{ u1 = r.nextFloat(); }while(u1 == 0); do{ u2 = r.nextFloat(); }while(u2 == 0); y1=(float)Math.pow(u1,ainv); y2=(float)Math.pow(u2,binv); sum=y1+y2; } while(sum > 1); rand = y1/sum; outlet(0,rand); } }
Cauchy分布
コーシー分布の生成アルゴリズムです。alphaの値で分布の形をコントロール可能です。
import com.cycling74.max.*; import java.util.Random; public class cauchyRandom extends MaxObject { float u; float pi = 3.1415927f; float alpha = 0.5f; float rand; long seed = Long.MAX_VALUE; Random r = new Random(); public cauchyRandom(Atom[] args) { declareAttribute("seed", null, "setSeed"); declareAttribute("alpha"); } public void bang() { u = r.nextFloat(); u=u*pi; rand = alpha*(float)Math.tan(u); outlet(0,rand); } }