
図1.夏によく合う涼しげなカオス
カオス現象について取り上げたのは2022年の記事で、あれからもう3年経ってしまった。
事の発端は、当時タモリ倶楽部で取り上げられた早稲田大学の「役に立たない機械コンテスト」に出品された、二重振り子を応用したメトロノームで、リズムがしっちゃかめっちゃかで実に役に立たなそうだったが、二重振り子はカオス現象を紹介するためによく使われる。
2022年当時、私はこのカオス現象を電子回路で再現させて、カオスの音を聴いてみたいと思ってあれこれ実験した。2つの発振回路が、相互に周波数を変更するような作用を行うように構成すれば再現できるのではないか……?そう思い何通りか実験してみたがどうにもういまく行かなかった。たいていは発振状態が安定してしまい、カオスと呼べる状態にはならなかったのだった。
そこでネットで、電子回路でカオス現象を再現する方法がないか調べてみたところ、chua回路なるものを発見した。これは1983年にchuaさんという技術者によって発明された回路だそうだ。さっそくLTSPICEでシミュレーションし、実際に回路も組み立てて検証したところ、カオス波形が得られた。カオス波形は、X信号とY信号のリサージュ波形として得られるものだった。
このカオス波形の音を聴いてみたいと思ったが、当時はXYのリサージュをうまいこと音声信号に変換する方法を思いつかず、苦肉の策でX+Y信号、X-Y信号の2種類を生成して聴いてみたが、ホワイトノイズのようにしかならず、結果として面白みに欠けるものだった。リサージュということなら位相差を演算すればいいのではないか?というところまでは考えたのだが、結局そこまではやらなかった。これらはすべて2022年の記事に記している。
ところで先日、トランジスタ技術の最新号を読んでいたら、アナログ乗算器を使った位相差演算回路の製作記事が載っていた。これを読んでいて、カオス信号の音声化がうまくいっていなかったことを思い出した。この位相差演算回路を使えば、カオス信号をもう少しそれらしく音声信号化できるのではないか……?
しかし記事ではアナログ乗算器というICを使っていて、経験のない分野なのでたとえばこれがLTSPICEでシミュレーションできるのか?など、わからない点も多く、またしても棚上げにしそうになったが、よく考えてみれば回路で実現するよりも、すべてプログラムでやってみた方が早く、しかもいろんな検証ができるのではないかと思い、pythonを使って検証してみることにした。
まずはpythonでchua回路のシミュレーションを考える。chua回路は次の微分方程式で与えられる。

