Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions PROJECT_CONTEXT.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,14 @@ EchoPy is a real-time music visualizer built with Python, PySide6, and NumPy. It
- **NumPy 2.0 Compatibility**: The system uses NumPy 2.4.1.
- **Optimization**: `AudioProcessor` callback has been refactored for vectorized Boolean masking to avoid performance bottlenecks (Input Overflow).

## Current State (Updated 2026-01-28)
## Current State (Updated 2026-02-20)

- **Logic**: Fully optimized for NumPy 2.0.
- **Audio Capture**: IMPROVED.
- Integrated **Weighted Multichannel Downmixing** (inspired by CAVA) to preserve surround audio fidelity on NVIDIA SyncMaster/HDMI drivers.
- Enhanced **WASAPI Loopback Discovery** with name-matching and "SyncMaster" prioritization.
- **Visuals**: Superior 'liquid' movement achieved via **CavaFilter** (Integral + Fall-off filters), replacing simple EMA smoothing.
- **Visuals**: Superior 'liquid' movement achieved via **CavaFilter** (Integral + Fall-off filters) tuned for elasticity.
- Glassmorphism UI enhanced with deeper transparencies and vibrant glow effects (Spectrum/Circular).
- **Calibration**: `NOISE_FLOOR = 0.00020` and `GAIN = 15000` maintained for clean response.

## Advanced Deployment (Frozen App Strategy)
Expand Down
30 changes: 19 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,21 @@
1. **Modern** - Indigo to Cyan gradients (Premium default)
2. **Cyberpunk** - High-contrast Neon Pink & Blue
3. **Aurora** - Northern Lights inspired (Green/Blue) [NEW]
4. **Aesthetic** - Soft pastel colors
5. **Classic** - Retro green monochrome
6. **Fire** - intense Red to yellow flame colors
7. **Ocean** - Deep blue to cyan waves
8. **Sunset** - Warm Orange and Purple hues
9. **Neon** - Bright multi-color spectrum
10. **Rainbow** - Full ROYGBIV spectrum
4. **Spectre** - Ultra-violet to Cyan neon [NEW]
5. **Aesthetic** - Soft pastel colors
6. **Classic** - Retro green monochrome
7. **Fire** - intense Red to yellow flame colors
8. **Ocean** - Deep blue to cyan waves
9. **Sunset** - Warm Orange and Purple hues
10. **Neon** - Bright multi-color spectrum
11. **Rainbow** - Full ROYGBIV spectrum

### 🎛️ Advanced Features

- 🪟 **Frameless & Translucent** - True "Glass" transparent backgrounds overlapping your desktop
- 🖼️ **Custom backgrounds** - Persistent background loading
- 🎚️ **Audio device selection** - Choose input source
- ⚙️ **Configurable settings** - Adjust smoothing, sample rate, FFT size
- ⚙️ **Configurable settings** - Adjust smoothing, sample rate, FFT size, and Gain in real-time
- 🖥️ **Fullscreen mode** - Immersive experience (F11)
- 💾 **Settings persistence** - Robust saving to AppData
- 📊 **Real-time performance** - 60 FPS smooth rendering
Expand Down Expand Up @@ -111,13 +113,19 @@ python src/main.py

- `F11` - Toggle fullscreen
- `Ctrl+H` - Show/hide control panel
- `Ctrl+V` - Cycle Visualization Style
- `Ctrl+T` - Cycle Color Theme
- `Ctrl+,` - Open settings
- `Ctrl+Q` - Quit application
- `S` - Take Screenshot
- `Ctrl+M` - Minimize application
- `Ctrl+X` - Quit application
- `ESC` - Exit fullscreen

### ️ Mouse Controls
### 🖱️ Mouse Controls

- **Right-Click** anywhere to open the **Main Menu** (Settings, Toggle Controls, Fullscreen, Exit).
- **Left-Click & Drag** anywhere on the visualizer to move the frameless window freely.
- **Hover Edges** to dynamically resize the application window.
- *(Note: Right-click context menu is intentionally disabled in this version. Please rely on the keyboard shortcuts above to access settings and controls).*

## 📦 Building Executables

Expand Down
157 changes: 157 additions & 0 deletions docs/RECOMENDACIONES_MEJORA.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
# Recomendaciones de mejora para EchoPy (UX, fluidez, diseño y refactorización)

## Resumen ejecutivo

EchoPy ya tiene una base sólida: arquitectura por capas, sistema de estilos extensible con `BaseVisualizer` + `VisualizerFactory`, y separación aceptable entre captura de audio y renderizado. Las mejoras con mayor impacto están en tres frentes:

1. **Fluidez perceptual**: reducir jitter y coste por frame en el render.
2. **UI moderna y coherente**: mejorar consistencia visual, ergonomía y microinteracciones.
3. **Refactor estructural**: reducir responsabilidades en `MainWindow`/`VisualizerWidget` y aislar configuración/estado de sesión.

