補足2 パラメータを推定しましょう。
***
パラメータを推定しましょう。
***
このCDには、エピ4で見たように、全曲とも頻度が0となる振幅の値(-1 や 11 など)があります。
トラック2の最初の10秒を示しますね。横軸は時間で、縦軸は振幅です。
図で白いラインとなって見えている部分が頻度が0な振幅です。
頻度0となる振幅の値を書き出すと、...
..., -57, -46, -35, -23, -12, -1, 11, 22, 34, 45, 56, ...
です。その間隔は、...
..., 11, 11, 12, 11, 11, 12, 11, 12, 11, 11, ...
です。間隔は 11 か 12 ですが、何やらパターンがありそうです。デジタルな気配がします。
もっと広い範囲で頻度0の発生間隔を調べると、
...,
11,11,12, 11,11,12, 11,11,12,
11,12,
11,11,12, 11,11,12, 11,11,12, 11,11,12,
11,12,
11,11,12, 11,11,12, 11,11,12,
11,12,
11,11,12, 11,11,12, 11,11,12,
11,12,
...,
というパターンが見えてきます。11,11,12 の繰り返しの間に 11,12 が入るのですが、これにもパターンがありそう。
*
この頻度0のパターンは全曲で発生していることから、CD作製時のバグなのかもと思います。
CDのマスター音源を出力する際に全曲共通のレベル調整をしたのか。あるいは編集に利用した機器に固有の癖?なのかも。...、何があったのでしょうね。
*
頻度0が発生する原因はともかくとして、-2, -1, 0, +1, +2, ...と連続的に変化する波形なのに、-2, <>, 0, +1, +2, ...と消えてしまう値があるのは、振幅に乗数が掛かっているからだと思います。
ではその乗数とは? どんな値か気になりますよね。
気になることは調べないといけませんです。パラメータの推定をするのです!
***
乗数が掛かると頻度がどのように変化するのか簡単に見てみましょう。
s = range(64)
for p in [1.07, 1.08, 1.09, 1.10, 1.11, 1.12, 1.13]:
h = [int(k*p) for k in s]
z = [k for k in s if not k in h]
t = "".join(["0" if k in z else "." for k in s])
print "%0.2f : %s"%(p,t)
変数 s は振幅で 0〜63 です。とりあえずね。変数 p が今回のパラメータとなる乗数で、とりあえず 1.07〜1.13 にしました。そして振幅と乗数の積を変数 h として、そこにない値(=頻度0)を変数 z とします。
変数 t は、頻度0の値を "0"、その他は "." と変換した文字列です。
すると、
> 1.07 : ...............0..............0..............0...............0..
> 1.08 : .............0............0.............0............0..........
> 1.09 : ............0...........0...........0...........0...........0...
> 1.10 : ..........0..........0..........0..........0..........0.........
> 1.11 : ..........0.........0.........0.........0.........0.........0...
> 1.12 : .........0........0........0.........0........0........0........
> 1.13 : ........0........0........0.......0........0........0.......0...
変数 p によって、頻度0の発生間隔が変わって行きます。間隔が 11 や 12 になるのは 1.09〜1.10 ですか。
*
余談になりますが。
z = [k for k in s if not k in h]
とは、
z = []
for k in s:
if not k in h:
z += [k]
をまとめて1行にしたのです。1行だと分かり難いかも。慣れてくると1行にするのが楽しいのだけど。ほどほどにしないと、ですね。
***
ここから先は図で確認します。
横軸がパラメータ(変数 p)で、縦軸は振幅です。青色が発生間隔が 11 の振幅で、橙色が 12 です。
発生間隔 11 と 12 が混在するパラメータは 1.091〜1.100 の間ですね。
*
発生間隔のパターンによって、パラメータの範囲を調べます。調べるパターンは次の3種類です。
s1 = [ 11,11,12 ]
s2 = [ 11,11,12, 11,11,12 ]
s3 = [ 11,11,12, 11,11,12, 11,11,12 ]
横軸は変数 p で、縦軸は振幅です。...、以下、軸の範囲は違いますが横軸と縦軸は同じです。
パターン s1 から s2, s3 と順にパラメータの範囲が狭くなって、s3 では 1.0964〜1.0972 の間。段々とパラメータが絞られてきます。
*
次は、この3種類のパターンです。sA ∩ sB = sC です。
sA = [11,11,12, 11,11,12, 11,11,12, 11,12]
sB = [11,11,12, 11,11,12, 11,11,12, 11,11,12, 11,12]
sC = [11,11,12, 11,11,12, 11,11,12, 11,12,
11,11,12, 11,11,12, 11,11,12, 11,11,12, 11,12]
パターン s3 の開始部分に sA,sB,sC が発生していますね。ここを拡大しましょう。
パターン sC が発生するパラメータは 1.09649〜1.09659 の間。だいたい 1.0965 ですかね。
***
さて。
振幅は 16 ビットの符号付き整数なので、-32768 〜 +32767 の範囲なのですが。
振幅 -1 で頻度0が発生することから、-32768 〜 +32767 の値にそのまま乗数 1.0965 が掛かっているのでは無さそうです。だって、
print [int(i*1.0965) for i in range(-4,5)]
> [-4, -3, -2, -1, 0, 1, 2, 3, 4]
ですから。
想定できるのはオフセット +32768 を入れて振幅を 0〜65536 として処理していることです。あるいは小数点以下の切捨て処理で、0に近くなる方向ではなくて、値が小さくなる方向にするか。
うーん。切捨てではなくて四捨五入かもですけど。...。
***
乗数が 1.0965... だとしても、そもそも何故に乗数が掛かるのか。それが謎ですし。
これ以上の推定は難しいですね。考察が必要です。
***
間違いの指摘とか疑問とか、ご意見・ご感想とかありましたら、どうぞ感想欄に!
***
2025.8.11 微推敲。