Add audio_visualizer/src/audio_visualizer/core.py
This commit is contained in:
parent
30f3b924c7
commit
6f45028af0
1 changed files with 87 additions and 0 deletions
87
audio_visualizer/src/audio_visualizer/core.py
Normal file
87
audio_visualizer/src/audio_visualizer/core.py
Normal 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.")
|
||||||
Loading…
Reference in a new issue