いらないモノ、ひつようなモノ

書籍、音楽、そして若干のテクノロジー

 csoundで純正律、12平均律、53平均律を奏でてみる

純正律と12平均律等の事はぼんやりと知ってはいたが、あまり詳しく知らなかったのだが、アルペジエータを作ろうと思って少し学んだ。で、csoundでドレミを純正律、12平均律、53平均律で奏でるとどうなるのか試してみた。oscilではなく、oscil3を使ってできるだけ綺麗な正弦波にしようとした*1

;
; Title:Pure Temperament 12Equal temperament 53Equal temperament
; Date:2009/01/28
; Author: a9a9qq@gmail.com
;
;
<CsoundSynthesizer>
<CsOptions>
;-+msg_color=no -d -m0 -W  -+rtaudio=alsa -odac:hw:1 ; -odac:hw:1 ; pitch.wav
-+msg_color=no -d -m0 -W  -o pitch.wav
</CsOptions>
<CsInstruments>
sr     = 44100
kr     = 44100
ksmps  = 1
nchnls = 2

gitab   ftgen 1, 0,65536,10,1

instr 4
 irel=0.1
 p3=p3+irel
 itone = p5*p6/p7*powoftwo(p8/12)*powoftwo(p9/53)
 kenv linseg 0.1, 0.02, 1, p3*0.8-0.02, 0.8, p3*0.2, 0.001
 a1 oscil3 p4*kenv, itone, 1
 a2 oscil3 p4*kenv, itone, 1
 outs a1, a2
endin

</CsInstruments>
<CsScore>
;                  x/y z/12 w/53
;Pure Temperament
i4 0 1  13000 440  1 1  0    0
i4 + 1  13000 440  9 8  0    0
i4 + 1  13000 440  5 4  0    0
i4 + 1  13000 440  4 3  0    0
i4 + 1  13000 440  3 2  0    0
i4 + 1  13000 440  5 3  0    0
i4 + 1  13000 440 15 8  0    0
i4 + 1  13000 440  2 1  0    0

;12Equal temperament
i4 + 1  13000 440  1 1  0    0
i4 + 1  13000 440  1 1  2    0
i4 + 1  13000 440  1 1  4    0
i4 + 1  13000 440  1 1  5    0
i4 + 1  13000 440  1 1  7    0
i4 + 1  13000 440  1 1  9    0
i4 + 1  13000 440  1 1 11    0
i4 + 1  13000 440  1 1 12    0

;53Equal temperament
i4 + 1  13000 440  1 1  0    0 ; 1.0
i4 + 1  13000 440  1 1  0    9 ; 1.12
i4 + 1  13000 440  1 1  0   17 ; 1.25
i4 + 1  13000 440  1 1  0   22 ; 1.33
i4 + 1  13000 440  1 1  0   31 ; 1.50
i4 + 1  13000 440  1 1  0   39 ; 1.66
i4 + 1  13000 440  1 1  0   48 ; 1.875
i4 + 1  13000 440  1 1  0   53 ; 2.0
s

;Pure Temperament+53Equal temperament
i4 0 1  13000 440  1 1  0    0
i4 + 1  13000 440  9 8  0    0
i4 + 1  13000 440  5 4  0    0
i4 + 1  13000 440  4 3  0    0
i4 + 1  13000 440  3 2  0    0
i4 + 1  13000 440  5 3  0    0
i4 + 1  13000 440 15 8  0    0
i4 + 1  13000 440  2 1  0    0

i4 0 1  13000 440  1 1  0    0 ; 1.0
i4 + 1  13000 440  1 1  0    9 ; 1.12
i4 + 1  13000 440  1 1  0   17 ; 1.25
i4 + 1  13000 440  1 1  0   22 ; 1.33
i4 + 1  13000 440  1 1  0   31 ; 1.50
i4 + 1  13000 440  1 1  0   39 ; 1.66
i4 + 1  13000 440  1 1  0   48 ; 1.875
i4 + 1  13000 440  1 1  0   53 ; 2.0
s
;Pure Temperament+12Equal temperament
i4 0 1  13000 440  1 1  0    0
i4 + 1  13000 440  9 8  0    0
i4 + 1  13000 440  5 4  0    0
i4 + 1  13000 440  4 3  0    0
i4 + 1  13000 440  3 2  0    0
i4 + 1  13000 440  5 3  0    0
i4 + 1  13000 440 15 8  0    0
i4 + 1  13000 440  2 1  0    0

