#!/usr/bin/env python3 """Test the C++ NAM engine integrated into the pipeline.""" import sys, types, time import numpy as np # Mock tkinter to allow nam package import tk = types.ModuleType('tkinter') tk.Tk = type('MockTk', (), {'__init__': lambda s: None}) sys.modules['tkinter'] = tk sys.path.insert(0, 'src') from dsp.pipeline import AudioPipeline from presets.types import Preset, FXBlock, FXType # Create pipeline p = AudioPipeline() print(f"NAM type: {type(p.nam).__name__}") # Load a NAM model ok = p.nam.load_model('models/nam/clean.nam') print(f"Model loaded: {ok}, is_loaded={p.nam.is_loaded}") if p.nam._engine: print(f" Static: {p.nam._engine.is_static}, SampleRate: {p.nam._engine._sample_rate}") # Test NAM engine directly block = np.sin(2 * np.pi * 440 * np.arange(256) / 48000).astype(np.float32) * 0.3 processed = p.nam.process(block) print(f"NAM direct: in_rms={np.sqrt(np.mean(block**2)):.4f} out_rms={np.sqrt(np.mean(processed**2)):.4f}") # Test through pipeline preset = Preset(name='test', bank=0, program=0, chain=[ FXBlock(fx_type=FXType.NOISE_GATE, enabled=True, params={'threshold': 0.01}), FXBlock(fx_type=FXType.NAM_AMP, enabled=True, params={'level': 0.8, 'gain': 0.5}, nam_model_path='models/nam/clean.nam'), ]) p.load_preset(preset) print(f"Preset loaded: {len(p._chain)} blocks") out = p.process(block) print(f"Pipeline out: in_rms={np.sqrt(np.mean(block**2)):.4f} out_rms={np.sqrt(np.mean(out**2)):.4f}") # Benchmark times = [] for _ in range(500): t0 = time.perf_counter() p.process(block) times.append((time.perf_counter() - t0) * 1000) print(f"Pipeline avg: {np.mean(times):.3f} ms, max: {np.max(times):.3f} ms, min: {np.min(times):.3f} ms") print(f"VU meter: input={p._input_level:.4f} output={p._output_level:.4f}") p.nam.unload() print("SUCCESS")