dabinkim commited on
Commit
08bc68d
·
1 Parent(s): 31ad5ac

Add app.py for the user audio input and mel-spec output

Browse files
Files changed (1) hide show
  1. app.py +164 -3
app.py CHANGED
@@ -1,7 +1,168 @@
 
 
 
 
 
 
 
 
 
1
  import gradio as gr
 
2
 
3
- def greet(name):
4
- return "Hello " + name + "!!"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
- demo = gr.Interface(fn=greet, inputs="text", outputs="text")
7
  demo.launch()
 
1
+ import os
2
+ import crepe.crepe as crepe
3
+ import matplotlib.pyplot as plt
4
+ import librosa
5
+ import librosa.display
6
+ import numpy as np
7
+ import torch
8
+ import torchaudio
9
+ import pretty_midi
10
  import gradio as gr
11
+ from scipy.io import wavfile
12
 
13
+ # Helper functions
14
+ def dynamic_range_compression_torch(x, C=1, clip_val=1e-5):
15
+ return torch.log(torch.clamp(x, min=clip_val) * C)
16
+
17
+ def dynamic_range_decompression_torch(x, C=1):
18
+ return torch.exp(x) / C
19
+
20
+ def spectral_normalize_torch(magnitudes):
21
+ output = dynamic_range_compression_torch(magnitudes)
22
+ return output
23
+
24
+ def spectral_de_normalize_torch(magnitudes):
25
+ output = dynamic_range_decompression_torch(magnitudes)
26
+ return output
27
+
28
+ def get_melspec(y: np.ndarray, sr: int = 16000, n_mels: int = 64,
29
+ window_length: int = 1024, hop_length: int = 160, fmax: int = 8000, fmin: int = 0) -> torch.tensor:
30
+ y = np.pad(y, (int((window_length - hop_length) / 2), int((window_length - hop_length) / 2)), mode="reflect")
31
+ S = librosa.feature.melspectrogram(y=y, sr=sr, n_mels=n_mels,
32
+ n_fft=window_length,
33
+ hop_length=hop_length,
34
+ win_length=window_length, window='hann',
35
+ fmin=fmin, fmax=fmax,
36
+ center=False, pad_mode="reflect")
37
+ S_norm = spectral_normalize_torch(torch.tensor(S))
38
+ return S_norm
39
+
40
+ def get_f0_melspec(frequency: np.ndarray, confidence: np.ndarray = None,
41
+ n_mels: int = 64, fmax: int = 8000, fmin: int = 0) -> torch.tensor:
42
+ n_frames = len(frequency)
43
+ S = np.zeros((n_mels, n_frames))
44
+ mel_bin_frequencies = librosa.core.mel_frequencies(n_mels=n_mels + 1, fmin=fmin, fmax=fmax, htk=False)
45
+ mel_band_indices = [
46
+ np.clip(np.searchsorted(mel_bin_frequencies, mel_f, side='right') - 1, 0, n_mels - 1) if mel_f is not None else None
47
+ for mel_f in frequency
48
+ ]
49
+ for t, mel_band in enumerate(mel_band_indices):
50
+ if mel_band is None:
51
+ continue
52
+ if confidence is not None:
53
+ S[mel_band, t] = confidence[t]
54
+ else:
55
+ S[mel_band, t] = 1.0
56
+ S_norm = spectral_normalize_torch(torch.tensor(S))
57
+ return S_norm
58
+
59
+ def midi_to_frequency(midi_file, sr=16000, duration=10.24, hop_length=160):
60
+ midi_data = pretty_midi.PrettyMIDI(midi_file)
61
+ max_len = int(duration * sr // hop_length)
62
+ frequency = np.full(max_len, None)
63
+
64
+ for instrument in midi_data.instruments:
65
+ if instrument.is_drum:
66
+ continue
67
+ for note in instrument.notes:
68
+ start_frame = int(note.start * sr // hop_length)
69
+ end_frame = int(note.end * sr // hop_length)
70
+ frequency[start_frame:end_frame] = note.pitch
71
+
72
+ frequency = np.array([pretty_midi.note_number_to_hz(note) if note is not None else None for note in frequency])
73
+ return frequency
74
+
75
+ def get_item(filepath: str, config: dict, input_type: str = 'midi'):
76
+ max_len = int(config["audio_length"] * config["sr"])
77
+
78
+ if input_type == 'audio':
79
+ if filepath.endswith('.flac'):
80
+ audio, sr = librosa.load(filepath)
81
+ elif filepath.endswith('.wav'):
82
+ sr, audio = wavfile.read(filepath)
83
+ else:
84
+ raise ValueError('Unsupported file format')
85
+
86
+ if audio.ndim > 1:
87
+ audio = np.mean(audio, axis=1)
88
+
89
+ if sr != config["sr"]:
90
+ audio = torchaudio.functional.resample(torch.Tensor(audio), sr, config['sr']).numpy()
91
+ sr = config["sr"]
92
+ hop_length = config["hop_length"]
93
+
94
+ if len(audio) > max_len:
95
+ audio = audio[:max_len]
96
+ elif len(audio) < max_len:
97
+ pad_length = max_len - len(audio)
98
+ audio = np.pad(audio, (0, pad_length), mode="constant")
99
+
100
+ S_waveform = torch.tensor(audio).unsqueeze(0)
101
+ S = get_melspec(audio, sr=config['sr'], n_mels=config['n_mels'], window_length=config['window_length'],
102
+ hop_length=config['hop_length'], fmax=config['fmax'], fmin=config['fmin'])
103
+
104
+ time, frequency, confidence, activation = crepe.predict(audio, sr, viterbi=True)
105
+ if not config['use_confidence']:
106
+ frequency = np.array([f if c >= config['confidence_threshold'] else None for f, c in zip(frequency, confidence)])
107
+
108
+ if len(frequency) < S.shape[1]:
109
+ if config['use_confidence']:
110
+ assert len(confidence) == len(frequency)
111
+ confidence = np.pad(confidence, (0, S.shape[1] - len(confidence)), mode="constant", constant_values=None)
112
+ frequency = np.pad(frequency, (0, S.shape[1] - len(frequency)), mode="constant", constant_values=None)
113
+
114
+ elif len(frequency) > S.shape[1]:
115
+ frequency = frequency[:S.shape[1]]
116
+ if config['use_confidence']:
117
+ confidence = confidence[:S.shape[1]]
118
+
119
+ elif input_type == 'midi':
120
+ confidence = 1.0
121
+ frequency = midi_to_frequency(filepath, sr=config["sr"], duration=config["audio_length"], hop_length=config["hop_length"])
122
+
123
+ S_f0 = get_f0_melspec(frequency, confidence=confidence if config['use_confidence'] else None,
124
+ n_mels=config['n_mels'], fmax=config['fmax'], fmin=config['fmin'])
125
+
126
+ item_dict = {
127
+ 'f0_condition': S_f0
128
+ }
129
+
130
+ return item_dict
131
+
132
+ def spec_show(S, sr):
133
+ fig, ax = plt.subplots(figsize=(6, 2))
134
+ img = librosa.display.specshow(S, sr=sr, ax=ax)
135
+ buf = BytesIO()
136
+ fig.savefig(buf, format='png')
137
+ buf.seek(0)
138
+ plt.close(fig)
139
+ return buf
140
+
141
+ config_AudioLDM = {
142
+ "sr": 16000,
143
+ "audio_length": 10.24,
144
+ "n_mels": 64,
145
+ "window_length": 1024,
146
+ "hop_length": 160,
147
+ "fmax": 8000,
148
+ "fmin": 0,
149
+ "use_confidence": False,
150
+ "confidence_threshold": 0.8,
151
+ }
152
+
153
+ cfg = config_AudioLDM
154
+
155
+ def process_file(file):
156
+ if file.name.endswith('.wav') or file.name.endswith('.flac'):
157
+ item_dict = get_item(file.name, config=cfg, input_type='audio')
158
+ elif file.name.endswith('.mid') or file.name.endswith('.midi'):
159
+ item_dict = get_item(file.name, config=cfg, input_type='midi')
160
+ else:
161
+ return "Unsupported file format"
162
+
163
+ f0_condition = item_dict['f0_condition']
164
+ return spec_show(f0_condition.numpy(), cfg["sr"])
165
+
166
+ demo = gr.Interface(fn=process_file, inputs=gr.inputs.File(), outputs="image", title="Pitch ControlNet")
167
 
 
168
  demo.launch()