1.バイオモルフ
昨日の続き。『心はプログラムできるか』にバイオモルフというプログラムが紹介されていた。次のリンクはBiomorphで検索したら出てきたサイト。
バイオモルフというものを実際に実行できる。
・Biomorphs | Emergent Mind
表示されている9つの個体の中で,一番おもしろいと思うものをクリックしていく。
すると今度はクリックしたものと微妙に異なった新たな個体ができる。
それを繰り返していけば,とてもおもしろい形を作れるというハナシ。
本の中では「進化の力を借りてアートを創る試み」として紹介されていた。
評価関数をコンピュータの中ではなく,人間を用いるというのが非常に面白い着想で,「美しさ」みたいな抽象的なものでも作れる可能性があるということが面白いと思った。
2.ミュージックモルフ
作者の有田先生の研究室では顔モルフというものを作っていたらしい。似顔絵をクリックするだけで作れるというもの。
この辺りから着想を得て良い音楽を選んでいくことで,だんだんと良い音楽に進化していくというプログラムを作ってみた。
残念ながらあまりいい出来とはいえないです……。音楽は5段階中3だったかな……。
2016/01/07 追記
この動画を見るとコードというものを使ってる……コードってなんぞ?プログラムのソースコードのことかの?どうやら音符の塊みたいなもののようだけれど……こういうのは音楽のトーシローができるもんじゃなさそうだ。
とりあえずソースコードを貼っておく。練習でGitHubでレポジトリを作ってみたのでそちらのリンクも貼っとく。
・TonyMooori/Music_Morph
ソースコード
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
import numpy as np | |
import pyaudio | |
import struct | |
import time | |
__author__ = "TonyMooori" | |
class MusicMorph: | |
def __init__(self,length = 8,n_child = 4,pulse = 0.25, mutation = 0.25): | |
""" | |
length: The length of a socre.(楽譜の長さ) | |
n_child: The number of the scores.(楽譜の数) | |
pulse: The length of a pulse(second).(拍の長さ[秒]) | |
mutation: The percentage of mutation.(突然変異の確率) | |
""" | |
""" The frequency of each scales.(音程の周波数) """ | |
self.scales = np.array([ 0.0, 261.63,293.66,329.63,349.23,392.00,440.00,493.88,523.25,]) | |
self.length = length | |
self.n_child = n_child | |
self.pulse = pulse | |
self.mutation = mutation | |
""" Make scores.(楽譜を作る) """ | |
self.refresh() | |
def createSineWave(self,freq,sec=1.0,rate = 44100.0): | |
""" | |
Return the sine wave.(サイン波を返します) | |
freq: The frequency of the sound.(音の周波数) | |
sec: The length of the sound(second).(音の時間[秒]) | |
rate: The sampling rate of the sound.(サンプリング周波数) | |
""" | |
x = np.linspace( 0, 2 * np.pi * sec, num = int(rate * sec)) | |
y = (32767.0 * np.sin( freq * x ) ).astype(np.int) | |
return struct.pack("h" * len(y), *y ) | |
def play(self,indx): | |
""" | |
The function to play the score.(演奏を行う関数) | |
indx: The index of score.(楽譜番号) | |
""" | |
p = pyaudio.PyAudio() | |
stream = p.open( | |
rate=44100, | |
channels=1, | |
format=pyaudio.paFloat32, | |
output=True | |
) | |
""" Play each sound.(音ごとに演奏する) """ | |
for indx,length in self.child_score[indx]: | |
sec = self.pulse * ( 2.0 ** length ) | |
freq = self.scales[int(indx)] | |
stream.write(self.createSineWave(freq,sec)) | |
stream.close() | |
p.terminate() | |
def random_sound(self,last_scale): | |
""" Return a random sound.(音をランダムに作る) """ | |
sound = np.zeros(2) | |
n_scale = len(self.scales) | |
""" Decide a scale of the sound.(音程を決める) """ | |
sound[0] = int(np.random.random_sample() * n_scale) | |
while last_scale == sound[0]: | |
sound[0] = int(np.random.random_sample() * n_scale) | |
""" Decide a length of the sound.(音の長さを決める) """ | |
sound[1] = int(np.random.random_sample() * 4) | |
return sound | |
def random_score(self): | |
""" Return a random score.(ランダムな楽譜を返す) """ | |
score = np.zeros((self.length,2)) | |
last_scale = -1 | |
for i in range(self.length): | |
score[i] = self.random_sound(last_scale) | |
last_scale = score[i,0] | |
return score | |
def make_children(self): | |
""" Remake all scores using the selected score.(選択した楽譜で全て作り直す) """ | |
scores = np.zeros((self.n_child,self.length,2)) | |
scores[0] = self.main_score | |
for i in range(1,self.n_child): | |
scores[i] = self.make_child() | |
return scores | |
def make_child(self): | |
""" Make a new score using a selected score.(類似した楽譜を作る) """ | |
score = self.main_score.copy() | |
last_scale = -1 | |
for i in range(len(score)): | |
if np.random.random_sample() < self.mutation: | |
score[i] = self.random_sound(last_scale) | |
last_scale = score[i,0] | |
return score | |
def select(self,indx): | |
""" | |
Select the best music.(選択を行うメソッド) | |
indx: The number of the score.(楽譜番号) | |
""" | |
self.main_score = self.child_score[indx] | |
self.child_score = self.make_children() | |
def refresh(self): | |
""" Refresh all the scores.(楽譜を一新するメソッド) """ | |
self.main_score = self.random_score() | |
self.child_score = self.make_children() | |
print("Music Morph") | |
n_child = 4 | |
mm = MusicMorph(n_child = n_child) | |
while True: | |
print("\n" + "*" * 40) | |
print("input command") | |
print("-3\t: exit") | |
print("-2\t: init scores") | |
print("-1\t: listen all") | |
for i in range(n_child): | |
print(str(i) + "\t: listen score no." + str(i)) | |
for i in range(n_child): | |
print(str(i+n_child) + "\t: select score no." + str(i)) | |
""" Input and parse to the integer.(入力してint型に変換) """ | |
cmd = raw_input() | |
try: | |
cmd = int(cmd) | |
except: | |
cmd = -4 | |
""" Branch.(分岐) """ | |
if cmd == -3: | |
break | |
elif cmd == -2: | |
print("refreshed") | |
mm.refresh() | |
elif cmd == -1: | |
print("listen all") | |
for i in range(n_child): | |
print("playing no." + str(i) ) | |
mm.play(i) | |
time.sleep(0.25) | |
elif 0 <= cmd <= n_child - 1: | |
print("playing no." + str(cmd)) | |
mm.play( cmd ) | |
elif n_child <= cmd <= 2 * n_child - 1: | |
print("selected no." + str(cmd%n_child)) | |
mm.select(cmd % n_child) | |
else: | |
print("wrong input") | |