Add audio_visualizer/src/audio_visualizer/core.py

This commit is contained in:
Mika 2026-02-08 03:06:31 +00:00
parent 30f3b924c7
commit 6f45028af0

View file

@ -0,0 +1,87 @@
from __future__ import annotations
import logging
from pathlib import Path
from typing import Optional
import numpy as np
import matplotlib.pyplot as plt
from audio_visualizer.io_utils import load_audio_data
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
if not logger.handlers:
handler = logging.StreamHandler()
formatter = logging.Formatter('[%(levelname)s] %(asctime)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
class Visualizer:
"""Verwaltet die Darstellung und Aktualisierung der Visualisierung des Frequenzspektrums."""
def __init__(self, output_path: Optional[str] = None) -> None:
self.output_path = Path(output_path) if output_path else None
def render(self, spectrum: np.ndarray) -> None:
"""Rendert das aktuelle Spektrum als grafische Darstellung."""
logger.info("Starte Rendering des Spektrums …")
if spectrum.ndim != 1:
raise ValueError("Spektrum muss eindimensional sein.")
plt.figure(figsize=(10, 6))
plt.plot(spectrum, color='royalblue', linewidth=1.2)
plt.title('Frequenzspektrum Echo der Wellen')
plt.xlabel('Frequenzindex')
plt.ylabel('Amplitude')
plt.grid(True, linestyle='--', alpha=0.5)
if self.output_path:
self.output_path.parent.mkdir(parents=True, exist_ok=True)
plt.savefig(self.output_path, dpi=150)
logger.info(f"Visualisierung gespeichert unter: {self.output_path}")
else:
plt.show()
plt.close()
logger.info("Rendering abgeschlossen.")
def compute_spectrum(data: np.ndarray) -> np.ndarray:
"""Berechnet die Frequenzspektralanalyse aus Rohdaten."""
logger.info("Berechne Spektrum …")
if not isinstance(data, np.ndarray):
raise TypeError("Eingabedaten müssen ein numpy.ndarray sein.")
if data.size == 0:
raise ValueError("Eingabedaten sind leer.")
# Überprüfung auf NaNs
if np.isnan(data).any():
logger.warning("Eingabedaten enthalten NaN-Werte; werden durch 0 ersetzt.")
data = np.nan_to_num(data)
spectrum = np.abs(np.fft.rfft(data - np.mean(data)))
logger.debug(f"Spektrum berechnet, Länge: {len(spectrum)}")
return spectrum
def generate_visualization(audio_file: str, output_file: Optional[str] = None) -> None:
"""Erzeugt eine visuelle Darstellung der Audiofrequenzen aus einer Eingabedatei."""
logger.info(f"Starte Visualisierung für Datei: {audio_file}")
input_path = Path(audio_file)
assert input_path.exists(), f"Eingabedatei existiert nicht: {audio_file}"
# Eingabedaten laden
data = load_audio_data(str(input_path))
assert isinstance(data, np.ndarray) and data.size > 0, "Geladene Daten sind ungültig oder leer."
# Spektrum berechnen
spectrum = compute_spectrum(data)
# Visualisierung ausgeben
visualizer = Visualizer(output_file)
visualizer.render(spectrum)
logger.info("Visualisierung erfolgreich abgeschlossen.")