SubtitleEdit/subtitleedit · error · Exception
Peaks file must be 16 bits per sample.
Error message
Peaks file must be 16 bits per sample.
What it means
Thrown by WavePeakData2.LoadPeaks when the cached peaks WAV file's header does not report exactly 16 bits per sample. The peaks cache is itself stored as a WAV whose samples are pre-computed min/max peak shorts, so only 16-bit data is meaningful for the peak-reading loop that follows. Any other bit depth means the file is not a SubtitleEdit-generated peaks cache.
Source
Thrown at src/ui/Logic/Media/WaveToVisualizer2.cs:787
for (var i = 1; i < count; i++)
{
float value = chunk[i];
max = Math.Max(max, value);
min = Math.Min(min, value);
}
return new WavePeak2((short)(short.MaxValue * max), (short)(short.MaxValue * min));
}
/// <summary>
/// Loads previously generated peaks from disk.
/// </summary>
internal WavePeakData2 LoadPeaks()
{
if (Header.BitsPerSample != 16)
{
throw new Exception("Peaks file must be 16 bits per sample.");
}
if (Header.NumberOfChannels != 1 && Header.NumberOfChannels != 2)
{
throw new Exception("Peaks file must have 1 or 2 channels.");
}
// load data
byte[] data = new byte[Header.DataChunkSize];
_stream.Position = Header.DataStartPosition;
_ = _stream.Read(data, 0, data.Length);
// read peak values
WavePeak2[] peaks = new WavePeak2[Header.LengthInSamples + 5];
int peakIndex = 0;
if (Header.NumberOfChannels == 2)
{
// max value in left channel, min value in right channelView on GitHub (pinned to 17a9f07487)
Solutions
- Regenerate the peaks cache (delete the existing peaks file and re-run peak generation) so it is written as 16-bit.
- Ensure LoadPeaks() is only called on the dedicated peaks cache path, never on the source audio file.
- If the peaks file format changed between versions, clear the cache directory.
- Guard the call: check Header.BitsPerSample == 16 before invoking LoadPeaks and fall back to generation.
Example fix
// before
var peaks = wave.LoadPeaks();
// after
WavePeakData2 peaks;
if (wave.Header.BitsPerSample == 16)
peaks = wave.LoadPeaks();
else
peaks = wave.GeneratePeaks(peakSampleRate); Defensive patterns
Strategy: validation
Validate before calling
// before LoadPeaks
if (wave.Header.BitsPerSample != 16)
throw new InvalidOperationException($"Peaks cache must be 16-bit, got {wave.Header.BitsPerSample}-bit"); Type guard
static bool IsPeaksCacheBitDepth(WaveHeader2 h) => h.BitsPerSample == 16;
Try / catch
try { var peaks = wave.LoadPeaks(); }
catch (Exception ex) when (ex.Message.Contains("16 bits per sample")) { peaks = wave.GeneratePeaks(peaksPerSecond); } Prevention
- Only call LoadPeaks on the generated peaks cache, never on source audio.
- Regenerate the cache after upgrades that change the peaks format.
- Delete stale peaks files when the source audio changes.
- Guard BitsPerSample before calling LoadPeaks.
When it happens
Trigger: Calling LoadPeaks() on a Wave object whose stream points at a regular audio WAV (8/24/32-bit) instead of the generated peaks cache, or on a peaks file produced by a different/older tool version that wrote a different bit depth.
Common situations: The peaks cache path was overwritten with the source audio; a user manually swapped the .wav; an upgrade changed the cache format and the stale file was not regenerated; pointing LoadPeaks at the original media instead of the generated peaks file.
Related errors
- Peaks file must have 1 or 2 channels.
- Cannot read bits per sample of {Header.BitsPerSample}
- Cannot write bits per sample of {Header.BitsPerSample}
- Stream is too small
- Too many bytes for CCData!
AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13).
Data as JSON: /api/errors/d89c5b7acf701060.
Report an issue: GitHub.