如何使用Python在csv文件中播放和弦表示的音乐?
考虑以下代码:如何使用Python在csv文件中播放和弦表示的音乐?,python,Python,考虑以下代码: import numpy as np import pandas as pd from pathlib import Path from tensorflow import keras def load_chorales(filepaths): return [pd.read_csv(filepath).values.tolist() for filepath in filepaths] DOWNLOAD_ROOT = "https://github.com
import numpy as np
import pandas as pd
from pathlib import Path
from tensorflow import keras
def load_chorales(filepaths):
return [pd.read_csv(filepath).values.tolist() for filepath in filepaths]
DOWNLOAD_ROOT = "https://github.com/ageron/handson-ml2/raw/master/datasets/jsb_chorales/"
FILENAME = "jsb_chorales.tgz"
filepath = keras.utils.get_file(FILENAME,
DOWNLOAD_ROOT + FILENAME,
cache_subdir="datasets/jsb_chorales",
extract=True)
jsb_chorales_dir = Path(filepath).parent
train_files = sorted(jsb_chorales_dir.glob("train/chorale_*.csv"))
valid_files = sorted(jsb_chorales_dir.glob("valid/chorale_*.csv"))
test_files = sorted(jsb_chorales_dir.glob("test/chorale_*.csv"))
train_chorales = load_chorales(train_files)
valid_chorales = load_chorales(valid_files)
test_chorales = load_chorales(test_files)
代码下载巴赫合唱团的数据集并将其解压。它由约翰·塞巴斯蒂安·巴赫创作的382首合唱曲组成。每个合唱的时间步长为100到640,每个时间步长包含4个整数,其中每个整数对应钢琴上的音符索引(值0除外,该值表示不播放音符)。这是一个合唱(来自训练集)的示例:
print(train_chorales[0])
[[74, 70, 65, 58],
[74, 70, 65, 58],
[74, 70, 65, 58],
[74, 70, 65, 58],
[75, 70, 58, 55],
...
[70, 65, 62, 46],
[70, 65, 62, 46],
[70, 65, 62, 46]]
它由192个时间步(或和弦,或192个4个值的列表组成。换句话说,上面的print语句将打印192行4个整数的列表)
在数据集中,音符的范围从36(1倍频程上的C1=C)到81(5倍频程上的A5=A),加上0表示静音
我的问题是:如何用Python播放这些合唱?我想听听他们的声音。提取的文件分为3个目录:
train
、valid
和test
。这些目录中的文件是.csv
文件,每个文件有4列(note0
,note1
,note2
,和note3
),合唱中每个和弦中每个可能按下的钢琴键对应一列。我怎样才能把这些数字列表变成我能听到的东西呢?我以前从未这样做过,所以我不知道如何解决这个问题。我希望我清楚地说明了我想做什么:我想把这些合唱从3个文件train
,valid
,和test
转换成python中的真实声音,换言之,将这些数字转换成巴赫创作的实际音乐。github用户Agron您可以从下载处理过的巴赫合唱曲,他有自己的合成器,用于生成音频来听音乐
from IPython.display import Audio
def notes_to_frequencies(notes):
# Frequency doubles when you go up one octave; there are 12 semi-tones
# per octave; Note A on octave 4 is 440 Hz, and it is note number 69.
return 2 ** ((np.array(notes) - 69) / 12) * 440
def frequencies_to_samples(frequencies, tempo, sample_rate):
note_duration = 60 / tempo # the tempo is measured in beats per minutes
# To reduce click sound at every beat, we round the frequencies to try to
# get the samples close to zero at the end of each note.
frequencies = np.round(note_duration * frequencies) / note_duration
n_samples = int(note_duration * sample_rate)
time = np.linspace(0, note_duration, n_samples)
sine_waves = np.sin(2 * np.pi * frequencies.reshape(-1, 1) * time)
# Removing all notes with frequencies ≤ 9 Hz (includes note 0 = silence)
sine_waves *= (frequencies > 9.).reshape(-1, 1)
return sine_waves.reshape(-1)
def chords_to_samples(chords, tempo, sample_rate):
freqs = notes_to_frequencies(chords)
freqs = np.r_[freqs, freqs[-1:]] # make last note a bit longer
merged = np.mean([frequencies_to_samples(melody, tempo, sample_rate)
for melody in freqs.T], axis=0)
n_fade_out_samples = sample_rate * 60 // tempo # fade out last note
fade_out = np.linspace(1., 0., n_fade_out_samples)**2
merged[-n_fade_out_samples:] *= fade_out
return merged
def play_chords(chords, tempo=160, amplitude=0.1, sample_rate=44100, filepath=None):
samples = amplitude * chords_to_samples(chords, tempo, sample_rate)
if filepath:
from scipy.io import wavfile
samples = (2**15 * samples).astype(np.int16)
wavfile.write(filepath, sample_rate, samples)
return display(Audio(filepath))
else:
return display(Audio(samples, rate=sample_rate))
play_chords(train_chorales[0])
来源:和回购来源
运行第一个设置单元,然后转到第10节,查看音频单元的运行情况。如果您可以将数据转换为MIDI文件,那么就有可以播放这些文件的模块。@martineau好的,但是如何将数据转换为MIDI文件呢?我很确定还有其他第三方模块可以用于此。