GUI frame
This commit is contained in:
@@ -0,0 +1,7 @@
|
|||||||
|
f:/ncmr/vocaloid/randomcovers/zorra/zorra_release1.mp3
|
||||||
|
f:/ncmr/vocaloid/randomcovers/zorra/zorra_release2.mp3
|
||||||
|
f:/ncmr/vocaloid/randomcovers/zorra/zorra_release4.mp3
|
||||||
|
f:/ncmr/vocaloid/randomcovers/silti/silti_release1.mp3
|
||||||
|
f:/ncmr/vocaloid/northwichcase/transparency/rover_release12.mp3
|
||||||
|
I:/musiikki/[160518] THE IDOLM@STER CINDERELLA GIRLS STARLIGHT MASTER 02 Tulip [320K]/01. Tulip (M@STER VERSION).mp3
|
||||||
|
I:/musiikki/556t - MELTING POT/01. ココロ.mp3
|
||||||
@@ -1,128 +1,40 @@
|
|||||||
import librosa
|
import sys
|
||||||
import numpy as np
|
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel
|
||||||
import os
|
from PyQt5.QtCore import Qt
|
||||||
|
|
||||||
import matplotlib.pyplot as plt
|
class AudioDragDropWidget(QWidget):
|
||||||
import matplotlib.colors as mcolors
|
def __init__(self):
|
||||||
import matplotlib.cm as cm
|
super().__init__()
|
||||||
|
self.initUI()
|
||||||
|
|
||||||
from mutagen.mp3 import MP3
|
def initUI(self):
|
||||||
from mutagen.easyid3 import EasyID3
|
self.setWindowTitle('Drag and Drop Audio Analysis')
|
||||||
|
self.setGeometry(100, 100, 400, 200) # x, y, width, height
|
||||||
|
self.setAcceptDrops(True)
|
||||||
|
|
||||||
def try_mp3_tags(file_path):
|
# Layout and label for displaying messages
|
||||||
try:
|
layout = QVBoxLayout()
|
||||||
# if there is metadata
|
self.label = QLabel('Drag and drop an audio file here', self)
|
||||||
audio = MP3(file_path, ID3=EasyID3)
|
self.label.setAlignment(Qt.AlignCenter)
|
||||||
return audio
|
layout.addWidget(self.label)
|
||||||
except Exception as e:
|
self.setLayout(layout)
|
||||||
print(f"Error reading ID3 tags: {e}")
|
|
||||||
return None
|
|
||||||
|
|
||||||
def read_mp3_tags(file_path):
|
def dragEnterEvent(self, event):
|
||||||
if (audio := try_mp3_tags(file_path)) is not None:
|
if event.mimeData().hasUrls():
|
||||||
print(f"File name: {os.path.basename(file_path)}")
|
event.accept()
|
||||||
print(f"{audio['artist'][0]} - {audio['title'][0]}")
|
|
||||||
else:
|
else:
|
||||||
print(f"File name: {os.path.basename(file_path)}")
|
event.ignore()
|
||||||
|
|
||||||
def analyze_track_librosa(file_path):
|
def dropEvent(self, event):
|
||||||
# Load the audio file
|
files = [u.toLocalFile() for u in event.mimeData().urls()]
|
||||||
# y is the audio time series and sr is the sampling rate
|
for file_path in files:
|
||||||
y, sr = librosa.load(file_path)
|
self.label.setText(f'File dropped: {file_path}')
|
||||||
|
# Here, you would call your plot function with the dropped file path
|
||||||
|
# For example: plot_macro_time_power_graph_colormap(file_path)
|
||||||
|
break # This example only processes the first dropped file
|
||||||
|
|
||||||
# Calculate the maximum amplitude
|
if __name__ == '__main__':
|
||||||
# Librosa's load function normalizes the audio to [-1, 1], so we scale it back
|
app = QApplication(sys.argv)
|
||||||
max_amplitude = np.max(np.abs(y))
|
ex = AudioDragDropWidget()
|
||||||
# Average amplitude
|
ex.show()
|
||||||
avg_amplitude = np.mean(np.abs(y))
|
sys.exit(app.exec_())
|
||||||
|
|
||||||
# Convert max amplitude to dBFS
|
|
||||||
max_amplitude_dBFS = librosa.amplitude_to_db([max_amplitude], ref=1.0)
|
|
||||||
avg_amplitude_dBFS = librosa.amplitude_to_db([avg_amplitude], ref=1.0)
|
|
||||||
|
|
||||||
# Calculate RMS in dB
|
|
||||||
S, phase = librosa.magphase(librosa.stft(y))
|
|
||||||
rms_stft = librosa.feature.rms(S=S)
|
|
||||||
rms = librosa.feature.rms(y=y)
|
|
||||||
avg_power_dBFS_stft = 20 * np.log10(np.mean(rms_stft))
|
|
||||||
avg_power_dBFS = 20 * np.log10(np.mean(rms))
|
|
||||||
|
|
||||||
return max_amplitude_dBFS[0], avg_amplitude_dBFS[0], avg_power_dBFS, avg_power_dBFS_stft
|
|
||||||
|
|
||||||
def plot_macro_time_power_graph(file_path):
|
|
||||||
# Load the audio file
|
|
||||||
y, sr = librosa.load(file_path, mono=True)
|
|
||||||
|
|
||||||
# Define the window and hop length
|
|
||||||
# 10 seconds window and 1 second hop
|
|
||||||
window_length = int(sr * 10) # 10 seconds in samples
|
|
||||||
hop_length = int(sr * 1) # 1 second in samples
|
|
||||||
|
|
||||||
# Calculate RMS over the rolling windows
|
|
||||||
rms = librosa.feature.rms(y=y, frame_length=window_length, hop_length=hop_length)
|
|
||||||
|
|
||||||
# Convert frame indices to time
|
|
||||||
times = librosa.frames_to_time(np.arange(rms.shape[1]), sr=sr, hop_length=hop_length)
|
|
||||||
|
|
||||||
# Normalize RMS for color mapping
|
|
||||||
norm = mcolors.Normalize(vmin=0, vmax=0.4)
|
|
||||||
|
|
||||||
# Choose a colormap
|
|
||||||
cmap = cm.autumn
|
|
||||||
|
|
||||||
# Plot
|
|
||||||
fig, ax = plt.subplots(figsize=(10, 4))
|
|
||||||
ax.set_ylim(0., 0.4)
|
|
||||||
for i in range(len(times)-1):
|
|
||||||
ax.fill_between(times[i:i+2], 0, rms[0][i], color=cmap(norm(rms[0][i])), edgecolor='none')
|
|
||||||
|
|
||||||
# Adding a colorbar to indicate the scale of RMS values
|
|
||||||
sm = cm.ScalarMappable(cmap=cmap, norm=norm)
|
|
||||||
sm.set_array([])
|
|
||||||
cbar = plt.colorbar(sm, ax=ax, label='RMS Power')
|
|
||||||
# cbar.ax.set_yticklabels([f"{x-60.0:.0f} dBFS" for x in cbar.get_ticks()]) # Adjust labels to show true dBFS values
|
|
||||||
|
|
||||||
ax.set_ylabel('Power')
|
|
||||||
ax.set_xlabel('Time')
|
|
||||||
ax.set_title(f'{os.path.basename(file_path)}')
|
|
||||||
# plt.ylabel('Power')
|
|
||||||
# plt.xlabel('Time (s)')
|
|
||||||
# plt.title(f'{os.path.basename(file_path)}')
|
|
||||||
plt.show(block=False)
|
|
||||||
plt.pause(0.001)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def find_mp3_files(directory):
|
|
||||||
mp3_files = []
|
|
||||||
# Walk through the directory
|
|
||||||
for root, dirs, files in os.walk(directory):
|
|
||||||
# Filter and append .mp3 files
|
|
||||||
for file in files:
|
|
||||||
if file.endswith(".mp3"):
|
|
||||||
mp3_files.append(os.path.join(root, file))
|
|
||||||
return mp3_files
|
|
||||||
|
|
||||||
|
|
||||||
# Replace 'path/to/your/audiofile.mp3' with the path to your audio file
|
|
||||||
file_path = []
|
|
||||||
# file_path.append('f:/ncmr/vocaloid/randomcovers/zorra/zorra_release1.mp3')
|
|
||||||
# file_path.append('f:/ncmr/vocaloid/randomcovers/zorra/zorra_release2.mp3')
|
|
||||||
file_path.append('f:/ncmr/vocaloid/randomcovers/zorra/zorra_release4.mp3')
|
|
||||||
# file_path.append('f:/ncmr/vocaloid/randomcovers/silti/silti_release1.mp3')
|
|
||||||
# file_path.append('f:/ncmr/vocaloid/northwichcase/transparency/rover_release12.mp3')
|
|
||||||
file_path.append('I:/musiikki/[160518] THE IDOLM@STER CINDERELLA GIRLS STARLIGHT MASTER 02 Tulip [320K]/01. Tulip (M@STER VERSION).mp3')
|
|
||||||
file_path.append('I:/musiikki/556t - MELTING POT/01. ココロ.mp3')
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for file in file_path:
|
|
||||||
max_amplitude, avg_amplitude, avg_power, avg_power_stft = analyze_track_librosa(file)
|
|
||||||
read_mp3_tags(file)
|
|
||||||
print(f"Maximum Amplitude: {max_amplitude:.2f} dBFS")
|
|
||||||
print(f"Average Amplitude: {avg_amplitude:.2f} dBFS")
|
|
||||||
print(f"Average Power: {avg_power:.2f} dBFS")
|
|
||||||
print(f"Average Power (STFT): {avg_power_stft:.2f} dBFS")
|
|
||||||
plot_macro_time_power_graph(file)
|
|
||||||
|
|
||||||
plt.show()
|
|
||||||
+123
@@ -0,0 +1,123 @@
|
|||||||
|
import librosa
|
||||||
|
import numpy as np
|
||||||
|
import os
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import matplotlib.colors as mcolors
|
||||||
|
import matplotlib.cm as cm
|
||||||
|
|
||||||
|
from mutagen.mp3 import MP3
|
||||||
|
from mutagen.easyid3 import EasyID3
|
||||||
|
|
||||||
|
def try_mp3_tags(file_path):
|
||||||
|
try:
|
||||||
|
# if there is metadata
|
||||||
|
audio = MP3(file_path, ID3=EasyID3)
|
||||||
|
return audio
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error reading ID3 tags: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def read_mp3_tags(file_path):
|
||||||
|
if (audio := try_mp3_tags(file_path)) is not None:
|
||||||
|
print(f"File name: {os.path.basename(file_path)}")
|
||||||
|
print(f"{audio['artist'][0]} - {audio['title'][0]}")
|
||||||
|
else:
|
||||||
|
print(f"File name: {os.path.basename(file_path)}")
|
||||||
|
|
||||||
|
def analyze_track_librosa(file_path):
|
||||||
|
# Load the audio file
|
||||||
|
# y is the audio time series and sr is the sampling rate
|
||||||
|
y, sr = librosa.load(file_path)
|
||||||
|
|
||||||
|
# Calculate the maximum amplitude
|
||||||
|
# Librosa's load function normalizes the audio to [-1, 1], so we scale it back
|
||||||
|
max_amplitude = np.max(np.abs(y))
|
||||||
|
# Average amplitude
|
||||||
|
avg_amplitude = np.mean(np.abs(y))
|
||||||
|
|
||||||
|
# Convert max amplitude to dBFS
|
||||||
|
max_amplitude_dBFS = librosa.amplitude_to_db([max_amplitude], ref=1.0)
|
||||||
|
avg_amplitude_dBFS = librosa.amplitude_to_db([avg_amplitude], ref=1.0)
|
||||||
|
|
||||||
|
# Calculate RMS in dB
|
||||||
|
S, phase = librosa.magphase(librosa.stft(y))
|
||||||
|
rms_stft = librosa.feature.rms(S=S)
|
||||||
|
rms = librosa.feature.rms(y=y)
|
||||||
|
avg_power_dBFS_stft = 20 * np.log10(np.mean(rms_stft))
|
||||||
|
avg_power_dBFS = 20 * np.log10(np.mean(rms))
|
||||||
|
|
||||||
|
return max_amplitude_dBFS[0], avg_amplitude_dBFS[0], avg_power_dBFS, avg_power_dBFS_stft
|
||||||
|
|
||||||
|
def plot_macro_time_power_graph(file_path):
|
||||||
|
# Load the audio file
|
||||||
|
y, sr = librosa.load(file_path, mono=True)
|
||||||
|
|
||||||
|
# Define the window and hop length
|
||||||
|
# 10 seconds window and 1 second hop
|
||||||
|
window_length = int(sr * 10) # 10 seconds in samples
|
||||||
|
hop_length = int(sr * 1) # 1 second in samples
|
||||||
|
|
||||||
|
# Calculate RMS over the rolling windows
|
||||||
|
rms = librosa.feature.rms(y=y, frame_length=window_length, hop_length=hop_length)
|
||||||
|
|
||||||
|
# Convert frame indices to time
|
||||||
|
times = librosa.frames_to_time(np.arange(rms.shape[1]), sr=sr, hop_length=hop_length)
|
||||||
|
|
||||||
|
# Normalize RMS for color mapping
|
||||||
|
norm = mcolors.Normalize(vmin=0, vmax=0.4)
|
||||||
|
|
||||||
|
# Choose a colormap
|
||||||
|
cmap = cm.autumn
|
||||||
|
|
||||||
|
# Plot
|
||||||
|
fig, ax = plt.subplots(figsize=(10, 4))
|
||||||
|
ax.set_ylim(0., 0.4)
|
||||||
|
for i in range(len(times)-1):
|
||||||
|
ax.fill_between(times[i:i+2], 0, rms[0][i], color=cmap(norm(rms[0][i])), edgecolor='none')
|
||||||
|
|
||||||
|
# Adding a colorbar to indicate the scale of RMS values
|
||||||
|
sm = cm.ScalarMappable(cmap=cmap, norm=norm)
|
||||||
|
sm.set_array([])
|
||||||
|
cbar = plt.colorbar(sm, ax=ax, label='RMS Power')
|
||||||
|
# cbar.ax.set_yticklabels([f"{x-60.0:.0f} dBFS" for x in cbar.get_ticks()]) # Adjust labels to show true dBFS values
|
||||||
|
|
||||||
|
ax.set_ylabel('Power')
|
||||||
|
ax.set_xlabel('Time')
|
||||||
|
ax.set_title(f'{os.path.basename(file_path)}')
|
||||||
|
# plt.ylabel('Power')
|
||||||
|
# plt.xlabel('Time (s)')
|
||||||
|
# plt.title(f'{os.path.basename(file_path)}')
|
||||||
|
plt.show(block=False)
|
||||||
|
plt.pause(0.001)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def find_mp3_files(directory):
|
||||||
|
mp3_files = []
|
||||||
|
# Walk through the directory
|
||||||
|
for root, dirs, files in os.walk(directory):
|
||||||
|
# Filter and append .mp3 files
|
||||||
|
for file in files:
|
||||||
|
if file.endswith(".mp3"):
|
||||||
|
mp3_files.append(os.path.join(root, file))
|
||||||
|
return mp3_files
|
||||||
|
|
||||||
|
|
||||||
|
# Replace 'path/to/your/audiofile.mp3' with the path to your audio file
|
||||||
|
file_path = []
|
||||||
|
with open('./files.txt', 'r') as f:
|
||||||
|
for line in f:
|
||||||
|
if line[0] != '#':
|
||||||
|
file_path.append(line.strip())
|
||||||
|
|
||||||
|
for file in file_path:
|
||||||
|
max_amplitude, avg_amplitude, avg_power, avg_power_stft = analyze_track_librosa(file)
|
||||||
|
read_mp3_tags(file)
|
||||||
|
print(f"Maximum Amplitude: {max_amplitude:.2f} dBFS")
|
||||||
|
print(f"Average Amplitude: {avg_amplitude:.2f} dBFS")
|
||||||
|
print(f"Average Power: {avg_power:.2f} dBFS")
|
||||||
|
print(f"Average Power (STFT): {avg_power_stft:.2f} dBFS")
|
||||||
|
plot_macro_time_power_graph(file)
|
||||||
|
|
||||||
|
plt.show()
|
||||||
Reference in New Issue
Block a user