【问题标题】:How can I play music represented as chords in a csv file with Python?如何使用 Python 在 csv 文件中播放表示为和弦的音乐?
【发布时间】:2020-09-20 08:51:11
【问题描述】:

考虑以下代码:

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(C1 = C on octave 1)到 81(A5 = A on octave 5),加上 0 表示静音。

我的问题如下:如何在 Python 中播放这些合唱?比如,我想听听他们的声音,听听他们的声音。提取的文件被分隔在 3 个目录中:trainvalidtest。这些目录中的文件是 .csv 文件,每个文件有 4 列(note0note1note2note3),每列对应于合唱的每个和弦中每个可能按下的钢琴键。我怎样才能把这些数字列表变成我可以听的东西?我以前从来没有这样做过,所以我不知道如何解决这个问题。我希望我明确了我想做的事情:我想将这些合唱从 3 个文件 trainvalidtest 变成 Python 中的真实声音,换句话说,将这些数字变成实际创作的音乐巴赫。

【问题讨论】:

  • 如果您可以将数据转换为 MIDI 文件,那么有可用的模块可以播放这些文件。
  • @martineau 好的,但是如何将数据转换为 MIDI 文件?
  • 我很确定还有其他第三方模块可以做到这一点。

标签: python


【解决方案1】:

您下载处理后的巴赫合唱的 github 用户 Ageron 有他自己的合成器,他用它来生成音频来听音乐。

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])

来源:https://colab.research.google.com/github/ageron/handson-ml2/blob/master/15_processing_sequences_using_rnns_and_cnns.ipynb 和 repo 来源https://github.com/ageron/handson-ml2

运行第一个设置单元,然后转到第 10 部分,查看正在运行的音频单元。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多