ただし、α、βは回路部品(抵抗、コンデンサ、インダクタ)に依存する定数、m0,m1は非線形素子の特性を決める定数。
pythonを使って、この微分方程式を数値的に解いてプロットしたグラフが、冒頭図1のカオスのグラフだ。実際にpythonで、この微分方程式を定義して、それを解く部分は次のとおり。(プログラムの全体は記事の下の方でリンクします。)
###Pythonコード抜粋
# Chua回路の微分方程式
def chua_circuit(t, state, alpha, beta, m0, m1):
x, y, z = state
# 非線形関数 h(x)
h = m1 * x + 0.5 * (m0 - m1) * (abs(x + 1) - abs(x - 1))
dxdt = alpha * (y - x - h)
dydt = x - y + z
dzdt = -beta * y
return [dxdt, dydt, dzdt]
# パラメータ設定
alpha = 15.6
beta = 28.0
m0 = -1.143
m1 = -0.714
# 初期条件と時間範囲
initial_state = [0.1, 0.0, 0.0]
t_span = (0, 100)
t_eval = np.linspace(t_span[0], t_span[1], 10000)
# 微分方程式を数値的に解く
solution = solve_ivp(chua_circuit, t_span, initial_state, t_eval=t_eval, args=(alpha, beta, m0, m1))
###ここまで
このコードでは、x,y,z空間上で、10000ポイント分の数値演算ができ、その3変数のうちのxとzをプロットしたものが図1だ。これは典型的なカオスのグラフとなっている。
実際のコードは次のとおり。
ダウンロード - 20250721chua_000.py
ダウンロード - variable_sine_tone_builder_wav.py
上の20250721chua_000.pyがchua回路のシミュレーションプログラム本体で、下の
variable_sine_tone_builder_wav.pyは、任意の正弦波を発生させてwavファイルに記録する関数を含むファイルだ。
使い方は、上の2つのファイルを同じホルダに配置し、20250721chua_000.pyを実行する。
すると、図1に示すカオスのグラフが表示され、同ホルダ内にカオスのグラフを音声化したものが生成される。
まずは理屈よりも先に、生成されたカオスの音を聴いていただこう(音量注意)。
20250805追記
91行目を次のように変更して、再生速度を2倍にしたパターンも録音してみた。こちらの方がスピーディでいいかもしれない。
ab.add_tone(freq=vFreq,level_db=-6,pan=vPan,dur_s=0.01,fade_ms=5)
chuaWav000.wav
20250805chuaWav2x.wav (2倍速Ver.)
なんとなくそれらしいサウンドになったように思うが、どうだろうか?ヨガのBGM用に売れるかもしれない。
これは、図1のカオスグラフのxの変域に対して、約65Hz~3kHzの範囲の正弦波を割り付けている。
x<0の領域では、440/3|x|、x>=0の領域では440*3xとしている(20250721chua_000.pyの85、87行目)。
これは単にxの変域に周波数を割り付けているだけで、当初想定した位相差演算などはしていない。
それでは位相差を演算してそれを音に変換するとどうだろうか。
chuaWavHilbert000.wav
20250805chuaWav_hilbert2x.wav (2倍速Ver.)
思ったほどおもしろい効果は得られず、個人的には上の単純割り付けの結果の方が良いように思う。
これはカオスの演算結果x,yに対してそれぞれをヒルベルト変換し、ポイント毎の瞬時位相を求めてその差をとることで、位相差を演算して、その結果を約70Hz~2.7kHzに割り付けている(20250721chua_000.pyの80,82行目)。
また上記のいずれに対しても、共通して、演算結果zの値に応じて、-1(左)~1(右)のパンポットを割り当てている。
以下、コードの簡単な説明。
まずはコード本体の20250721chua_000.pyにおいて、45行目で微分方程式を数値的に解いて、47行目で演算結果x,y,zを各10000個のリストデータとして得ている。61行目以降で、これらのデータのうちx,zをプロットして、図1のグラフを得ている。
次にデータの音声化は、ヒルベルト変換で位相差を使うか、単に変域のデータを使うかを72行目のhilbertフラグで設定する。hilbert=1ならヒルベルト変換による位相差、hilbert=0なら変域データ。
任意の正弦波を発生する関数はvariable_sine_tone_builder_wav.pyに含まれているので、20250721chua_000.pyの13行目以降でAudioBuiderライブラリをインポートしている。
使い方は、
ab = AudioBuilder(sample_rate=48000)
(74行目)として、AudioBuilderオブジェクトをabとして、48kHzサンプリングのインスタンス化をして、ab.add_tone(freq=vFreq,level_db=-6,pan=vPan,dur_s=0.02,fade_ms=10)
(91行目)で各ポイントデータに対してfreq(周波数)、level_db(信号レベル)、pan(パンポット-1~1)、s(信号長さ(s))、フェードイン/アウト時間(ms)をそれぞれ設定して、ポイントデータ毎の正弦波を追加していく。
すべてのデータ(10000個)に対して信号の割り付けができたら、
ab.write_wav("chuaWav000.wav", normalize="store_true", peak=0.99)
(95行目)で、信号ピークを0.99に正規化したオーディオ信号を"chuaWav000.wav"として書き出す。
以上の処理で、グラフと音声信号を生成している。
2022年の記事と比べると、格段にカオスっぽいサウンドが得られたと自負しているが、いかがでしょうか?
最近のコメント