---

## 1) Fluidez de visualización (prioridad alta)

### 1.1 Cachear operaciones de pintura costosas
- El fondo se escala en cada `paintEvent` (`QPixmap.scaled`), lo cual es caro cuando hay resize o FPS altos.
- **Mejora**: cachear una versión escalada del fondo y regenerarla solo en `resizeEvent` o cuando cambie imagen/opacidad.
- **Impacto**: menor uso de CPU/GPU y menos stutter en estilos complejos.

### 1.2 Reducir trabajo por frame en visualizadores con `QPainterPath`
- Algunos estilos construyen paths largos cada frame (p. ej. `Waveform`).
- **Mejora**:
- Precalcular coordenadas X (vector fijo por ancho de widget).
- Downsampling adaptativo (según FPS real, no fijo).
- Evitar recrear gradientes/brushes si no cambian tema ni tamaño.
- **Impacto**: frame-time más estable bajo audio intenso.

### 1.3 Métricas de performance en runtime
- Ya existe `DebugOverlay`; se puede explotar para telemetría de render.
- **Mejora**: medir `frame_time_ms`, `audio_callback_time_ms`, `dropped_frames` y mostrar semáforo de salud.
- **Impacto**: permite tuning de parámetros y profiling en producción.

### 1.4 Control de VSync/FPS más robusto
- El timer usa intervalos discretos (`1000 // fps`) y puede introducir jitter.
- **Mejora**: usar `QElapsedTimer` para delta-time estable y compensación del loop; mantener `QTimer` solo como trigger base.
- **Impacto**: animaciones más suaves, especialmente en 120Hz/144Hz.

---

## 2) UI/UX más moderna y atractiva (prioridad alta)

### 2.1 Sistema de diseño unificado (tokens)
- Hoy hay estilos embebidos en QSS y CSS inline en widgets.
- **Mejora**: definir Design Tokens centralizados (radio, spacing, elevación, colores semánticos, tipografía) y generar QSS desde esos tokens.
- **Impacto**: coherencia visual, mantenimiento más simple y theming más premium.

### 2.2 Panel de controles contextual y no intrusivo
- El `ControlPanel` es flotante tipo tool window, útil pero algo rígido.
- **Mejora**:
- Modo dockable + modo overlay compacto.
- Auto-hide inteligente en fullscreen.
- Mini panel quick-actions (tema, estilo, sensibilidad).
- **Impacto**: mejor experiencia para uso continuo en modo visualización.

### 2.3 Microinteracciones visuales
- **Mejora**:
- Transiciones cortas (150–250 ms) en hover, focus, toggle.
- Estados vacíos/onboarding para “sin señal” o “sin dispositivo”.
- Indicadores de nivel de entrada en tiempo real dentro de settings.
- **Impacto**: percepción de app más moderna, viva y profesional.

### 2.4 Accesibilidad y legibilidad
- **Mejora**:
- Contraste WCAG AA para textos secundarios.
- Escala tipográfica consistente (12/14/16/20).
- Navegación por teclado más explícita (focus ring visible).
- **Impacto**: mayor usabilidad en diferentes condiciones de pantalla.

---

## 3) Patrones de diseño y refactorización (prioridad media/alta)

### 3.1 Reducir responsabilidades de `MainWindow`
- Actualmente coordina UI, audio, configuración, estado y acciones.
- **Refactor recomendado**:
- `AppController` (orquestación global)
- `SettingsService` (persistencia y validación)
- `AudioSessionService` (arranque/parada/cambio de dispositivo)
- **Impacto**: menor acoplamiento y mayor testabilidad.

### 3.2 Separar “estado de sesión” de widgets
- El estado operativo vive disperso (config + widget + audio).
- **Mejora**: introducir `AppState` (dataclass inmutable por snapshots + events), con suscripciones desde UI.
- **Impacto**: facilita depuración, undo básico de ajustes y future-proof para plugins.

### 3.3 Estrategia de render por estilo
- Ya existe base abstracta de visualizadores (muy bien).
- **Mejora**: interfaz opcional `prepare_frame(context)` + `render_frame(painter)` para desacoplar cálculo y dibujo.
- **Impacto**: posibilita paralelizar/precalcular en estilos pesados.

### 3.4 Registro de estilos por plugin discovery
- La factory actual usa registro estático.
- **Mejora**: carga dinámica de estilos por entry points (o carpeta plugins), con metadata (coste estimado, tags, preview).
- **Impacto**: extensibilidad real sin tocar core.

---

## 4) Calidad técnica y robustez (prioridad media)

### 4.1 Manejo de excepciones más específico
- Hay varios `except:` genéricos.
- **Mejora**: capturar excepciones concretas y normalizar errores de audio con códigos/causas.
- **Impacto**: mejor diagnóstico y menos silencios peligrosos.

