trying other stuff

This commit is contained in:
tsi-billypom 2025-03-31 15:51:06 -04:00
parent a115a3c423
commit c906922372
3 changed files with 33 additions and 22 deletions

View File

@ -11,7 +11,7 @@ class AudioVisualizer(QtWidgets.QWidget):
self.media_player = media_player self.media_player = media_player
self.x_resolution = x_resolution self.x_resolution = x_resolution
self.fft_analyser = FFTAnalyser(self.media_player, self.x_resolution) self.fft_analyser = FFTAnalyser(self.media_player, self.x_resolution)
self.fft_analyser.calculated_visual.connect(self.set_amplitudes) self.fft_analyser.calculatedVisual.connect(self.set_amplitudes)
self.fft_analyser.start() self.fft_analyser.start()
self.amps = np.array([]) self.amps = np.array([])
self._plot_item = None self._plot_item = None
@ -63,7 +63,7 @@ class AudioVisualizer(QtWidgets.QWidget):
With a noise floor cutoff at around -96dB (for very small values) With a noise floor cutoff at around -96dB (for very small values)
""" """
# Avoid log(0) by adding a small epsilon # Avoid log(0) by adding a small epsilon
epsilon = 1e-10 epsilon = 1e-30
amplitudes = np.maximum(self.amps, epsilon) amplitudes = np.maximum(self.amps, epsilon)
# Convert to decibels (20*log10 is the standard formula for amplitude to dB) # Convert to decibels (20*log10 is the standard formula for amplitude to dB)
db_values = 20 * np.log10(amplitudes) db_values = 20 * np.log10(amplitudes)
@ -72,4 +72,9 @@ class AudioVisualizer(QtWidgets.QWidget):
return db_values return db_values
def set_amplitudes(self, amps): def set_amplitudes(self, amps):
"""
This function is hooked into the calculatedVisual signal from FFTAnalyzer() object
Amps are assigned here, based on values passed by the signal
"""
# self.amps = np.maximum(np.array(amps), 1e-12) # Set a very small threshold
self.amps = np.array(amps) self.amps = np.array(amps)

View File

@ -11,6 +11,7 @@ from mutagen.id3 import ID3
from mutagen.id3._frames import APIC from mutagen.id3._frames import APIC
from configparser import ConfigParser from configparser import ConfigParser
from pathlib import Path from pathlib import Path
from numpy import where as npwhere
from appdirs import user_config_dir from appdirs import user_config_dir
from logging import debug, error, warning, basicConfig, INFO, DEBUG from logging import debug, error, warning, basicConfig, INFO, DEBUG
from ui import Ui_MainWindow from ui import Ui_MainWindow
@ -161,7 +162,7 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
self.config.read(self.cfg_file) self.config.read(self.cfg_file)
self.player: QMediaPlayer = QMediaPlayer() # Audio player object self.player: QMediaPlayer = QMediaPlayer() # Audio player object
self.probe: QAudioProbe = QAudioProbe() # Gets audio data self.probe: QAudioProbe = QAudioProbe() # Gets audio data
self.analyzer_x_resolution = 150 self.analyzer_x_resolution = 100
self.audio_visualizer: AudioVisualizer = AudioVisualizer( self.audio_visualizer: AudioVisualizer = AudioVisualizer(
self.player, self.analyzer_x_resolution self.player, self.analyzer_x_resolution
) )
@ -446,6 +447,8 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
if len(y) == 0: if len(y) == 0:
return return
# print(y)
# if self.audio_visualizer._plot_item is None: # if self.audio_visualizer._plot_item is None:
# thanks cursor sonnet whatever # thanks cursor sonnet whatever
self.PlotWidget.clear() self.PlotWidget.clear()

View File

