python - 输入一系列音符并让它们演奏
问题描述
我儿子和我正在尝试编写一个程序,允许用户输入一系列音符,并将它们保存到一个列表中以供播放。我们提出了以下建议:
import math #import needed modules
import pyaudio #sudo apt-get install python-pyaudio
def playnote(char):
octave = int(char[1])
if char[0] == 'c':
frequency = 16.35*octave+1
elif char[0] =='C':
frequency = 17.32*octave+1
elif char[0] =='d':
frequency = 18.35*octave+1
elif char[0] == 'D':
frequency = 19.45*octave+1
elif char[0] =='e':
frequency = 20.6*octave+1
elif char[0] == 'f':
frequency = 21.83*octave+1
elif char[0] =='F':
frequency = 23.12*octave+1
elif char[0] == 'g':
frequency = 24.5*octave+1
elif char[0] == 'G':
frequency = 25.96*octave+1
elif char[0] == 'a':
frequency = 27.5*octave+1
elif char[0] == 'A':
frequency = 29.14*octave+1
elif char[0] == 'b':
frequency = 30.87*octave+1
elif char[0] == 'p':
del song[-1]
PyAudio = pyaudio.PyAudio #initialize pyaudio
#See https://en.wikipedia.org/wiki/Bit_rate#Audio
bitrate = 256000 #number of frames per second/frameset.
# frequency = 220 #Hz, waves per second, 261.63=C4-note.
LENGTH = 1 #seconds to play sound
if frequency > bitrate:
bitrate = frequency+100
frames = int(bitrate * LENGTH)
# RESTFRAMES = frames % bitrate
wavedata = ''
#generating waves
for x in range(frames):
wavedata = wavedata+chr(int(math.sin(x/((bitrate/frequency)/math.pi))*127+128))
# for x in range(RESTFRAMES):
# wavedata = wavedata+chr(128)
p = PyAudio()
stream = p.open(format = p.get_format_from_width(1),
channels = 1,
rate = bitrate,
output = True)
stream.write(wavedata)
stream.stop_stream()
stream.close()
p.terminate()
song = []
while True:
try:
note = str(input('''Enter note (A-G) (capital for sharp)
and an octave (0-8) or any other key to play: '''))
playnote(note)
song.append(note)
except:
for note in song:
playnote(note)
break
作为起点,它工作得很好,但音符听起来不是很“音乐”。
从这里,我们想知道:
是否有任何现有的 Python 脚本或模块可以做类似的事情?
有没有办法修改波形以模拟不同的仪器?
解决方案
如果您正在寻找使用 Python 制作音乐的其他工作,您可能会发现以下程序对您很有帮助。它使用winsound
Windows 上的模块来产生一定持续时间和频率的哔哔声。下面显示的程序很旧并且没有维护 - 确实是一个实验,但可能会给您和您的儿子一些进一步相关工作的想法。
#! /usr/bin/env python3
import msvcrt
import random
import time
import winsound
# CONSTANTS
KEYS = 'zsxcfvgbnjmk,l./\'q2we4r5t6yu8i9op-[=]'
A4 = 440
AUTHOR = '.\',zb'
NEW_SONG = ('vm',
'zv',
'cn',
'vm',
'xb',
'cn',
'zv')
# CONFIGURATION
NS_SP = 1
SPEED = 5
HOLD_RATIO = 0.95
TRANSPOSE = 0
PAUSE_TIME = 2
SHOW_FREQU = False
# RANDOM
NEIGHBOR_RATIO = 0.9
ODD_RATIO = 0.05
SWITCH_RATIO = 0.01
WHITE_KEYS = 'zxcvbnm,./qwertyuiop[]'
BLACK_KEYS = 'sfgjkl\'245689-='
EXAMPLE_SONG_1 = [('x', 1),
('x', 2),
('x', 1),
('x', 1),
('f', 1),
('g', 1),
('b', 2),
('b', 1),
('g', 2),
('x', 1),
('k', 2),
('k', 1),
('j', 2),
('g', 1),
('f', 5),
('x', 1),
('k', 2),
('k', 1),
('l', 1),
('.', 1),
("'", 1),
('j', 2),
('j', 1),
('g', 2),
('g', 1),
('b', 2),
('g', 1),
('f', 1),
('x', 1),
('f', 1),
('x', 5)]
EXAMPLE_SONG_2 = [('j', 2),
('j', 1),
('j', 2),
('.', 1),
('b', 2),
('j', 1),
('b', 1),
('g', 1.5),
('f', 0.5),
('g', 2),
('g', 1),
('g', 1),
('f', 1),
('x', 1),
('f', 6),
('j', 2),
('j', 1),
('j', 2),
('.', 1),
('b', 2),
('j', 1),
('b', 1),
('g', 1.5),
('f', 0.5),
('g', 2),
('g', 1),
('f', 1),
('x', 1),
('f', 1),
('x', 5),
('x', 1),
('k', 2),
('k', 1),
('l', 3),
('l', 2),
("'", 1),
('.', 2),
('.', 1),
('.', 2),
('.', 1),
('2', 1),
("'", 1),
('.', 1),
('j', 6),
('j', 2),
('j', 1),
('j', 2),
('.', 1),
('b', 2),
('j', 1),
('b', 1),
('g', 1.5),
('f', 0.5),
('g', 2),
('g', 1),
('f', 1),
('x', 1),
('f', 1),
('x', 6)]
EXAMPLE_SONG_3 = [(' ', 1),
('x', 0.5),
('f', 0.5),
('g', 0.5),
('b', 0.5),
('j', 1),
('.', 3),
('.', 0.5),
('l', 0.5),
('k', 0.5),
('l', 0.5),
('j', 3),
(' ', 1),
('k', 0.5),
('j', 0.5),
('b', 0.5),
('k', 0.5),
('j', 1),
('x', 3),
('f', 0.5),
('g', 0.5),
('b', 0.5),
('g', 0.5),
('f', 3),
(' ', 1),
('x', 0.5),
('f', 0.5),
('g', 0.5),
('b', 0.5),
('j', 1),
('.', 3),
('.', 0.5),
('l', 0.5),
('k', 0.5),
('l', 0.5),
('j', 3),
(' ', 1),
('k', 0.5),
('j', 0.5),
('b', 0.5),
('k', 0.5),
('j', 1),
('x', 2.5),
('x', 0.5),
('b', 0.5),
('g', 0.5),
('f', 0.5),
('g', 0.5),
('x', 3),
('z', 0.5),
('x', 0.5),
('f', 0.5),
('g', 0.5),
('b', 0.5),
('j', 0.5),
('k', 1),
('.', 0.5),
('l', 0.5),
('k', 0.5),
('l', 0.5),
('.', 1),
('k', 2),
(' ', 1),
('l', 0.5),
('k', 0.5),
('j', 0.5),
('k', 0.5),
('l', 3),
(' ', 1),
('k', 0.5),
('j', 0.5),
('b', 0.5),
('j', 0.5),
('k', 1),
('b', 2),
(' ', 1),
('j', 0.5),
('b', 0.5),
('g', 0.5),
('b', 0.5),
('j', 3),
(' ', 1),
('.', 0.5),
('l', 0.5),
('k', 0.5),
('l', 0.5),
('.', 1),
('k', 2),
("'", 0.5),
('.', 0.5),
('l', 0.5),
('.', 0.5),
('j', 3),
(' ', 1),
("'", 0.5),
('.', 0.5),
('l', 0.5),
('.', 0.5),
('j', 3),
(' ', 1),
('k', 0.5),
('j', 0.5),
('b', 0.5),
('k', 0.5),
('j', 1),
('x', 2),
(' ', 1),
('b', 0.5),
('g', 0.5),
('f', 0.5),
('g', 0.5),
('x', 3)]
EXAMPLE_SONG_4 = [('j', 1.5),
('j', 0.5),
('j', 0.75),
('b', 0.25),
('g', 0.75),
('b', 0.25),
('j', 1),
('k', 1),
('j', 2),
('l', 1.5),
('l', 0.5),
('l', 0.75),
('k', 0.25),
('j', 0.75),
('b', 0.25),
('g', 1),
('k', 1),
('j', 2),
('j', 1.5),
('j', 0.5),
('j', 0.75),
('b', 0.25),
('g', 0.75),
('b', 0.25),
('j', 1),
('k', 1),
('j', 1),
('.', 1),
("'", 2),
('l', 2),
('.', 4),
('.', 1.5),
('l', 0.5),
('.', 0.75),
('l', 0.25),
('.', 0.75),
('k', 0.25),
('k', 1),
('j', 1),
('j', 2),
('l', 1.5),
('k', 0.5),
('l', 0.75),
('k', 0.25),
('l', 0.75),
('k', 0.25),
('j', 1),
('.', 1),
('.', 2),
('.', 1.5),
('l', 0.5),
('.', 0.75),
('l', 0.25),
('.', 0.75),
('k', 0.25),
('k', 1),
('j', 1),
('j', 1),
('.', 1),
("'", 2),
('l', 2),
('.', 4)]
EXAMPLE_SONG_5 = [('g', 0.5),
('g', 0.5),
('g', 0.5),
('g', 0.5),
('b', 0.5),
('b', 0.5),
('b', 0.5),
('g', 0.5),
('f', 0.5),
('f', 0.5),
('j', 0.5),
('f', 0.5),
('g', 2),
('b', 0.5),
('b', 0.5),
('j', 0.5),
('k', 0.5),
('j', 0.5),
('x', 0.5),
('b', 0.5),
('g', 0.5),
('f', 4),
('g', 0.5),
('g', 0.5),
('g', 0.5),
('g', 0.5),
('b', 0.5),
('g', 0.5),
('g', 0.5),
('g', 0.5),
('k', 0.5),
('k', 0.5),
('l', 0.5),
('k', 0.5),
('g', 1),
('g', 1),
('b', 0.5),
('b', 0.5),
('j', 0.5),
('k', 0.5),
('j', 0.5),
('x', 0.5),
('b', 0.5),
('g', 0.5),
('f', 5),
('j', 1),
('k', 1),
('l', 1),
('l', 0.5),
('.', 0.5),
('.', 0.5),
('j', 0.5),
('j', 1.5),
('g', 0.5),
('b', 0.5),
('g', 0.5),
('x', 0.5),
('f', 0.5),
('g', 1.5),
('g', 0.5),
('b', 0.5),
('b', 0.5),
('j', 0.5),
('k', 0.5),
('j', 0.5),
('.', 0.5),
('.', 0.5),
('l', 0.5),
('k', 0.5),
('k', 0.5),
('l', 0.5),
('.', 0.5),
("'", 1.5),
("'", 0.5),
('2', 0.5),
('2', 0.5),
('2', 0.5),
("'", 0.5),
("'", 0.5),
('.', 0.5),
('l', 0.5),
('.', 0.5),
('k', 0.5),
('k', 0.5),
('k', 0.5),
('j', 0.5),
('b', 1.5),
('f', 0.5),
('g', 0.5),
('j', 0.5),
('j', 0.5),
('g', 0.5),
('b', 0.5),
('k', 0.5),
('k', 0.5),
('j', 0.5),
('k', 2),
('l', 2),
('.', 4)]
EXAMPLE_SONG_6 = [('j', 2),
('k', 1),
('j', 2),
('j', 1),
('b', 2),
('g', 1),
('b', 0.5),
('g', 0.5),
('f', 2),
('g', 2),
('j', 1),
('.', 2),
('j', 1),
('b', 2),
('f', 1),
('j', 3),
('j', 2),
('k', 1),
('j', 2),
('j', 1),
('k', 2),
('l', 1),
('.', 1),
('k', 2),
('j', 2),
('g', 1),
('x', 2),
('g', 1),
('f', 2),
('x', 1),
('x', 3),
('.', 2),
("'", 1),
('.', 2),
('l', 1),
('.', 2),
("'", 1),
('.', 1),
('k', 2),
('j', 2),
('.', 1),
('2', 2),
('.', 1),
("'", 2),
('k', 1),
('j', 3),
('j', 1),
('k', 1),
('l', 1),
('.', 2),
('l', 1),
('k', 2),
('j', 1),
('j', 1),
('g', 2),
('g', 2),
('j', 1),
('x', 2),
('g', 1),
('f', 2),
('x', 1),
('x', 3)]
# These next few songs were contributed by Mike Sperry.
TWINKLE_TWINKLE = [('c', 1),
('c', 1),
('m', 1),
('m', 1),
(',', 1),
(',', 1),
('m', 2),
('n', 1),
('n', 1),
('b', 1),
('b', 1),
('v', 1),
('v', 1),
('c', 2),
('m', 1),
('m', 1),
('n', 1),
('n', 1),
('b', 1),
('b', 1),
('v', 2),
('m', 1),
('m', 1),
('n', 1),
('n', 1),
('b', 1),
('b', 1),
('v', 2),
('c', 1),
('c', 1),
('m', 1),
('m', 1),
(',', 1),
(',', 1),
('m', 2),
('n', 1),
('n', 1),
('b', 1),
('b', 1),
('v', 1),
('v', 1),
('c', 2)]
ABCS = [('c', 1),
('c', 1),
('m', 1),
('m', 1),
(',', 1),
(',', 1),
('m', 2),
('n', 1),
('n', 1),
('b', 1),
('b', 1),
('v', 0.5),
('v', 0.5),
('v', 0.5),
('v', 0.5),
('c', 2),
('m', 1),
('m', 1),
('n', 2),
('b', 1),
('b', 1),
('v', 2),
('m', 1),
('m', 1),
('n', 2),
('b', 1),
('b', 1),
('v', 2),
('c', 1),
('c', 1),
('m', 1),
('m', 1),
(',', 1),
(',', 1),
('m', 2),
('n', 1),
('n', 1),
('b', 1),
('b', 1),
('v', 1),
('v', 1),
('c', 2)]
BAH_BAH_BLACK_SHEEP = [('c', 1),
('c', 1),
('m', 1),
('m', 1),
(',', 0.5),
(',', 0.5),
(',', 0.5),
(',', 0.5),
('m', 2),
('n', 1),
('n', 1),
('b', 1),
('b', 1),
('v', 1),
('v', 1),
('c', 2),
('m', 1),
('m', 0.5),
('m', 0.5),
('n', 1),
('n', 1),
('b', 1),
('b', 0.5),
('b', 0.5),
('v', 2),
('m', 1),
('m', 0.5),
('m', 0.5),
('n', 0.5),
('n', 0.5),
('n', 0.5),
('n', 0.5),
('b', 1),
('b', 0.5),
('b', 0.5),
('v', 2),
('c', 1),
('c', 1),
('m', 1),
('m', 1),
(',', 0.5),
(',', 0.5),
(',', 0.5),
(',', 0.5),
('m', 2),
('n', 1),
('n', 1),
('b', 1),
('b', 1),
('v', 1),
('v', 1),
('c', 2)]
HAPPY_BIRTHDAY = [('m', 0.75),
('m', 0.25),
(',', 1),
('m', 1),
('/', 1),
('.', 2),
('m', 0.75),
('m', 0.25),
(',', 1),
('m', 1),
('q', 1),
('/', 2),
('m', 0.75),
('m', 0.5),
('r', 1),
('w', 1),
('/', 1),
('.', 1),
(',', 1),
('n', 0.75),
('n', 0.25),
('b', 1),
('c', 1),
('v', 1),
('c', 3)]
# KNOWN MUSIC
SONGS = EXAMPLE_SONG_1, \
EXAMPLE_SONG_2, \
EXAMPLE_SONG_3, \
EXAMPLE_SONG_4, \
EXAMPLE_SONG_5, \
EXAMPLE_SONG_6, \
TWINKLE_TWINKLE, \
ABCS, \
BAH_BAH_BLACK_SHEEP, \
HAPPY_BIRTHDAY
def main():
print('''
MENU
====
(R)andom
(S)huffle
(P)lay
(K)eyboard
(A)uthor
(N)ew Song''')
while True:
key = msvcrt.getwch()
if key in 'rspk': print()
if key == 'r': menu_help(random.random)
if key == 's': menu_help(random.shuffle)
if key == 'p': select_song()
if key == 'k': menu_help()
if key == 'a': author()
if key == 'n': new_song()
def new_song():
while True:
sig = 0
for notes in NEW_SONG:
sig *= 2
for note in random.sample(notes, 2):
try:
winsound.Beep(get_frequency(note), int(100 / float(NS_SP)))
except:
pass
if notes[1] == note:
sig += 1
time.sleep((1.0 / 30) / NS_SP)
if not SHOW_FREQU:
print(sig + 1)
def select_song():
songs = (('EXAMPLE_SONG_1', EXAMPLE_SONG_1),
('EXAMPLE_SONG_2', EXAMPLE_SONG_2),
('EXAMPLE_SONG_3', EXAMPLE_SONG_3),
('EXAMPLE_SONG_4', EXAMPLE_SONG_4),
('EXAMPLE_SONG_5', EXAMPLE_SONG_5),
('EXAMPLE_SONG_6', EXAMPLE_SONG_6),
('TWINKLE_TWINKLE', TWINKLE_TWINKLE),
('ABCS', ABCS),
('BAH_BAH_BLACK_SHEEP', BAH_BAH_BLACK_SHEEP),
('HAPPY_BIRTHDAY', HAPPY_BIRTHDAY))
for index, data in enumerate(songs):
print('(%s) %s' % (index + 1, data[0].replace('_', ' ').lower().title()))
while True:
try:
index = int(input('\nSelect: '))
assert 0 < index <= len(songs)
play(songs[index - 1][1])
except:
pass
def menu_help(score=None):
if isinstance(score, list):
play(score)
elif score is random.random:
play_random()
elif score is random.shuffle:
play_songs()
keyboard()
def play(score):
for key, duration in score:
duration /= float(SPEED)
bd = int(duration * HOLD_RATIO * 1000)
sd = duration * (1 - HOLD_RATIO)
try:
winsound.Beep(get_frequency(key), bd)
except:
time.sleep(duration * HOLD_RATIO)
time.sleep(sd)
def keyboard():
while msvcrt.kbhit():
msvcrt.getwch()
while True:
try:
winsound.Beep(get_frequency(msvcrt.getwch()), 1000)
except:
pass
def get_frequency(key):
assert key[0] in KEYS
if SHOW_FREQU:
frequ = int((A4 * 2 ** ((KEYS.find(key[0]) + key.count('+') - (0 if key[0] == '-' else key.count('-')) + TRANSPOSE) / 12.0)) + 0.5)
print(frequ)
return frequ
else:
print(key, end=' ')
return int((A4 * 2 ** ((KEYS.find(key[0]) + key.count('+') - (0 if key[0] == '-' else key.count('-')) + TRANSPOSE) / 12.0)) + 0.5)
def play_random():
key = 'c'
RANDOM_KEYS = WHITE_KEYS
while not msvcrt.kbhit():
if random.random() < SWITCH_RATIO:
if RANDOM_KEYS is WHITE_KEYS:
RANDOM_KEYS = BLACK_KEYS
else:
RANDOM_KEYS = WHITE_KEYS
key = RANDOM_KEYS[random.randrange(len(RANDOM_KEYS))]
if random.random() < NEIGHBOR_RATIO:
index = RANDOM_KEYS.index(key[0]) + key.count('+') - key.count('-') + random.randrange(2) * 2 - 1
if index < 0:
key = RANDOM_KEYS[0] + '-' * (index * -1)
elif index >= len(RANDOM_KEYS):
key = RANDOM_KEYS[-1] + '+' * (index - len(RANDOM_KEYS) + 1)
else:
key = RANDOM_KEYS[index]
else:
key = RANDOM_KEYS[random.randrange(len(RANDOM_KEYS))]
if random.random() < ODD_RATIO:
if random.randrange(2):
key += '+'
else:
key += '-'
neg = key.count('-')
pos = key.count('+')
trans = pos - neg
if trans > 0:
key = key[0] + '+' * trans
elif trans < 0:
key = key[0] + '-' * (trans * -1)
else:
key = key[0]
winsound.Beep(get_frequency(key), 100)
def play_songs():
songs = list(SONGS)
while True:
random.shuffle(songs)
for song in songs:
play(song)
time.sleep(PAUSE_TIME)
def author():
for note in AUTHOR:
winsound.Beep(get_frequency(note), 1000)
time.sleep(1)
while msvcrt.kbhit():
msvcrt.getwch()
author = random.sample(AUTHOR, len(AUTHOR))
while not msvcrt.kbhit():
for note in author:
winsound.Beep(get_frequency(note), 100)
last_note = author[-1]
author = random.sample(AUTHOR, len(AUTHOR))
while author[0] == last_note:
author = random.sample(AUTHOR, len(AUTHOR))
if __name__ == '__main__':
main()
推荐阅读
- c# - RS-232 无法在 Windows 10 物联网上运行
- c# - 从具有索引的数组中获取前 3 个最高值
- google-apps-script - Google脚本中的“委派被拒绝”
- c# - 两个协变接口的 C# 协方差问题
- 3d - 如何创建 USDZ 文件?
- nlp - 如何合并 2 个 LUIS 模型?
- python - 在 Antlr4 中解析字符串中的令牌
- facebook - 如何使用应用访问令牌获取 Facebook 应用的所有者电子邮件
- web-services - 启动wildfly时出现org.jboss.weld.exceptions.DefinitionException
- kakoune - Kakoune:如何在 goto 模式下映射“向前跳跃”和“向后跳跃”(例如,将“gp”映射到
)