Spaces:
Runtime error
Runtime error
import librosa | |
from librosa import display | |
from librosa import feature | |
import numpy as np | |
from matplotlib import pyplot as plt | |
import scipy | |
from numpy import typing as npt | |
import typing | |
def plot_mel_spectrogram( | |
y: npt.ArrayLike, | |
sr:int, | |
shift_array: npt.ArrayLike, | |
with_pitch : bool = True, | |
): | |
S = librosa.feature.melspectrogram(y=y, sr=sr) | |
S_dB = librosa.power_to_db(S, ref=np.max) | |
if with_pitch : | |
f0, voiced_flag, voiced_probs = librosa.pyin(y, | |
fmin=librosa.note_to_hz('C2'), | |
fmax=librosa.note_to_hz('C7')) | |
times = librosa.times_like(f0, sr) | |
fig, ax = plt.subplots(figsize=(12,6)) | |
img = librosa.display.specshow(S_dB, x_axis='time', | |
y_axis='mel', sr=sr, | |
fmax=8000, ax=ax) | |
ax.plot(times, f0, label='f0', color='cyan', linewidth=3) | |
ax.set_xticks(shift_array - shift_array[0], | |
shift_array) | |
fig.colorbar(img, ax=ax, format='%+2.0f dB') | |
ax.legend(loc='upper right') | |
ax.set(title='Mel-frequency spectrogram') | |
else : | |
fig, ax = plt.subplots(figsize=(12,6)) | |
img = librosa.display.specshow(S_dB, x_axis='time', | |
y_axis='mel', sr=sr, | |
fmax=8000, ax=ax) | |
ax.set_xticks(shift_array - shift_array[0], | |
shift_array) | |
fig.colorbar(img, ax=ax, format='%+2.0f dB') | |
ax.set(title='Mel-frequency spectrogram') | |
ax.set_xlabel('Time (s)') | |
return fig, ax | |
def plot_constant_q_transform(y: npt.ArrayLike, sr:int, | |
shift_array: npt.ArrayLike | |
) : | |
C = np.abs(librosa.cqt(y, sr=sr)) | |
fig, ax = plt.subplots(figsize=(12,6)) | |
img = librosa.display.specshow(librosa.amplitude_to_db(C, ref=np.max), | |
sr=sr, x_axis='time', y_axis='cqt_note', ax=ax) | |
ax.set_xticks(shift_array - shift_array[0], | |
shift_array) | |
ax.set_title('Constant-Q power spectrum') | |
ax.set_xlabel('Time (s)') | |
fig.colorbar(img, ax=ax, format="%+2.0f dB") | |
return fig, ax | |
def pitch_class_type_one_vis(y: npt.ArrayLike, sr: int) -> None : | |
S = np.abs(librosa.stft(y)) | |
chroma = librosa.feature.chroma_stft(S=S, sr=sr) | |
count_pitch = np.empty(np.shape(chroma)) # To count pitch | |
notes = np.array(librosa.key_to_notes('C:maj')) | |
# Set the threshold to determine the exact pitch | |
count_pitch[chroma < 0.5] = 0 | |
count_pitch[chroma > 0.5] = 1 | |
# To compute the probability | |
occurProbs = np.empty(np.shape(count_pitch)[0]) | |
for i in range(np.shape(count_pitch)[0]) : | |
total = np.sum(count_pitch) | |
occurProbs[i] = np.sum(count_pitch[i]) / total | |
result = np.vstack((notes, np.round(occurProbs, 4))).T | |
ticks = range(12) | |
fig, ax = plt.subplots() | |
plt.title("Pitch Class") | |
plt.bar(ticks,occurProbs * 100, align='center') | |
plt.xticks(ticks, notes) | |
plt.xlabel("Note") | |
plt.ylabel("Number of occurrences %") | |
return fig, ax, result | |
def pitch_class_histogram_chroma(y: npt.ArrayLike, sr: int, higher_resolution: bool, save_to_csv: bool = False) -> None : | |
S = np.abs(librosa.stft(y)) | |
notes = np.array(librosa.key_to_notes('C:maj')) # For x-axis legend | |
if not higher_resolution : | |
chroma = librosa.feature.chroma_stft(S=S, sr=sr) | |
valid_pitch = np.empty(np.shape(chroma)) # To count pitch | |
valid_pitch[chroma < 0.7] = 0 | |
valid_pitch[chroma >= 0.7] = 1 | |
total = np.sum(valid_pitch) | |
# To compute the probability | |
# WARNING: (12,) means pure 1-D array | |
occurProbs = np.empty((12,)) | |
for i in range(0, 12) : | |
occurProbs[i] = np.sum(valid_pitch[i]) / total | |
ticks = range(12) | |
colors = ['lightcoral', 'goldenrod', 'lightseagreen', 'indigo', 'lightcoral', | |
'goldenrod', 'lightseagreen', 'indigo', 'lightcoral', 'goldenrod', | |
'lightseagreen', 'indigo'] | |
xLegend = notes | |
fig, ax = plt.subplots() | |
ax.bar(ticks,occurProbs * 100, align='center', color=colors) | |
ax.set_xticks(ticks) | |
ax.set_xticklabels(xLegend) | |
ax.set_title("Pitch Class Histogram") | |
ax.set_xlabel("Note") | |
ax.set_ylabel("Occurrences %") | |
if higher_resolution : | |
chroma = librosa.feature.chroma_stft(S=S, sr=sr, n_chroma=120) | |
valid_pitch = np.empty(np.shape(chroma)) # To count pitch | |
valid_pitch[chroma < 0.7] = 0 | |
valid_pitch[chroma >= 0.7] = 1 | |
total = np.sum(valid_pitch) | |
occurProbs = np.empty((120,)) | |
for i in range(0, 120) : | |
occurProbs[i] = np.sum(valid_pitch[i]) / total | |
ticks = range(120) | |
fig, ax = plt.subplots() | |
xLegend = list() | |
for i in range(120) : | |
if i % 10 == 0 : | |
xLegend.append(notes[i // 10]) | |
else : | |
xLegend.append('') | |
colors = list() | |
for i in range(120) : | |
if i % 40 >=0 and i % 40 < 10 : colors.append('lightcoral') | |
elif i % 40 >= 10 and i % 40 < 20 : colors.append('goldenrod') | |
elif i % 40 >= 10 and i % 40 < 30 : colors.append('lightseagreen') | |
elif i % 40 >= 10 and i % 40 < 40 : colors.append('indigo') | |
fig, ax = plt.subplots() | |
ax.bar(ticks,occurProbs * 100, align='center', color = colors) | |
ax.set_xticks(ticks) | |
ax.set_xticklabels(xLegend) | |
ax.set_title("Pitch Class Histogram") | |
ax.set_xlabel("Note") | |
ax.set_ylabel("Occurrence %") | |
result = np.vstack((xLegend, np.round(occurProbs, 4))).T | |
if save_to_csv : | |
with open('pitch_class.csv', 'w') as out : | |
for row in result : | |
print(*row, sep=',', file=out) | |
return fig, ax, result |