Claude-skill-registry eqapo-format-expert
Expert in EqualizerAPO configuration file format, parsing, and generation. Use when implementing EAPO config import/export, adding support for new filter types, or debugging config file issues.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/eqapo-format-expert" ~/.claude/skills/majiayu000-claude-skill-registry-eqapo-format-expert && rm -rf "$T"
skills/data/eqapo-format-expert/SKILL.mdEqualizerAPO Format Expert
Specialized agent for working with EqualizerAPO configuration files, ensuring correct parsing and generation of
.txt config files.
EqualizerAPO Overview
EqualizerAPO is a parametric equalizer for Windows that processes system audio via APO (Audio Processing Objects) framework.
- Config Location:
C:\Program Files\EqualizerAPO\config\config.txt - Format: Plain text with line-based commands
- Real-time: Changes apply immediately when file is saved
- Channels: Supports per-channel processing (L, R, C, SUB, etc.)
Config File Format
Basic Structure
# Comment lines start with # Preamp: -5.0 dB Filter: ON PK Fc 1000 Hz Gain 3.0 dB Q 1.41 Filter: ON LS Fc 80 Hz Gain -2.5 dB Q 0.71 Filter: ON HS Fc 10000 Hz Gain 4.0 dB Q 0.71
Filter Types Supported by EQAPO GUI
| Type | EAPO Code | Description | Parameters |
|---|---|---|---|
| Peaking | | Bell curve EQ | Fc, Gain, Q |
| Low Shelf | | Bass adjustment | Fc, Gain, Q |
| High Shelf | | Treble adjustment | Fc, Gain, Q |
Additional Filter Types (Not Yet Implemented)
| Type | EAPO Code | Description |
|---|---|---|
| Low Pass | | Cuts high frequencies |
| High Pass | | Cuts low frequencies |
| Band Pass | | Passes only a frequency range |
| Notch | | Cuts a specific frequency |
| All Pass | | Affects phase, not magnitude |
Preamp Syntax
Preamp: <value> dB
Examples:
Preamp: -5.0 dB Preamp: 3 dB Preamp: 0 dB
Rules:
- Must be on its own line
- Value can be integer or float
- Unit "dB" required
- Negative values reduce volume (prevent clipping)
- Typical range: -20 to +20 dB
Filter Syntax
Filter: <ON|OFF> <TYPE> Fc <frequency> Hz Gain <gain> dB Q <q_factor>
Examples:
Filter: ON PK Fc 1000 Hz Gain 3.0 dB Q 1.41 Filter: ON LS Fc 80 Hz Gain -2.5 dB Q 0.71 Filter: OFF HS Fc 10000 Hz Gain 4.0 dB Q 0.71
Rules:
orON
state (case-insensitive)OFF- Filter type:
,PK
,LS
, etc.HS - Frequency:
(20-20000 typical)Fc <value> Hz - Gain:
(can be negative)Gain <value> dB - Q factor:
(0.1-30 typical)Q <value>
Channel-Specific Filters
Channel: L Filter: ON PK Fc 1000 Hz Gain 3.0 dB Q 1.41 Channel: R Filter: ON PK Fc 1000 Hz Gain 2.0 dB Q 1.41 Channel: ALL
Not yet supported in EQAPO GUI - applies filters to all channels globally.
Parsing EqualizerAPO Files
Parser Implementation (TypeScript)
export interface ParsedEapoConfig { preamp: number; bands: ParametricBand[]; } export function parseEapoConfig(content: string): ParsedEapoConfig { const lines = content.split('\n').map((line) => line.trim()); let preamp = 0; const bands: ParametricBand[] = []; for (const line of lines) { // Skip comments and empty lines if (line.startsWith('#') || line === '') continue; // Parse preamp if (line.startsWith('Preamp:')) { const match = line.match(/Preamp:\s*([-+]?\d+\.?\d*)\s*dB/i); if (match) { preamp = parseFloat(match[1]); } continue; } // Parse filter if (line.startsWith('Filter:')) { const band = parseFilterLine(line); if (band) { bands.push(band); } } } return { preamp, bands }; } function parseFilterLine(line: string): ParametricBand | null { // Extract state (ON/OFF) const stateMatch = line.match(/Filter:\s*(ON|OFF)/i); if (!stateMatch || stateMatch[1].toUpperCase() === 'OFF') { return null; // Skip disabled filters } // Extract filter type const typeMatch = line.match(/(PK|LS|HS|LP|HP|BP|NO|AP)/i); if (!typeMatch) return null; const filterType = normalizeFilterType(typeMatch[1].toUpperCase()); // Extract frequency const freqMatch = line.match(/Fc\s+([\d.]+)\s*Hz/i); if (!freqMatch) return null; const frequency = parseFloat(freqMatch[1]); // Extract gain const gainMatch = line.match(/Gain\s+([-+]?[\d.]+)\s*dB/i); if (!gainMatch) return null; const gain = parseFloat(gainMatch[1]); // Extract Q factor const qMatch = line.match(/Q\s+([\d.]+)/i); if (!qMatch) return null; const qFactor = parseFloat(qMatch[1]); // Validate if (!isValidBand(frequency, gain, qFactor)) { return null; } return { filterType, frequency, gain, qFactor }; } function normalizeFilterType(type: string): FilterType { switch (type) { case 'PK': case 'PEAKING': return 'Peaking'; case 'LS': case 'LOWSHELF': return 'LowShelf'; case 'HS': case 'HIGHSHELF': return 'HighShelf'; default: throw new Error(`Unsupported filter type: ${type}`); } } function isValidBand(frequency: number, gain: number, qFactor: number): boolean { return ( frequency >= 20 && frequency <= 20000 && gain >= -30 && gain <= 30 && qFactor >= 0.01 && qFactor <= 100 ); }
Edge Cases in Parsing
-
Case Insensitivity
filter: on pk fc 1000 hz gain 3.0 db q 1.41 ✓ FILTER: ON PK FC 1000 HZ GAIN 3.0 DB Q 1.41 ✓ Filter: ON PK Fc 1000 Hz Gain 3.0 dB Q 1.41 ✓ -
Extra Whitespace
Filter: ON PK Fc 1000 Hz Gain 3.0 dB Q 1.41 ✓ -
Integer vs Float
Filter: ON PK Fc 1000 Hz Gain 3 dB Q 1.41 ✓ Filter: ON PK Fc 1000.0 Hz Gain 3.0 dB Q 1.41 ✓ -
Negative Gains
Filter: ON PK Fc 1000 Hz Gain -3.0 dB Q 1.41 ✓ Filter: ON LS Fc 80 Hz Gain -6 dB Q 0.71 ✓ -
Comments Mid-Line (Not standard, but seen in wild)
Filter: ON PK Fc 1000 Hz Gain 3.0 dB Q 1.41 # Boost presence
Generating EqualizerAPO Files
Writer Implementation (Rust)
pub fn write_eapo_config( path: &Path, bands: &[ParametricBand], preamp: f32, ) -> Result<(), std::io::Error> { let mut content = String::new(); // Header comment content.push_str("# Generated by EQAPO GUI\n"); content.push_str(&format!("# Generated: {}\n\n", chrono::Local::now().format("%Y-%m-%d %H:%M:%S"))); // Preamp content.push_str(&format!("Preamp: {:.1} dB\n", preamp)); // Filters for band in bands { let filter_line = format!( "Filter: ON {} Fc {} Hz Gain {:.1} dB Q {:.2}\n", filter_type_to_code(&band.filter_type), band.frequency as u32, band.gain, band.q_factor ); content.push_str(&filter_line); } // Write to file std::fs::write(path, content)?; Ok(()) } fn filter_type_to_code(filter_type: &FilterType) -> &'static str { match filter_type { FilterType::Peaking => "PK", FilterType::LowShelf => "LS", FilterType::HighShelf => "HS", } }
Output Format Example
# Generated by EQAPO GUI # Generated: 2026-01-04 15:30:00 Preamp: -3.5 dB Filter: ON PK Fc 1000 Hz Gain 3.0 dB Q 1.41 Filter: ON LS Fc 80 Hz Gain -2.5 dB Q 0.71 Filter: ON HS Fc 10000 Hz Gain 4.0 dB Q 0.71
Formatting Rules:
- Frequency: Integer (no decimal places)
- Gain: 1 decimal place
- Q factor: 2 decimal places
- Consistent spacing
- One filter per line
Advanced EqualizerAPO Features
Include Directive
Include: subwoofer_eq.txt Include: headphone_compensation.txt
Loads another config file at that position.
Copy Filter
Copy: L=L+0.5*R R=R+0.5*L
Mixes channels (crossfeed for headphones).
Delay
Delay: L=0 R=2.5
Delays right channel by 2.5ms (speaker positioning).
Convolution (Impulse Response)
Convolution: room_correction.wav
Applies FIR filter from WAV file (room correction).
None of these are supported in EQAPO GUI yet - future features.
File Permissions
Windows UAC Challenges
EqualizerAPO's default config location requires admin rights:
C:\Program Files\EqualizerAPO\config\config.txt
Solutions:
-
Live Config (Recommended)
C:\Users\<Username>\Documents\EQAPO GUI\live_config.txtThen use EqualizerAPO's
directive in main config:Include:Include: C:\Users\<Username>\Documents\EQAPO GUI\live_config.txt -
Run as Admin (Not recommended)
- Tauri app requests elevation
- Security risk
- UAC prompt every time
Permission Check (Rust)
pub fn can_write_to_eapo_config(path: &Path) -> bool { // Try to open file for writing std::fs::OpenOptions::new() .write(true) .create(false) .open(path) .is_ok() } pub fn get_recommended_config_path() -> PathBuf { if can_write_to_eapo_config(&get_default_config_path()) { get_default_config_path() } else { get_live_config_path() } }
Validation
Pre-Write Validation
function validateEapoConfig(bands: ParametricBand[], preamp: number): string[] { const errors: string[] = []; // Check preamp if (preamp < -20 || preamp > 20) { errors.push(`Preamp ${preamp} dB exceeds typical range (-20 to +20 dB)`); } // Check band count if (bands.length > 32) { errors.push(`Too many bands (${bands.length}). EqualizerAPO supports max 32.`); } // Check each band bands.forEach((band, i) => { if (band.frequency < 20 || band.frequency > 20000) { errors.push(`Band ${i + 1}: Frequency ${band.frequency} Hz out of range (20-20000 Hz)`); } if (band.gain < -30 || band.gain > 30) { errors.push(`Band ${i + 1}: Gain ${band.gain} dB exceeds typical range (-30 to +30 dB)`); } if (band.qFactor < 0.1 || band.qFactor > 30) { errors.push(`Band ${i + 1}: Q factor ${band.qFactor} out of range (0.1-30)`); } }); return errors; }
Testing
Parser Test Cases
describe('EAPO Parser', () => { it('should parse basic config', () => { const config = ` Preamp: -5.0 dB Filter: ON PK Fc 1000 Hz Gain 3.0 dB Q 1.41 `; const result = parseEapoConfig(config); expect(result.preamp).toBe(-5.0); expect(result.bands).toHaveLength(1); expect(result.bands[0].frequency).toBe(1000); }); it('should skip disabled filters', () => { const config = ` Filter: ON PK Fc 1000 Hz Gain 3.0 dB Q 1.41 Filter: OFF PK Fc 2000 Hz Gain 6.0 dB Q 1.41 `; const result = parseEapoConfig(config); expect(result.bands).toHaveLength(1); }); it('should handle case insensitivity', () => { const config = `FILTER: on pk fc 1000 hz gain 3.0 db q 1.41`; const result = parseEapoConfig(config); expect(result.bands[0].filterType).toBe('Peaking'); }); });
Common Issues
-
❌ Missing "dB" Unit
Preamp: -5 # WRONG: Missing unit Preamp: -5 dB # CORRECT -
❌ Wrong Filter Code
Filter: ON Peaking Fc 1000 Hz ... # WRONG: Use "PK" Filter: ON PK Fc 1000 Hz ... # CORRECT -
❌ Missing Fc Keyword
Filter: ON PK 1000 Hz ... # WRONG Filter: ON PK Fc 1000 Hz ... # CORRECT -
❌ Comma as Decimal Separator
Filter: ON PK Fc 1000 Hz Gain 3,0 dB Q 1,41 # WRONG (European notation) Filter: ON PK Fc 1000 Hz Gain 3.0 dB Q 1.41 # CORRECT
Reference Materials
- Full EqualizerAPO specificationreferences/eapo_spec.md
- All supported filter typesreferences/filter_types.md
- Real-world config file examplesreferences/examples.md