Matlab Evaluate Acoustic Metrics
MathWorksOfficialCreated by MathWorks
- Skill
- Tool integration
- Science and research
- BSD-2-Clause
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
This skill provides a structured approach to using MATLAB Audio Toolbox for acoustic measurement and analysis. It guides users through selecting the correct functions for psychoacoustic metrics, speech intelligibility, noise compliance, and broadcast loudness. The skill emphasizes proper calibration techniques, standard-compliant workflows, and the correct handling of signal data to ensure accurate results, while explicitly warning against the use of nonexistent or licensed-restricted functions.
What it does
- Calculates psychoacoustic metrics like loudness, sharpness, roughness, and fluctuation strength.
- Evaluates speech quality and intelligibility using metrics such as ViSQOL, STOI, STI, and SII.
- Assesses noise compliance using NC, RC, and RNC ratings for various environments.
- Performs offline SPL measurements and broadcast loudness checks (EBU R 128).
- Provides guidance on microphone calibration and system-level calibration factors.
- Offers standard-compliant filtering and unit conversion utilities.
When to use it
- When you need to measure perceived loudness or sound quality in a research or engineering context.
- When evaluating room acoustics or HVAC noise compliance against industry standards.
- When analyzing speech intelligibility for communication systems or public address setups.
- When you need to calibrate audio recordings for accurate SPL or metric computation.
- When you need to perform broadcast loudness compliance checks.
Advantages
- Ensures adherence to international standards like ISO 532-1/2, ANSI/ASA S12.2, and IEC 60268-16.
- Prevents common errors such as incorrect function usage, argument ordering, or manual implementation of complex algorithms.
- Provides clear guidance on calibration to ensure measurement accuracy.
- Streamlines the selection of appropriate metrics based on specific application goals.
Usage examples
- “How do I calculate the loudness of a recording in sones?”
- The agent will guide you to use the acousticLoudness function, specifying the ISO 532-1 method, applying your calibration factor, and selecting the appropriate sound field.
- “Is my office HVAC noise compliant?”
- The agent will recommend using the roomCriteria function to obtain an RC rating, explaining how to interpret the output and verify the measurement conditions.
- “How can I measure the speech quality of a processed audio file?”
- The agent will instruct you to use the visqol function with the 'speech' mode, ensuring the processed signal is passed as the first argument.
- “How do I calibrate my microphone for SPL measurements?”
- The agent will explain how to use calibrateMicrophone with a 1 kHz tone recording and a known SPL reference to compute the correct calibration factor.
Install
Download the skill as a ZIP:
https://autogineer.com/agent-skills/matlab/matlab-evaluate-acoustic-metrics/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip matlab-evaluate-acoustic-metrics.zip -d .agents/skills
Documentation by MathWorks
Evaluate Acoustic Metrics
Select the correct Audio Toolbox function for acoustic measurement, apply proper calibration, and choose appropriate standards — instead of reimplementing algorithms or calling nonexistent functions.
When to Use
Computing psychoacoustic metrics (loudness, sharpness, roughness, fluctuation)
Evaluating speech quality or intelligibility (ViSQOL, STOI, STI, SII)
Assessing noise compliance (NC rating, RC rating, RNC, SIL)
Measuring SPL from recordings (offline, calibrated)
Computing broadcast loudness (EBU R 128 / LUFS)
Measuring reverberation time (RT60) from impulse responses
Detecting tonal content (tone-to-noise ratio, prominence ratio)
Converting microphone sensitivity to CalibrationFactor
User mentions PESQ or POLQA (redirect to correct alternatives)
When NOT to Use
Real-time streaming audio processing loops — use
matlab-process-streaming-audioAudio device I/O, recording, or live
calibrateMicrophone— usematlab-play-record-audioAudio plugin authoring (VST/AU) — use
matlab-write-audio-pluginGeneral filter design unrelated to measurement — use
matlab-design-digital-filterSpatial audio / HRTF / SOFA processing
Workflow
Follow this decision tree to route the user's goal to the right function:
1. Identify the measurement goal
| Goal | Category | Go to |
|---|---|---|
| "How loud is it?" (perceived) | Psychoacoustic | → Psychoacoustic Metrics |
| "Does it comply with broadcast loudness?" | Broadcast | → Broadcast Loudness |
| "Is the noise level acceptable for this space?" | Noise compliance | → Noise Compliance |
| "Can people understand speech in this room?" | Speech intelligibility | → STI/SII Measurement |
| "How good does processed speech sound?" | Speech quality | → Speech Quality |
| "What's the SPL?" | Level measurement | → SPL Measurement |
| "What's the reverberation time?" | Room acoustics | → RT60 |
| "Is there a tonal component?" | Tonality | → Tonality |
2. Ask before computing
Before writing code, confirm these with the user:
Calibration: Do they have a CalibrationFactor? Did they calibrate with
calibrateMicrophone? (See Calibration section)Standard: Which standard or method applies? (ISO 532-1 vs 532-2, NC vs RC vs RNC)
Sound field: Free field or diffuse field recording?
Application context: What space type? What's the concern? (Drives NC vs RC vs RNC selection)
3. Select function and apply
Use the Key Functions table and the category-specific patterns below.
Functions That Do NOT Exist
| Function | Status | Use Instead |
|---|---|---|
pesq | Does NOT exist (proprietary ITU-T P.862 license) | visqol(degraded, reference, fs, Mode="speech") |
polqa | Does NOT exist (proprietary ITU-T P.863 license) | visqol(degraded, reference, fs) |
Never suggest pesq or polqa. They are not in Audio Toolbox and cannot be added due to licensing.
Key Functions
| Function | Purpose | Standard | Available From |
|---|---|---|---|
acousticLoudness | Perceived loudness (sones) | ISO 532-1/2 | R2020a |
acousticSharpness | Perceived sharpness (acum) | DIN 45692 | R2020a |
acousticRoughness | Perceived roughness (asper) | — | R2021a |
acousticFluctuation | Fluctuation strength (vacil) | — | R2020b |
integratedLoudness | Broadcast loudness (LUFS) | EBU R 128 / ITU-R BS.1770 | R2016b |
loudnessMeter | Streaming broadcast loudness meter | EBU R 128 / ITU-R BS.1770 | R2018a |
visqol | Full-reference audio quality (MOS) | — | R2024a |
stoi | Short-time objective intelligibility | — | R2024a |
mnru | Modulated noise reference unit | ITU-T P.810 | R2024a |
dBov | Power level relative to overload (dB) | ITU-T G.100.1 | R2024a |
speechTransmissionIndex | STI from IR or test signals | IEC 60268-16 | R2026a |
speechIntelligibilityIndex | SII from IR, test signals, or levels | ANSI/ASA S3.5-1997 | R2026b |
stipaExcitation | Generate STI/STIPA test signals | IEC 60268-16 | R2026a |
siiExcitation | Generate SII test signals | ANSI/ASA S3.5-1997 | R2026b |
noiseCriteria | NC rating + SIL + spectrum imbalance + rattle risk | ANSI/ASA S12.2 | R2026b |
roomNoiseCriteria | RNC rating (detects surging/fluctuations) | ANSI/ASA S12.2 | R2026b |
roomCriteria | RC Mark II rating (HVAC systems) | ANSI/ASA S12.2 | R2026b |
noiseCriteriaCurves | Look up NC curve values | ANSI/ASA S12.2 | R2026b |
noiseCriteriaRecommendations | Recommended NC levels by room type | ANSI/ASA S12.2 | R2026b |
speechInterferenceLevel | SIL from recording | ANSI/ASA S12.2 | R2026b |
rt60 | Reverberation time from impulse response | ISO 3382-1/2 | R2025a |
acousticToneToNoiseRatio | Detect/quantify tones | ECMA-418-1 | R2023b |
acousticProminenceRatio | Tonality via critical band comparison | ECMA-418-1 | R2023b |
splMeter | SPL measurement (time-weighted, per-band) | IEC 61672 | R2018a |
calibrateMicrophone | Compute calibration factor from known tone | — | R2018b |
weightingFilter | A/C/Z/K frequency weighting | IEC 61672-1 | R2016b |
octaveFilter | Single octave-band filter | ANSI S1.11-2004 | R2017b |
octaveFilterBank | Multi-band octave filtering | ANSI S1.11-2004 | R2019a |
See references/function-arguments.md for complete argument lists, defaults, and valid values for each function — consult when constructing calls with non-default parameters.
Calibration
CalibrationFactor from microphone sensitivity
Convert dB sensitivity (dBV/Pa) to the linear CalibrationFactor:
sensitivity_dBV = -26; % Example: -26 dBV/Pa microphone
calibrationFactor = 1 / 10^(sensitivity_dBV/20);The CalibrationFactor is the 3rd positional argument for acousticLoudness, acousticSharpness, acousticRoughness, and acousticFluctuation (default: sqrt(8)). For noise compliance functions, pass it as a name-value: CalibrationFactor=value.
System-level calibration advice
Always ask the user about their signal chain. If the recording path includes a preamp, audio interface, or ADC with unknown gain, the mic sensitivity spec alone is insufficient. Recommend:
Play a 1 kHz tone through the system and record it through the full signal chain (mic → preamp → ADC → WAV). Use a pistonphone for a known 94 dB reference, or place a physical SPL meter next to the microphone to get an SPL reading.
Compute the system calibration factor:
calibrationFactor = calibrateMicrophone(calRecording, fs, SPLreading, FrequencyWeighting="Z-weighting")Pass that factor to the measurement function
calibrateMicrophone expects a 1 kHz tone recording as input. The SPLreading argument is the known SPL in dB (e.g., 94 from a pistonphone, or the value shown on a physical SPL meter).
Cross-reference: for the physical recording workflow with calibrateMicrophone, see the matlab-play-record-audio skill.
Patterns
Psychoacoustic Metrics
[audioIn, fs] = audioread("recording.wav");
calFactor = 1 / 10^(-26/20);
loudness = acousticLoudness(audioIn, fs, calFactor, ...
Method="ISO 532-1", SoundField="diffuse", TimeVarying=true);
sharpness = acousticSharpness(audioIn, fs, calFactor, ...
SoundField="diffuse", TimeVarying=true);
roughness = acousticRoughness(audioIn, fs, calFactor, SoundField="diffuse");
fluctuation = acousticFluctuation(audioIn, fs, calFactor, SoundField="diffuse");Return types: acousticLoudness returns a scalar (sones) for stationary analysis. With TimeVarying=true, it returns a column vector (time-varying loudness in sones). The second output (specificLoudness) is a matrix (time x critical bands). It does NOT return a struct or timetable.
Ask the user:
ISO 532-1 (Zwicker, stationary/time-varying) or ISO 532-2 (Moore-Glasberg)?
Free-field or diffuse-field recording?
Time-varying analysis needed?
See references/psychoacoustic-metrics.md for method selection guidance (ISO 532-1 vs 532-2), interpretation tables (sone values, sharpness/roughness/fluctuation scales), tonality metric selection, and combined sound quality assessment workflows.
Unit Conversions
Use built-in functions — do NOT reimplement conversion formulas manually:
| Conversion | Function | Method selection |
|---|---|---|
| phon → sone | phon2sone(phon, standard) | "ISO 532-1" (default), "ISO 532-2" |
| sone → phon | sone2phon(sone, standard) | "ISO 532-1" (default), "ISO 532-2" |
| Hz → ERB | hz2erb(freq) | Single formula (no variants) |
| ERB → Hz | erb2hz(erb) | Single formula (no variants) |
| Hz → bark | hz2bark(freq) | Single formula (no variants) |
| bark → Hz | bark2hz(bark) | Single formula (no variants) |
| Hz → mel | hz2mel(freq, MelStyle=s) | "oshaughnessy" (default), "slaney" |
| mel → Hz | mel2hz(mel, MelStyle=s) | "oshaughnessy" (default), "slaney" |
When the user specifies a standard (e.g., "ISO 532-2"), pass it as the second positional argument for phon2sone/sone2phon. For hz2mel/mel2hz, use the MelStyle name-value pair.
Noise Compliance
Choose the function based on the application:
| Situation | Function | Why |
|---|---|---|
| General background noise rating | noiseCriteria | Standard NC curves (ANSI/ASA S12.2) |
| HVAC system noise specifically | roomCriteria | RC Mark II designed for HVAC evaluation |
| Noise with audible surging/fluctuation | roomNoiseCriteria | RNC penalizes time-varying noise (requires ≥15 s recording) |
| Quick speech interference check | speechInterferenceLevel | Direct SIL value |
| Need recommended levels for room type | noiseCriteriaRecommendations | Lookup table by room use |
[audioIn, fs] = audioread("office_noise.wav");
[NC, SIL, specImbalance, rattleRisk] = noiseCriteria(audioIn, fs, ...
CalibrationFactor=2.3);
[RC, LMF, QAI, rattleRisk] = roomCriteria(audioIn, fs, ...
CalibrationFactor=2.3);
SIL = speechInterferenceLevel(audioIn, fs, CalibrationFactor=2.3);
rec = noiseCriteriaRecommendations("NC", Occupancy="all");Return types:
NCis a string (e.g.,"NC-35"or"NC-56 (1000 Hz)"if a band exceeds)RCis a string (e.g.,"RC-32(N)"— the letter indicates spectrum quality: N/R/H/RV)SILandLMFare double scalars (dB)QAIis a double scalar (dB; 0 = ideal neutral)specImbalanceandrattleRiskare structs with.Summary(string) and.Details(table) — access.Summaryfor display. Exception:specImbalancedegrades to acharscalar (not a struct) when NC exceeds the curve range (e.g., "Above NC-70") or falls below NC-15. Guard withisstruct(specImbalance)before dot-indexing.noiseCriteriaRecommendationsrequires a criteria name argument:"NC","RNC", or"RC"
Ask the user:
What type of space? (office, classroom, hospital, concert hall)
Is the noise source HVAC? → prefer
roomCriteriaIs the noise steady or fluctuating? → if fluctuating, use
roomNoiseCriteria
See references/noise-compliance.md for detailed output interpretation and selection guidance.
Speech Quality
[degraded, fs] = audioread("processed_speech.wav");
[reference, ~] = audioread("reference_speech.wav");
mosScore = visqol(degraded, reference, fs, Mode="speech");
intelligibility = stoi(degraded, reference, fs);Critical: stoi and visqol argument order is (processed, reference, fs) — processed/degraded signal FIRST.
visqol modes: "speech" for narrowband/wideband speech (outputs 1-5 MOS), "audio" (default) for general audio.
STI/SII Measurement
Two methods are available for both speechTransmissionIndex and speechIntelligibilityIndex:
IR-based method (simpler — no alignment needed):
[ir, fs] = audioread("room_impulse_response.wav");
sti = speechTransmissionIndex(ir, fs);
sii = speechIntelligibilityIndex(ir, fs);Direct method (from test signals transmitted through the system):
fs = 48000;
reference = stipaExcitation(fs, Duration=15);
% Transmit reference through system, record as 'processed'
[processed, ~] = audioread("received_stipa.wav");
% IMPORTANT: Align signals before computing (see Signal Alignment)
processed = alignsignals(processed, reference);
sti = speechTransmissionIndex(processed, reference, fs);Ask the user:
Do they have an impulse response? → use IR method (simpler, no alignment needed)
Measuring live? → generate test signal, transmit, record, align, compute
STI or SII? STI for room/PA systems (IEC 60268-16); SII for hearing/communication (ANSI S3.5)
See references/sti-measurement.md for STI NV arguments, post-processing adjustment workflow (Annex M), test signal generation, and result interpretation. See references/sii-measurement.md for SII standard clause selection (5.1-5.3), BandImportanceFunction guidance, measurement positioning, and result interpretation.
SPL Measurement (Offline)
[audioIn, fs] = audioread("recording.wav");
spl = splMeter(SampleRate=fs, ...
Bandwidth="Full band", ...
FrequencyWeighting="A-weighting", ...
TimeWeighting="fast", ...
CalibrationFactor=2.3);
[Lt, Leq, Lpeak, Lmax] = spl(audioIn);
% For a single overall value, read the final row
fprintf("Leq: %.1f dB(A)\n", Leq(end));Valid Bandwidth values: "Full band" (overall level), "1 octave", "2/3 octave", "1/3 octave". There is no "broadband" option — use "Full band" for a single overall SPL value.
Output arity: All outputs (Lt, Leq, Lpeak, Lmax) have one row per input sample. For a 12-second file at 44.1 kHz, that is 539,648 rows. Never fprintf or disp the full output — it will hang. Instead:
Single overall value: read
Leq(end)(the final accumulated value)Time-interval readings: downsample to interval boundaries:
Leq(round(fs*T):round(fs*T):end, :)whereTis the desired interval in seconds
TimeInterval controls the integration window for Leq computation but does NOT reduce the number of output rows.
Do not manually compute 20*log10(rms(audioIn)/20e-6) — splMeter handles calibration, weighting, and time integration correctly per IEC 61672.
Multi-band (octave-band) SPL: Use splMeter with Bandwidth="1 octave" — do NOT use octaveFilterBank + manual dB conversion. Key properties for octave-band SPL:
[audioIn, fs] = audioread("recording.wav");
spl = splMeter(SampleRate=fs, ...
Bandwidth="1 octave", ...
FrequencyWeighting="Z-weighting", ...
TimeWeighting="fast", ...
FrequencyRange=[15 8000], ...
OctaveFilterOrder=8, ...
CalibrationFactor=2.3);
[Lt, Leq, Lpeak, Lmax] = spl(audioIn);
cf = getCenterFrequencies(spl);Critical gotchas for octave-band splMeter:
Property name is
OctaveFilterOrder(notFilterOrder).FilterOrderdoes not exist onsplMeter.FrequencyRangecompares against true center frequencies (fc = 1000 × 10^(3b/10)per IEC 61260), not nominal values. A band is included only if its true center falls within[lower, upper]. Bands below 1 kHz have true centers slightly above nominal (e.g., "63 Hz" = 63.10); bands above 1 kHz have true centers below nominal (e.g., "2 kHz" = 1995.26, "8 kHz" = 7943.28). Usefloor(true_center)for lower bounds andceil(true_center)for upper bounds. Common case "16 Hz to 8 kHz": use[15 8000]— the 16 Hz true center is 15.85 (so 15 ≤ 15.85 includes it) and 8 kHz true center is 7943 (so 8000 ≥ 7943 includes it). Do NOT use[16 8000]— this drops the 16 Hz band.Output is per-sample (see Output arity note above). Never print the full output. For time-interval readings, downsample:
Lt100ms = Lt(round(fs*0.1):round(fs*0.1):end, :);
See references/spl-measurement.md for weighting selection guidance (A/C/Z and fast/slow), SPL interpretation tables, occupational exposure limits, splMeter vs poctave equivalency, and common measurement scenarios.
Broadcast Loudness (EBU R 128)
[audioIn, fs] = audioread("broadcast_content.wav");
[loudness, loudnessRange] = integratedLoudness(audioIn, fs);
% Check compliance: target is -23 LUFS +/- 1 LU
isCompliant = abs(loudness - (-23)) <= 1;Use integratedLoudness for offline compliance checks. Use loudnessMeter for streaming/real-time monitoring (see matlab-process-streaming-audio).
RT60
[ir, fs] = audioread("room_ir.wav");
rtsummary = rt60(ir, fs, Bandwidth="1 octave");Ask the user:
What is the room type? (drives the target RT60)
Do they have an IR, or do they need to measure one?
T30 (standard) vs T20 (when noise floor limits dynamic range)?
See references/rt60-measurement.md for target RT60 values by space type, T20/T30/EDT interpretation, frequency-dependent analysis, and relationship to STI.
Tonality
[audioIn, fs] = audioread("machine_noise.wav");
[tnr, tnrFreq, isProminent] = acousticToneToNoiseRatio(audioIn, fs);
[pr, prFreq, isProminent] = acousticProminenceRatio(audioIn, fs);All outputs are empty (0×1) when no tonal components are detected. Check isempty(tnr) before indexing.
Standards-Compliant Filters (Custom Preprocessing)
The metric functions above perform standards-compliant filtering internally. Use standalone filter objects only for custom measurement workflows where no single metric function applies AND you do not need SPL output:
% A-weighting filter
wf = weightingFilter("A-weighting", fs);
weightedSignal = wf(audioIn);
% Octave-band filter bank (for waveform-level band decomposition only)
ofb = octaveFilterBank("1 octave", fs, ...
FrequencyRange=[31.5 16000], FilterOrder=8);
bandSignals = ofb(audioIn);If you need octave-band SPL levels, use splMeter with Bandwidth="1 octave" instead of octaveFilterBank + manual dB conversion. See the Multi-band SPL section above.
Signal Alignment
| Function | Internal alignment? | Action |
|---|---|---|
visqol | Yes | No action needed |
stoi | No | Align before calling |
speechTransmissionIndex | No | Align for direct method; IR method avoids issue |
speechIntelligibilityIndex | No | Align for direct method; IR method avoids issue |
For the direct (processed, reference, fs) method, always align signals:
processed = alignsignals(processed, reference);SII is more sensitive to misalignment than STI. At 50 ms delay: SII error ~0.016, STI negligible. At 200 ms: SII ~0.036, STI ~0.017. The IR-based (ir, fs) method avoids alignment issues entirely.
Common Mistakes
| Mistake | Why it fails | Correct approach |
|---|---|---|
Call pesq(reference, degraded, fs) | Function does not exist | visqol(degraded, reference, fs, Mode="speech") |
stoi(reference, processed, fs) | Wrong argument order | stoi(processed, reference, fs) — processed FIRST |
acousticFluctuationStrength(...) | Wrong function name | acousticFluctuation(audioIn, fs, calFactor) |
| Implement NC from scratch with hardcoded curves | Misses SIL, spectrum imbalance, rattle risk | noiseCriteria(audioIn, fs, CalibrationFactor=cf) |
20*log10(rms(x)/20e-6) for SPL | No weighting, no time integration, no calibration | splMeter with appropriate settings |
| Implement STI algorithm manually | ~100 lines, error-prone, misses NV options | speechTransmissionIndex(ir, fs) |
| Divide signal by calibration factor manually | Incorrect; factor is a multiplier, not a divisor | Pass as positional arg or CalibrationFactor=value |
| Skip alignment for direct STI/SII | Silent accuracy degradation | alignsignals(processed, reference) before calling |
Use acousticLoudness for broadcast loudness | Wrong standard (ISO 532 = sones, not LUFS) | integratedLoudness for EBU R 128 compliance |
string(rattleRisk) or fprintf("%s", specImbalance) | These are structs, not strings | Access .Summary field: rattleRisk.Summary |
specImbalance.Summary when NC is out of curve range | specImbalance degrades to char (not struct) when "Above NC-70" or below NC-15 | Guard: if isstruct(specImbalance), disp(specImbalance.Summary); end |
roomNoiseCriteria on recordings shorter than 15 s | ANSI/ASA S12.2-2019 requires ≥150 Lt samples at 100 ms intervals | Ensure recording is at least 15 seconds; use noiseCriteria for shorter clips |
round(NC) or arithmetic on NC/RC output | NC and RC are strings, not numbers | Use directly: fprintf("%s\n", NC) |
noiseCriteriaRecommendations() with no args | First argument (criteria name) is required | noiseCriteriaRecommendations("NC") |
loudness.OverallLoudness after acousticLoudness | Returns a scalar or vector, not a struct | Use directly: fprintf("%.1f sones\n", loudness) |
splMeter(..., FilterOrder=8) | Property does not exist on splMeter | Use OctaveFilterOrder=8 |
splMeter(..., FrequencyRange=[16 8000]) for 16 Hz–8 kHz | Drops 16 Hz band (true center is 15.85 Hz, which is below 16) | Use FrequencyRange=[15 8000] — use floor(true_center) for lower bound |
octaveFilterBank + 20*log10(rms(band)/pRef) for SPL | Manual, no time weighting, no calibration integration | Use splMeter with Bandwidth="1 octave" |
Treating splMeter output as a single value | All outputs have one row per input sample (e.g., 539k rows for 12s at 44.1 kHz) | Use Leq(end) for a single value, or downsample to interval boundaries |
Conventions
Always ask about the user's measurement goal before selecting a function
Always ask about calibration — recommend
calibrateMicrophonefor system-level accuracyDefault to
SoundField="free"for anechoic/outdoor,"diffuse"for reverberant roomsDefault to
Method="ISO 532-1"for loudness (Zwicker method, most common)Use IR-based methods for STI/SII when an impulse response is available (avoids alignment)
Pass
CalibrationFactorexplicitly rather than pre-scaling the signalFor noise compliance, prefer
roomCriteriafor HVAC andnoiseCriteriafor general background noise
Copyright 2026 The MathWorks, Inc.
Files
- ATTRIBUTION.mdAdded by AutoGineer1.1 KiB
- LICENSELicence file added by AutoGineer1.4 KiB
- SKILL.md22.7 KiB
- manifest.yaml444 B
- references/function-arguments.md7.3 KiB
- references/noise-compliance.md16.4 KiB
- references/psychoacoustic-metrics.md16.0 KiB
- references/rt60-measurement.md14.4 KiB
- references/sii-measurement.md16.9 KiB
- references/spl-measurement.md12.5 KiB
- references/sti-measurement.md14.0 KiB
references/spl-measurement.md
SPL Measurement
Guidance for selecting parameters, interpreting results, and guiding user workflows for splMeter.
Intake Questions
1. What is the measurement purpose?
| Purpose | Frequency Weighting | Time Weighting | Key Output |
|---|---|---|---|
| Occupational noise exposure (hearing protection) | A-weighting | Slow | Leq (8-hour TWA) |
| Environmental noise monitoring | A-weighting | Fast | Leq, Lmax |
| Peak assessment (impulse hazard) | C-weighting | — | Lpeak |
| Product noise testing (to spec sheet) | A-weighting | — | Leq |
| Machinery noise for NC/RC compliance | Z-weighting | Fast | Octave-band Leq |
| Regulatory environmental limit | Depends on regulation | Depends on regulation | Varies |
| Building acoustics (background noise) | Z-weighting | Fast | Octave-band Leq → pass to noiseCriteria |
| General "how loud is it?" | A-weighting | Fast | Leq |
2. Frequency weighting selection
| Weighting | What it does | When to use |
|---|---|---|
| A-weighting | Approximates human hearing sensitivity at moderate levels; attenuates low frequencies | Most general-purpose measurements, occupational noise, environmental noise, product noise specs |
| C-weighting | Flatter response; mild LF roll-off below 31.5 Hz | Peak measurements (Cpeak), high-level noise (>100 dB), assessing low-frequency content, some regulatory requirements |
| Z-weighting | Flat (no filtering) — raw acoustic pressure level | Octave-band analysis for NC/RC/RNC, feeding into compliance functions, when you need unweighted per-band levels, research |
Guidance:
If the user says "dB" without qualification, they likely mean dB(A) — confirm
If they need octave-band levels for noise compliance, use Z-weighting (the compliance functions apply their own corrections)
C-weighting for peak is standard in occupational noise (IEC 61672 specifies C-peak for impulse hazard)
A-weighting underestimates the perceived loudness of low-frequency noise — if the user complains about "rumble" but A-weighted levels seem low, suggest octave-band analysis or C-weighting
3. Time weighting selection
| Time Weighting | Time Constant | Behavior | When to use |
|---|---|---|---|
| Fast | 125 ms attack/release | Tracks fluctuations; standard for most measurements | General purpose, environmental monitoring, product testing |
| Slow | 1000 ms attack/release | Smoothed; averages short-term fluctuation | Occupational noise exposure, stable environments, when fast readings fluctuate too much to read |
| Custom | User-defined | For specialized standards | Rarely needed; specific regulatory or research requirements |
Guidance:
Default to Fast unless the user has a specific reason for Slow
If levels fluctuate rapidly and the user wants a single characterization, Leq (equivalent continuous level) is more meaningful than any single time-weighted reading
For impulsive noise (hammering, gunfire), neither Fast nor Slow captures the peak — use Lpeak output
4. Bandwidth selection
| Bandwidth | Output columns | When to use |
|---|---|---|
"Full band" | 1 (overall level) | Quick overall SPL, occupational noise, simple monitoring |
"1 octave" | 1 per octave band | NC/RC/RNC input, spectral diagnosis of noise sources, building acoustics |
"1/3 octave" | 1 per 1/3-octave band | Detailed spectral analysis, product noise standards, transmission loss |
"2/3 octave" | 1 per 2/3-octave band | Rarely used; specific legacy standards |
Guidance:
If the goal is noise compliance (NC/RC/RNC), use
"1 octave"with Z-weighting — the compliance functions expect octave-band LeqIf the goal is a single number (occupational, environmental), use
"Full band"If the user wants to "see what frequencies are loud," use
"1 octave"or"1/3 octave"
5. Calibration
Ask about the full signal chain:
Recording device: What mic/interface was used? What is the sensitivity?
Calibration method: Did they use a pistonphone or physical SPL meter for system calibration?
CalibrationFactor: Do they already have one? If not, see the Calibration section in SKILL.md
If calibration is unknown and absolute levels are needed, the measurement is unreliable. Recommend:
Re-record with a calibration reference, OR
Use
calibrateMicrophonewith a known-SPL reference tone recording
For relative comparisons (before/after, product A vs B), calibration matters less as long as the same setup is used for both recordings.
6. Multichannel input
splMeter accepts matrix input where each column is an independent channel. For multichannel:
CalibrationFactorcan be a vector (one value per channel)Outputs become 3D arrays when using octave/fractional-octave bandwidth: L-by-B-by-C (samples × bands × channels)
Each channel is metered independently
splMeter vs poctave
Both splMeter and poctave compute octave-band levels. They produce identical results when filter orders match:
% These are equivalent:
spl = splMeter(SampleRate=fs, Bandwidth="1 octave", FrequencyWeighting="Z-weighting", ...
OctaveFilterOrder=2, CalibrationFactor=1, TimeInterval=duration);
[~, Leq] = spl(x);
levels_splMeter = Leq(end,:);
[p, cf] = poctave(x, fs, "power", BandsPerOctave=1, FilterOrder=2);
levels_poctave = 10*log10(p' / (2e-5)^2);The default filter orders differ — splMeter uses OctaveFilterOrder=2, poctave uses FilterOrder=6. This causes ~1–2 dB differences if not matched.
TimeInterval and Leq accumulation
splMeter resets its Leq accumulation at each TimeInterval boundary. If the signal length is not an integer multiple of TimeInterval, the last interval is shorter. To compute overall Leq from per-interval values, duration-weight the energy sum:
% Wrong: treats partial last interval as a full interval
Leq_wrong = 10*log10(mean(10.^(Leq_intervals/10)));
% Correct: weight by actual interval duration
Leq_correct = 10*log10((1/T_total) * sum(t_i .* 10.^(L_i/10)));To avoid this issue entirely, set TimeInterval to the full signal duration — then Leq(end,:) is the overall Leq directly.
Interpreting SPL Results
Overall Sound Pressure Levels
| dB(A) | Environment / Source | Subjective Impression |
|---|---|---|
| 20–30 | Quiet bedroom, recording studio | Very quiet; barely audible |
| 30–40 | Quiet library, rural ambient | Quiet; comfortable |
| 40–50 | Quiet office, residential area at night | Moderate; noticeable |
| 50–60 | Normal conversation at 1 m, office | Clearly audible; may interfere with concentration |
| 60–70 | Busy restaurant, TV audio | Loud; raised voice needed for speech |
| 70–80 | Vacuum cleaner, busy traffic | Very loud; prolonged exposure fatiguing |
| 80–85 | Power tools, loud music | Hearing protection threshold (occupational) |
| 85–90 | Heavy machinery, motorcycle | OSHA action level; hearing damage begins |
| 90–100 | Lawn mower, band rehearsal | Painful without protection |
| 100–120 | Chainsaw, rock concert, jet takeoff at distance | Immediate hearing damage risk |
| >120 | Threshold of pain, close to explosion | Physical pain; acoustic trauma |
Occupational Noise Exposure Limits
| Standard | Permissible Exposure Limit (8h TWA) | Action Level |
|---|---|---|
| OSHA PEL (USA) | 90 dB(A) | 85 dB(A) |
| NIOSH REL (USA) | 85 dB(A) | — |
| EU Directive 2003/10/EC | 87 dB(A) | 80 dB(A) (lower) / 85 dB(A) (upper) |
| ISO 1999:2013 | 85 dB(A) (recommended) | — |
Halving/doubling rule: For every 3 dB increase (NIOSH/EU) or 5 dB increase (OSHA), permissible exposure time halves:
NIOSH: 85 dB → 8h, 88 dB → 4h, 91 dB → 2h, 94 dB → 1h
OSHA: 90 dB → 8h, 95 dB → 4h, 100 dB → 2h, 105 dB → 1h
Environmental Noise Limits (Typical)
These vary by jurisdiction. Common residential limits:
| Time Period | Typical Limit | Standard/Regulation |
|---|---|---|
| Daytime (7am–10pm) | 55 dB(A) Leq | WHO guidelines, many local codes |
| Nighttime (10pm–7am) | 45 dB(A) Leq | WHO guidelines |
| Lmax nighttime | 60 dB(A) | WHO sleep disturbance threshold |
Always ask the user which specific regulation they're working to — limits vary significantly by location and zone (residential, commercial, industrial).
Peak Level Interpretation
| Lpeak dB(C) | Risk |
|---|---|
| < 135 | Generally safe for single events |
| 135–140 | EU upper exposure action value — hearing protection mandatory |
| > 140 | Immediate acoustic trauma risk |
Output Metric Selection
| User's Question | Which Output to Report |
|---|---|
| "What's the noise level?" | Leq (time-averaged level — single representative value) |
| "How loud does it get?" | Lmax (maximum level during measurement) |
| "Is there an impulse hazard?" | Lpeak (true peak pressure, unweighted by time constant) |
| "What does the level look like over time?" | Lt (time-weighted instantaneous level — use downsampled intervals) |
| "8-hour exposure?" | Leq over measurement period, then compute TWA |
Common Scenarios
Scenario: Background Noise Survey for NC Rating
Record ≥15 s of steady-state background noise (HVAC on, room unoccupied)
Compute A-weighted Leq as a quick sanity check:
splMeter: Bandwidth="Full band", FrequencyWeighting="A-weighting"Compare to the A-weighted target for the space type (see
references/noise-compliance.md)Compute octave-band Leq for spectral diagnosis:
splMeter: Bandwidth="1 octave", FrequencyWeighting="Z-weighting", FrequencyRange=[15 8000]For formal NC/RNC/RC compliance, pass the recording to
noiseCriteria(audioIn, fs, CalibrationFactor=cf)— it computes octave-band Leq and assigns the rating internally
Scenario: Product Noise Measurement
Set up mic at specified distance (typically 1 m, per product standard)
Record product in specified operating conditions
Compute A-weighted Leq:
splMeterwithBandwidth="Full band",FrequencyWeighting="A-weighting"Report
Leq(end)as the product noise level in dB(A)If spec requires octave-band data, also compute with
Bandwidth="1 octave",FrequencyWeighting="Z-weighting"
Scenario: Occupational Noise Assessment
Record representative work period (or use duration-weighted samples)
Compute A-weighted Leq with Slow time weighting:
splMeter: Bandwidth="Full band", FrequencyWeighting="A-weighting", TimeWeighting="slow"Report Leq(end) and compare to exposure limit
If peak hazard is a concern, also report Lpeak with C-weighting:
splMeter: FrequencyWeighting="C-weighting"
Troubleshooting
Handling splMeter output size
splMeter outputs one row per input sample, but Leq is only updated at TimeInterval boundaries — between boundaries the value is held from the previous interval, and it is -Inf before the first boundary. Choose TimeInterval based on what you need:
| Goal | TimeInterval | How to read Leq |
|---|---|---|
| Single overall level | Set to signal duration | Leq(end) |
| Time history (e.g., 1-second snapshots) | 1 | Leq(fs:fs:end,:) (value at each 1-second boundary) |
Notes:
If
TimeInterval> signal duration,Leqis never reported (all-Inf)Leqresets at eachTimeIntervalboundary — it is NOT a cumulative running total across the full signal (see "TimeInterval and Leq accumulation" above)
Common issues
| Observation | Likely Cause | Action |
|---|---|---|
| SPL seems 20–40 dB too low or too high | Missing or incorrect calibration factor | Verify CalibrationFactor; if unknown, levels are relative only |
| Leq is all -Inf | TimeInterval > signal duration | Set TimeInterval ≤ signal duration |
| Octave-band output missing expected bands | FrequencyRange excludes some true center frequencies | Use [15 8000] for 16 Hz–8 kHz; see SKILL.md gotchas |
| All octave bands show same level | FrequencyWeighting is applied — Z-weighting for flat bands | Use Z-weighting if you want unweighted per-band levels |
| Levels don't match physical meter | Different weighting, time constant, or calibration | Match all settings: same weighting, same time constant, verify cal |
| Lpeak is much higher than Leq | Normal for impulsive or highly variable noise | Report both; Lpeak represents instantaneous peak exposure |
Copyright 2026 The MathWorks, Inc.
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- MathWorks
- Publisher
- MathWorks (Official)
- Source
- matlab/matlab-agentic-toolkit · skills-catalog/signal-processing/matlab-evaluate-acoustic-metrics · commit 2a7f215
- Licence
- BSD 2-Clause License (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE.md)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by MathWorks or MathWorks.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download matlab-evaluate-acoustic-metrics.zip