- Introduced .python-version for Python version management. - Added AGENTS.md for documentation on agent usage and best practices. - Created alembic.ini for database migration configurations. - Implemented main.py as the entry point for the application. - Established pyproject.toml for project dependencies and configurations. - Initialized README.md for project overview. - Generated uv.lock for dependency locking. - Documented milestones and specifications in docs/milestones.md and docs/spec.md. - Created logs/status_line.json for logging status information. - Added initial spike implementations for UI tray hotkeys, audio capture, ASR latency, and encryption validation. - Set up NoteFlow core structure in src/noteflow with necessary modules and services. - Developed test suite in tests directory for application, domain, infrastructure, and integration testing. - Included initial migration scripts in infrastructure/persistence/migrations for database setup. - Established security protocols in infrastructure/security for key management and encryption. - Implemented audio infrastructure for capturing and processing audio data. - Created converters for ASR and ORM in infrastructure/converters. - Added export functionality for different formats in infrastructure/export. - Ensured all new files are included in the repository for future development.
87 lines
2.1 KiB
Python
87 lines
2.1 KiB
Python
"""Audio level computation implementation.
|
|
|
|
Provides RMS and dB level calculation for VU meter display.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import math
|
|
from typing import Final
|
|
|
|
import numpy as np
|
|
from numpy.typing import NDArray
|
|
|
|
|
|
class RmsLevelProvider:
|
|
"""RMS-based audio level provider.
|
|
|
|
Computes RMS (Root Mean Square) level from audio frames for VU meter display.
|
|
"""
|
|
|
|
# Minimum dB value to report (silence threshold)
|
|
MIN_DB: Final[float] = -60.0
|
|
|
|
def get_rms(self, frames: NDArray[np.float32]) -> float:
|
|
"""Calculate RMS level from audio frames.
|
|
|
|
Args:
|
|
frames: Audio samples as float32 array (normalized -1.0 to 1.0).
|
|
|
|
Returns:
|
|
RMS level normalized to 0.0-1.0 range.
|
|
"""
|
|
if len(frames) == 0:
|
|
return 0.0
|
|
|
|
# Calculate RMS: sqrt(mean(samples^2))
|
|
rms = float(np.sqrt(np.mean(frames.astype(np.float64) ** 2)))
|
|
|
|
# Clamp to 0.0-1.0 range
|
|
return min(1.0, max(0.0, rms))
|
|
|
|
def get_db(self, frames: NDArray[np.float32]) -> float:
|
|
"""Calculate dB level from audio frames.
|
|
|
|
Args:
|
|
frames: Audio samples as float32 array (normalized -1.0 to 1.0).
|
|
|
|
Returns:
|
|
Level in dB (MIN_DB to 0 range).
|
|
"""
|
|
rms = self.get_rms(frames)
|
|
|
|
if rms <= 0:
|
|
return self.MIN_DB
|
|
|
|
# Convert to dB: 20 * log10(rms)
|
|
db = 20.0 * math.log10(rms)
|
|
|
|
# Clamp to MIN_DB to 0 range
|
|
return max(self.MIN_DB, min(0.0, db))
|
|
|
|
def rms_to_db(self, rms: float) -> float:
|
|
"""Convert RMS value to dB.
|
|
|
|
Args:
|
|
rms: RMS level (0.0-1.0).
|
|
|
|
Returns:
|
|
Level in dB (MIN_DB to 0 range).
|
|
"""
|
|
if rms <= 0:
|
|
return self.MIN_DB
|
|
|
|
db = 20.0 * math.log10(rms)
|
|
return max(self.MIN_DB, min(0.0, db))
|
|
|
|
def db_to_rms(self, db: float) -> float:
|
|
"""Convert dB value to RMS.
|
|
|
|
Args:
|
|
db: Level in dB.
|
|
|
|
Returns:
|
|
RMS level (0.0-1.0).
|
|
"""
|
|
return 0.0 if db <= self.MIN_DB else 10.0 ** (db / 20.0)
|