@ -12,7 +12,7 @@ from logging import debug, info
class FFTAnalyser(QtCore.QThread): class FFTAnalyser(QtCore.QThread):
"""Analyses a song using FFTs.""" """Analyses a song using FFTs."""
calculated_visual = QtCore.pyqtSignal(np.ndarray) calculatedVisual = QtCore.pyqtSignal(np.ndarray)
def __init__(self, player, x_resolution): # noqa: F821 def __init__(self, player, x_resolution): # noqa: F821
super().__init__() super().__init__()
@ -25,7 +25,7 @@ class FFTAnalyser(QtCore.QThread):
# of the audio at a specific point in time # of the audio at a specific point in time
# in this case, it takes 5% of the samples at some point in time # in this case, it takes 5% of the samples at some point in time
self.sampling_window_length = 0.05 self.sampling_window_length = 0.05
self.visual_delta_threshold = 1000 self.visual_delta_threshold = 100
self.sensitivity = 10 self.sensitivity = 10
def reset_media(self): def reset_media(self):
@ -52,9 +52,8 @@ class FFTAnalyser(QtCore.QThread):
sample_count = int(self.song.frame_rate * self.sampling_window_length) sample_count = int(self.song.frame_rate * self.sampling_window_length)
start_index = int((self.player.position() / 1000) * self.song.frame_rate) start_index = int((self.player.position() / 1000) * self.song.frame_rate)
v_sample = self.samples[ # samples to analyse
start_index : start_index + sample_count v_sample = self.samples[start_index : start_index + sample_count]
] # samples to analyse
# Use a window function to reduce spectral leakage # Use a window function to reduce spectral leakage
window = np.hanning(len(v_sample)) window = np.hanning(len(v_sample))
@ -65,6 +64,7 @@ class FFTAnalyser(QtCore.QThread):
freq = np.fft.fftfreq(fourier.size, d=self.sampling_window_length) freq = np.fft.fftfreq(fourier.size, d=self.sampling_window_length)
amps = 2 / v_sample.size * np.abs(fourier) amps = 2 / v_sample.size * np.abs(fourier)
data = np.array([freq, amps]).T data = np.array([freq, amps]).T
# TEST:
# print(freq * .05 * self.song.frame_rate) # print(freq * .05 * self.song.frame_rate)
# NOTE: # NOTE:
@ -108,26 +108,29 @@ class FFTAnalyser(QtCore.QThread):
# array (self.points) is so that we can fade out the previous amplitudes from # array (self.points) is so that we can fade out the previous amplitudes from
# the past # the past
for n, amp in enumerate(point_samples): for n, amp in enumerate(point_samples):
# amp *= 2 if self.player.state() in (
self.player.PausedState,
if ( self.player.StoppedState,
self.points[n] > 0
and amp < self.points[n]
or self.player.state()
in (self.player.PausedState, self.player.StoppedState)
): ):
self.points[n] -= self.points[n] / 5 # fade out # More aggressive decay when no audio is playing
elif abs(self.points[n] - amp) > self.visual_delta_threshold: self.points[n] *= 0.7 # Faster fade out when paused/stopped
elif amp < self.points[n]:
# Faster fade for frequencies that are decreasing
self.points[n] = self.points[n] * 0.8 + amp * 0.2 # Smoother transition
else:
# Rise quickly to new peaks
self.points[n] = amp self.points[n] = amp
if self.points[n] < 1:
self.points[n] = 1e-12 # Set a lower threshold to properly reach zero
if self.points[n] < 1e-4:
self.points[n] = 0
# interpolate points # interpolate points
rs = gaussian_filter1d(self.points, sigma=1.5) rs = gaussian_filter1d(self.points, sigma=1)
# divide by the highest sample in the song to normalise the # divide by the highest sample in the song to normalise the
# amps in terms of decimals from 0 -> 1 # amps in terms of decimals from 0 -> 1
self.calculated_visual.emit(rs / self.max_sample) self.calculatedVisual.emit(rs / self.max_sample)
# self.calculated_visual.emit(rs) # self.calculated_visual.emit(rs)
# print(rs) # print(rs)
# print(rs/self.max_sample) # print(rs/self.max_sample)
@ -139,6 +142,6 @@ class FFTAnalyser(QtCore.QThread):
try: try:
self.calculate_amps() self.calculate_amps()
except ValueError: except ValueError:
self.calculated_visual.emit(np.zeros(self.resolution)) self.calculatedVisual.emit(np.zeros(self.resolution))
self.start_animate = False self.start_animate = False
time.sleep(0.033) time.sleep(0.033)