i4 0 1  13000 440  1 1  0    0
i4 + 1  13000 440  1 1  2    0
i4 + 1  13000 440  1 1  4    0
i4 + 1  13000 440  1 1  5    0
i4 + 1  13000 440  1 1  7    0
i4 + 1  13000 440  1 1  9    0
i4 + 1  13000 440  1 1 11    0
i4 + 1  13000 440  1 1 12    0
</CsScore>
</CsoundSynthesizer>

これを実行すると。純正律のドレミ、12平均律のドレミ、
53平均律のドレミ。次に純正律のドレミと53平均律のドレミを同時に鳴らす。
最後に純正律のドレミと12平均律のドレミを同時に鳴らす。

こんな風に聞こえる
同時に鳴らすとうなりが聞こえたりしてなる程、と思う。
で、数値的にはどうなのか気になったので、プログラムを作って計算してみた。

#include <stdio.h>
#include <math.h>
int main(int agrgc, char ** argv) {
  double i,t53[53],t12[12],j12[13];
  for (i=0.0; i<54; i++) {
    t53[(int)i]=pow(2, i/53.0);
    printf("i=%5lf 53=%5lf\n",i,t53[(int)i]);
  }
  for (i=0.0; i<12; i++) {
    t12[(int)i]=pow(2, i/12.0);
    printf("i=%5lf 12=%5lf\n",i,t12[(int)i]);
  }
  j12[0]=1.0;
  j12[1]=0;
  j12[2]=9.0/8.0;
  j12[3]=0;
  j12[4]=5.0/4.0;
  j12[5]=4.0/3.0;
  j12[6]=0;
  j12[7]=3.0/2.0;
  j12[8]=0;
  j12[9]=5.0/3.0;
  j12[10]=0;
  j12[11]=15.0/8.0;
  j12[12]=2.0;
  printf("   Pure Temperament|12Equal temperament|53Equal temperament\n");
  printf("C: 100                  %+1.4lf(%)               %+1.4lf(%)\n",
	 (j12[0]-t12[0])/j12[0]*100.0,(j12[0]-t53[0])/j12[0]*100.0);
  printf("D: 100                  %+1.4lf(%)               %+1.4lf(%)\n",
	 (j12[2]-t12[2])/j12[2]*100.0,(j12[2]-t53[9])/j12[2]*100.0);
  printf("E: 100                  %+1.4lf(%)               %+1.4lf(%)\n",
	 (j12[4]-t12[4])/j12[4]*100.0,(j12[4]-t53[17])/j12[4]*100.0);
  printf("F: 100                  %+1.4lf(%)               %+1.4lf(%)\n",
	 (j12[5]-t12[5])/j12[5]*100.0,(j12[5]-t53[22])/j12[5]*100.0);
  printf("G: 100                  %+1.4lf(%)               %+1.4lf(%)\n",
	 (j12[7]-t12[7])/j12[7]*100.0,(j12[7]-t53[31])/j12[7]*100.0);
  printf("A: 100                  %+1.4lf(%)               %+1.4lf(%)\n",
	 (j12[9]-t12[9])/j12[9]*100.0,(j12[9]-t53[39])/j12[9]*100.0);
  printf("B: 100                  %+1.4lf(%)               %+1.4lf(%)\n",
	 (j12[11]-t12[11])/j12[11]*100.0,(j12[11]-t53[48])/j12[11]*100.0);
}

コンパイルして実行する。出力結果をちょっと直すと以下のようになる。

   Pure Temperament|12Equal temperament|53Equal temperament
C: 100                  +0.0000(%)          +0.0000(%)
D: 100                  +0.2256(%)          +0.0079(%)
E: 100                  -0.7937(%)          +0.0813(%)
F: 100                  -0.1130(%)          -0.0039(%)
G: 100                  +0.1129(%)          +0.0039(%)
A: 100                  -0.9076(%)          +0.0774(%)
B: 100                  -0.6799(%)          +0.0852(%)

53平均律ってそれなりに純正律に近いことが分かる。ふーん。

*1:osciliの線形補間の方がよいのかどうかは疑問が残るが