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