SubtitleEdit/subtitleedit · error · Exception

Peaks file must have 1 or 2 channels.

Error message

Peaks file must have 1 or 2 channels.

What it means

Thrown by WavePeakData2.LoadPeaks when the peaks cache WAV header reports a channel count other than 1 or 2. The peak-reading logic only knows how to deserialize mono (single sample) or stereo (max/min pair) peak records; any other channel count is unparseable and would corrupt the peak array.

Source

Thrown at src/ui/Logic/Media/WaveToVisualizer2.cs:792

            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 channel
            int byteIndex = 0;
            while (byteIndex < data.Length)
            {
                short max = (short)ReadValue16Bit(data, ref byteIndex);
                short min = (short)ReadValue16Bit(data, ref byteIndex);

View on GitHub (pinned to 17a9f07487)

Solutions

  1. Regenerate the peaks cache from a mono or stereo source.
  2. Down-mix multi-channel audio to stereo before peak generation.
  3. Guard: check Header.NumberOfChannels is 1 or 2 before LoadPeaks and regenerate otherwise.
  4. Verify the cache file is the one produced by this application's GeneratePeaks path.

Example fix

// before
var peaks = wave.LoadPeaks();

// after
if (wave.Header.NumberOfChannels is 1 or 2)
    peaks = wave.LoadPeaks();
else
    peaks = GeneratePeaksForCache();
Defensive patterns

Strategy: validation

Validate before calling

if (wave.Header.NumberOfChannels is not (1 or 2))
    throw new InvalidOperationException($"Peaks cache must be 1 or 2 channels, got {wave.Header.NumberOfChannels}");

Type guard

static bool IsSupportedChannelCount(WaveHeader2 h) => h.NumberOfChannels == 1 || h.NumberOfChannels == 2;

Try / catch

try { var peaks = wave.LoadPeaks(); }
catch (Exception ex) when (ex.Message.Contains("1 or 2 channels")) { /* regenerate or down-mix */ }

Prevention

When it happens

Trigger: LoadPeaks() is pointed at a multi-channel (e.g. 5.1 / 6-channel) WAV, or a file whose header was damaged so NumberOfChannels parses to an out-of-range value.

Common situations: Source audio had more than 2 channels and was mistakenly used as the peaks cache; corruption of the fmt chunk shifting the channels field; a third-party tool wrote a non-standard peaks file.

Related errors


AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13). Data as JSON: /api/errors/ea46358df3adf301. Report an issue: GitHub.