|
import os.path |
|
import json |
|
from tqdm import tqdm |
|
import pandas as pd |
|
import numpy as np |
|
import textgrid |
|
import pretty_midi |
|
import music21 |
|
import librosa |
|
import soundfile as sf |
|
|
|
|
|
def piano_roll_to_pretty_midi(piano_roll, fs=100, program=0, bpm=120): |
|
notes, frames = piano_roll.shape |
|
pm = pretty_midi.PrettyMIDI() |
|
instrument = pretty_midi.Instrument(program=program, ) |
|
|
|
|
|
piano_roll = np.pad(piano_roll, [(0, 0), (1, 1)], 'constant') |
|
|
|
|
|
velocity_changes = np.nonzero(np.diff(piano_roll).T) |
|
|
|
|
|
prev_velocities = np.zeros(notes, dtype=int) |
|
note_on_time = np.zeros(notes) |
|
|
|
for time, note in zip(*velocity_changes): |
|
|
|
velocity = piano_roll[note, time + 1] |
|
time = time / fs * bpm / 120 |
|
|
|
if velocity > 0: |
|
if prev_velocities[note] == 0: |
|
note_on_time[note] = time |
|
prev_velocities[note] = velocity |
|
else: |
|
pm_note = pretty_midi.Note( |
|
velocity=prev_velocities[note], |
|
pitch=note, |
|
start=note_on_time[note], |
|
end=time) |
|
instrument.notes.append(pm_note) |
|
prev_velocities[note] = 0 |
|
pm.instruments.append(instrument) |
|
|
|
beats = np.array([0, int(pm.get_end_time()+1)]) |
|
pm.adjust_times(beats, beats * 120 / bpm) |
|
|
|
return pm |
|
|
|
|
|
f = open('CSD/English/metadata.json', encoding="utf8") |
|
meta = json.load(f) |
|
folder = 'CSD/English/' |
|
for wav in tqdm(os.listdir(folder+'wav')): |
|
song_id = wav.replace('.wav', '') |
|
midi_id = wav.replace('.wav', '.mid') |
|
roll_id = wav.replace('.wav', '.npy') |
|
|
|
wav, sr = librosa.load(folder+'wav/'+wav) |
|
midi = pretty_midi.PrettyMIDI(folder+'mid/'+midi_id) |
|
roll = midi.get_piano_roll() |
|
|
|
bpm = meta[song_id]['tempo'] |
|
|
|
for i in range(int(roll.shape[1])//1000): |
|
|
|
start = i*10 |
|
end = (i+1)*10 |
|
|
|
wav_seg = wav[round(start * sr):round(end * sr)] |
|
|
|
os.makedirs('CSD_segements/'+song_id+'/vocal/', exist_ok=True) |
|
os.makedirs('CSD_segements/' + song_id + '/roll/', exist_ok=True) |
|
os.makedirs('CSD_segements/' + song_id + '/midi/', exist_ok=True) |
|
|
|
sf.write('CSD_segements/'+song_id+'/vocal/'+str(i)+'.wav', wav_seg, samplerate=sr) |
|
|
|
cur_roll = roll[:, round(100*start):round(100*end)] |
|
|
|
if round((end-start)*100) != cur_roll.shape[1]: |
|
print(sentence) |
|
print(song_id) |
|
print((end-start)*100) |
|
print(cur_roll.shape) |
|
|
|
|
|
np.save('CSD_segements/'+song_id+'/roll/'+str(i)+'.npy', cur_roll) |
|
|
|
|
|
cur_midi = piano_roll_to_pretty_midi(cur_roll, fs=100, bpm=bpm) |
|
|
|
cur_midi.write('CSD_segements/'+song_id+'/midi/'+str(i)+'.midi') |
|
|
|
|
|
|
|
|
|
|