/docs · VoiceLab · Deep
What envelope decay after speech actually measures
We built a cheap reverb proxy from the decay after each phrase, then tested it against 24 measured rooms. It does not measure reverb. Here are the numbers and what we changed.
Updated Sep 27, 2026
RT60 wants you to inject a known stimulus into a room. You cannot do that on a recording someone already made, so for voice QA we built a cheap proxy instead: measure how much energy is left just after each phrase ends, relative to the phrase itself. A live room rings on, a treated one does not.
On 27 September 2026 we tested that proxy against rooms whose reverberation time had actually been measured. It failed. This page is the measurement, the test, and what we changed, because a negative result you can reproduce is worth more than a threshold table that reads well.
The measurement
Detect the speech-to-silence transitions with a simple energy gate, then read the envelope in the tail after each one against the level at the transition.
function decayRatio(envelope, mask, hopSec) {
const decays = [];
for (let i = 1; i < mask.length - 30; i++) {
if (mask[i - 1] && !mask[i]) {
const peak = envelope[i - 1];
if (peak < 1e-5) continue;
const window = Math.min(30, Math.floor(0.6 / hopSec));
let tail = 0;
for (let k = 0; k < window; k++) tail += envelope[i + k];
tail /= window;
decays.push(tail / peak);
}
}
return decays.reduce((a, b) => a + b, 0) / decays.length;
}
Nothing is wrong with the code. The problem is what the number was claimed to mean.
What we tested it against
- Real rooms, no added noise. Five clean sentences through 24 measured impulse responses, with reverberation times from 0.18 s to 1.71 s.
- Noise with and without reverb. 1280 recordings, four environments, signal-to-noise ratios of 20, 10, 5 and 0 dB, each with and without 0.5 s of reverb.
- A rebuild that matched the engine to 0.0000 on all 1760 files, so the results apply to the code that ships and not to an approximation of it.
What the numbers said
| Question | Requirement | Result |
|---|---|---|
| Does it track the measured RT60 of real rooms? (Spearman) | 0.70 or better | 0.06 |
| Does it tell reverb from dry at 20 dB SNR? (AUC) | 0.75 or better | 0.52 |
| Same question at 10 dB SNR | 0.75 or better | 0.55 |
| Is it unmoved by noise alone? (AUC) | between 0.35 and 0.65 | 0.68 |
An AUC of 0.5 is a coin flip. The clearest single number: a room with 1.71 s of reverberation scored 0.175, and a booth with 0.18 s scored 0.186. The reverberant room scored lower than the booth.
The one thing the measurement does do reliably is rise with background noise, which is the opposite of useful when the label says “room”.
Why it fails
Three reasons, each fixable on its own and not enough together:
- The noise floor is the 10th percentile of the whole file. When the background varies, the noise inside a pause sits well above that percentile, and the difference gets counted as a tail.
- The tail is not checked for being inside the pause. The window runs from 60 to 420 ms after the phrase ends, and after short gaps are closed up, many pauses are shorter than that. The measurement then reads the start of the next word.
- The scale is wrong even without those two. A real RT60 of 0.5 s works out to a ratio of about 0.09 in theory, which is below the 0.15 boundary that used to mean “Dry”. Moderate reverberation was always going to be called dry.
With a 20 ms step and the jumps of speech itself, the decay after a phrase is too coarse to read reverberation out of. That is a research question, not a small repair.
What changed on 27 September 2026
- The
Dry/Tight/Live/Reverberantlabel is gone from the engine output, not set to a default. A field that is always empty is not a measurement to ship. - The plain-language card advising you to treat your room is gone, and so is the penalty this number applied to the intelligibility score. That penalty was charging a noisy recording twice.
- The number stays, under the name of what it measures: energy in the pauses after speech, noise or reverb, and it does not separate the two. Read it as “how much is left in the gaps”, never as a verdict on the room.
- In the API and the MCP server the field is still called
roomEchoScore. Renaming a published field breaks saved history and existing integrations, so that is a separate decision rather than part of this correction. The description says what it measures.
What would actually answer the question
If you need a reverberation figure from a recording alone, the honest candidates are a modulation-spectrum measure such as SRMR, or a small model trained on measured impulse responses. Both are testable against the same 24 rooms.
The rule we set for ourselves: a new measure may only be called reverb once it passes that test. Until then it gets a name that describes the arithmetic.
Related
- Measure how long a room rings with one clap: the profile that does measure reverberation, from a clap, a pop, an impulse response or a sweep
- Gate before transcription
- Designing hearing support without medicalising it
Next in VoiceLab docs
Measure how long a room rings with one clap →
The room profile reads the reverberation time per octave band from one clap, a balloon pop, an impulse response or a sweep. How to record it, how to read the answer, and how far the numbers are tested.
More in VoiceLab docs
- Intro
Voice AI: ten questions, answered
What AudioLab measures for a voice agent, what it does not, where your audio goes, how a verdict is made and who sets the limits, how to compare versions and automate the checks, and what is free.
- Intro
Why filler density matters more than filler count
Counting "ums" is the wrong measurement. Density tells you whether they are a problem.
- Practical
A pragmatic loudness target for podcasts
The right loudness target for spoken-word podcasts is not the same as music. Here are the numbers and why.
- Practical
Read the audio before you transcribe
One call before the model: what the scene fields tell you about a file, and what they do not, with the numbers from our own transcription test.
- Practical
Pitch and voice quality: what the profile gives and what it holds back
The pitch profile reads where a voice sits, how much it moves, how voiced the recording is and how clean the voice is. The test numbers, the limits, and why jitter and shimmer are not offered yet.
- Practical
Find lost packets in a recording
The chain profile counts the gaps of digital silence that a lost packet leaves in the middle of speech. How it decides, the test numbers, what it cannot see, and the echo and slapback measure.