### 4.2 Imports y empaquetado
- Se usa `sys.path.insert` en `main.py`.
- **Mejora**: ejecutar como paquete (`python -m src.main`) y migrar a imports absolutos de paquete.
- **Impacto**: despliegue más limpio y menos fragilidad por rutas.

### 4.3 Test de rendimiento y regresión visual
- **Mejora**:
- Benchmarks de callback de audio (tiempo medio/p95).
- Snapshot tests de estilos clave con entradas sintéticas.
- Smoke tests de cambio de estilo/tema/dispositivo.
- **Impacto**: evita degradaciones al iterar en efectos visuales.

---

## 5) Plan propuesto por fases

### Fase 1 (1–2 semanas, quick wins)
1. Cache de fondo escalado + cache de gradientes por tamaño/tema.
2. Telemetría de frame-time/audio-time en overlay.
3. Limpieza de `except:` genéricos en módulos críticos.
4. Tokenizar QSS base (colores, radios, spacing).

### Fase 2 (2–4 semanas)
1. Extraer `AppController` y `SettingsService`.
2. Introducir `AppState` y evento de cambios.
3. Mejorar panel de control (dockable + quick-actions).
4. Implementar pruebas smoke + benchmark base.

### Fase 3 (4+ semanas)
1. Plugin discovery de visualizadores.
2. Pipeline `prepare_frame/render_frame` para estilos avanzados.
3. Galería de presets (tema + estilo + sensibilidad + FPS).

---

## 6) Top 10 recomendaciones accionables (ordenadas)

1. Cachear fondo escalado y recursos de dibujo por tamaño.
2. Introducir métricas de frame-time y callback-time en overlay.
3. Separar `MainWindow` en controller + servicios.
4. Unificar estilos con design tokens en QSS.
5. Implementar downsampling adaptativo por carga real.
6. Reemplazar imports frágiles por estructura de paquete formal.
7. Mejorar estados de UI (no signal/no device) con UX explícita.
8. Añadir tests de regresión visual y smoke tests de flujo.
9. Preparar arquitectura para plugins externos de visualizadores.
10. Crear presets y quick-actions para personalización rápida.

---

## Cierre

EchoPy ya transmite una base técnica muy buena para su categoría. Si priorizas **fluidez + coherencia visual + separación de responsabilidades**, el salto de calidad será muy visible sin reescribir toda la app.
46 changes: 24 additions & 22 deletions resources/modern.qss
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ QMainWindow {

/* Glassmorphism effect for panels and dialogs */
QWidget#ControlPanel, QDialog {
background-color: #121212;
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 16px;
background-color: rgba(18, 18, 18, 0.85); /* Mayor transparencia */
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 20px; /* Bordes más redondeados */
}

QLabel {
Expand All @@ -29,31 +29,33 @@ QPushButton {

QPushButton:hover {
background-color: #2A2A2A;
border-color: #6C5CE7; /* Indigo Accent */
color: #FFFFFF;
border-color: #7A5FFF; /* Indigo Accent */
color: #00E5FF; /* Cyan resaltado */
}

QPushButton:pressed {
background-color: #151515;
}

QPushButton:checked {
background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #6C5CE7, stop:1 #00CEC9);
color: #FFFFFF;
background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #7A5FFF, stop:1 #00E5FF);
color: #000000;
border: none;
font-weight: bold;
}

QComboBox, QSpinBox {
background-color: #1E1E1E;
border: 1px solid #333;
border-radius: 6px;
background-color: rgba(30, 30, 30, 0.7);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 8px;
padding: 6px 12px;
color: #E0E0E0;
selection-background-color: #6C5CE7;
selection-background-color: #7A5FFF;
}

QComboBox:hover, QSpinBox:hover {
border-color: #00CEC9;
border-color: #00E5FF;
background-color: rgba(40, 40, 40, 0.9);
}

QComboBox::drop-down {
Expand All @@ -79,12 +81,12 @@ QSlider::groove:horizontal {
}

QSlider::handle:horizontal {
background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #6C5CE7, stop:1 #00CEC9);
border: 1px solid rgba(255,255,255,0.2);
width: 16px;
height: 16px;
margin: -6px 0;
border-radius: 8px;
background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #7A5FFF, stop:1 #00E5FF);
border: 1px solid rgba(255,255,255,0.4);
width: 18px;
height: 18px;
margin: -7px 0;
border-radius: 9px;
}

QSlider::handle:horizontal:hover {
Expand All @@ -93,12 +95,12 @@ QSlider::handle:horizontal:hover {
}

QGroupBox {
border: 1px solid rgba(255, 255, 255, 0.05);
border-radius: 12px;
margin-top: 20px;
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 14px;
margin-top: 22px;
padding-top: 15px;
font-weight: bold;
color: #00CEC9; /* Cyan Accent Title */
color: #00E5FF; /* Cyan Accent Title */
}

QGroupBox::title {
Expand Down
Loading