Signal-to-Noise Ratio (SNR)
Short answer. SNR is the ratio of speech power to noise power in decibels: SNR = 10 log10(P_speech / P_noise). The number depends entirely on where you measured it. Computed over a whole file that contains pauses, the speech power is diluted by the silent frames, so the same recording reports 10.0 dB over the full file and 15.8 dB over the speech frames only. Always state the measurement window with the number.
How to do it
The formula and its two halves
Power here means mean squared amplitude over the measurement window. Speech and noise are both averaged over the same window, and the ratio is converted to decibels. A ratio of 10 is 10 dB; 100 is 20 dB.
The subtlety is that you need the noise alone, not the mixture. In practice you either have a separate noise recording to add, or you estimate the noise from the pauses in the same recording — and the second method is where most SNR numbers go wrong.
Mixing to a target SNR, and checking the round trip
To build a corpus at a specified SNR you scale the noise so the ratio lands where you want it: compute the gain from the current ratio and the target, multiply the noise by it, add. The arithmetic is exact, so the achieved SNR equals the target to within floating-point error.
Verify it anyway, because when the number comes out wrong it is the input to the calculation that is wrong rather than the calculation. In the run below the raw pair sits at 22.58 dB and the gains of +2.58, +12.58, +17.58 and +22.58 dB hit the four targets exactly.
The pause problem
Speech recordings contain silence, and silence has no speech power. Averaging the speech power over the whole file divides by a duration that includes the pauses, so the measured speech power falls and the reported SNR falls with it.
In the example below the speech occupies 27% of the file. The whole-file measurement gives 10.0 dB; restricting both averages to the speech-active frames gives 15.8 dB. Same formula, same audio, different measurement window. That 5.8 dB gap is entirely a definition.
What to write in a data specification
A useful SNR specification states the measurement method, not just a number: the window used, whether the noise was measured during pauses or from a separate capture, and the spread if it varies.
A corpus described as "15 dB SNR" where 15 is a mean over utterances ranging from 5 to 30 is a different product from one where every file sits between 14 and 16. If the noise is non-stationary — traffic, babble, a fan that cycles — a single number describes the average condition and hides the worst moment, which is the one the model fails on.
Code
Mix synthetic speech and noise to four target SNRs, verify the round trip, then measure one of those mixes two different ways.
import numpy as np
SR = 16000
rng = np.random.default_rng(2)
t = np.arange(int(2.0 * SR)) / SR
speech = np.zeros_like(t)
for start in (0.0, 0.5, 1.0, 1.5):
m = (t >= start) & (t < start + 0.15)
speech[m] = np.sin(2 * np.pi * 140 * t[m]) * (0.4 + 0.6 * np.sin(2 * np.pi * 4 * t[m]) ** 2)
noise = 0.02 * rng.standard_normal(len(t))
def snr_db(speech, noise):
return 10 * np.log10((speech ** 2).mean() / (noise ** 2).mean())
def mix_to_snr(speech, noise, target_db):
gain = np.sqrt((speech ** 2).mean() / (noise ** 2).mean()) * 10 ** (-target_db / 20)
return speech + gain * noise
print(f"the raw pair sits at {snr_db(speech, noise):.2f} dB\n")
print(f"{'target':>8}{'achieved':>11}{'gain applied to the noise':>27}")
for target in (20, 10, 5, 0):
mixed = mix_to_snr(speech, noise, target)
applied = 20 * np.log10((mixed - speech).std() / noise.std())
print(f"{target:>7}dB{snr_db(speech, mixed - speech):>10.2f}dB{applied:>26.2f}dB")
active = speech ** 2 > 0.01 * (speech ** 2).max()
mixed = mix_to_snr(speech, noise, 10)
print("\nthe same 10 dB mix, measured two ways:")
print(f" over the whole file {snr_db(speech, mixed - speech):>6.2f} dB")
print(f" over speech frames only {snr_db(mixed[active], (mixed - speech)[active]):>6.2f} dB")
print(f" speech is only {active.mean():.0%} of this file, and the pauses are what "
f"pull the first number down") - numpy only. Both signals are synthesized, and the speech occupies four 0.15 s bursts in a 2.0 s file.
- All four targets are hit exactly, which is the point of mixing to a ratio rather than to a gain: 20.00, 10.00, 5.00 and 0.00 dB achieved against the same four targets.
- The last two lines are the reason to state your measurement window. The same mix reads 10.00 dB over the file and 15.78 dB over the speech frames, because speech is only 27% of the file.
Where this goes wrong
Measuring SNR over a file that contains silence
The pauses dilute the speech power and the number comes out lower than the speech-to-noise ratio during actual speech. On a file that is 27% speech the gap is about 5.8 dB. State the window or the number means nothing.
Estimating noise from a pause that is not silent
In far-field and mobile recordings, pauses contain room tone, traffic and other talkers. Using them as the noise reference overstates the noise and understates the SNR. Use a noise segment you have verified is noise-only.
Assuming SNR is constant across a file
A single number describes the average. If the noise is non-stationary, segment-level SNR varies by 10 dB or more inside one recording, and the model fails at the worst moment rather than the average one.
Adding noise at a fixed gain instead of a target SNR
A fixed gain gives a different SNR for every utterance, because utterances differ in level. A corpus built that way and labeled "10 dB" will contain files at 3 dB and files at 18 dB, so a model evaluated on it is evaluated on neither condition. Mix to a target ratio and verify the result after mixing.
Comparing SNR across corpora without the method
Two corpora both described as 20 dB SNR can differ by 6 dB in practice because one measured over speech frames and the other over the whole file. Ask for the measurement method before comparing.
When to buy the data instead of building the pipeline
Buy when you need a specific SNR distribution rather than a specific SNR: a corpus where every file sits inside a stated band, or a spread across conditions you cannot stage yourself — 0 dB, 5 dB and 15 dB, each with enough speakers to train on. Buy when the noise has to be real, since stationary synthetic noise and real babble produce different models. Build it yourself when you have a clean recording and a clean noise recording and only need to mix them, which is the code above.
More technical reference
-
Mel Spectrogram
mel spectrogram
-
Transcription Accuracy
transcription accuracy
-
Speaker Verification
speaker verification
-
Speaker Identification vs Speaker Verification
speaker identification vs speaker verification
-
Speaker Embedding
speaker embedding
-
Phoneme Recognition
phoneme recognition
Need data for Signal-to-Noise Ratio (SNR)?
Tell us the language, the hours, and what the data needs to look like. You will get a real number and a real timeline — not a range. If we cannot source it well, we will tell you that instead.
- Pilot batch before the full run, so problems surface early.
- Consent documentation delivered with the data.
- No medical or clinical data. No recorded telephone calls.