Skip to content

Instantly share code, notes, and snippets.

@TonyMooori
Created January 6, 2016 05:59
Show Gist options
  • Save TonyMooori/434bdfa83fcd12aa2f3d to your computer and use it in GitHub Desktop.
Save TonyMooori/434bdfa83fcd12aa2f3d to your computer and use it in GitHub Desktop.
バイオモルフみたいに選んでいくだけで音楽が作れると豪語するプログラム(雑音なら作れる)
# -*- 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")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment