stride3d/stride · error · Exception

Failed to create Celt custom mode.

Error message

Failed to create Celt custom mode.

What it means

Thrown from the Celt constructor when the native call opus_custom_mode_create returns NULL, meaning the codec library could not create a custom mode for the requested sampleRate/bufferSize combination. Celt custom modes only accept specific sample rates and frame sizes, so invalid parameters make native initialization impossible.

Solutions

  1. Use a supported sample rate for Celt custom mode (e.g. 48000 Hz) with its matching frame buffer size.
  2. Query the audio hardware sample rate and resample or select a compatible Celt mode instead of passing the raw value.
  3. Verify the bundled native Celt/Opus library is present and compatible with the platform.
  4. Check for native memory pressure if parameters are known-valid.

Example fix

// before
var celt = new Celt(deviceSampleRate, 256, channels, decoderOnly:false);
// after
const int celtSampleRate = 48000;
var celt = new Celt(celtSampleRate, 256, channels, decoderOnly:false); // device input resampled to celtSampleRate
Defensive patterns

Strategy: try-catch

Validate before calling

public static bool IsCeltCompatibleRate(int sampleRate) =>
    sampleRate == 48000 || sampleRate == 24000 || sampleRate == 16000 || sampleRate == 12000 || sampleRate == 8000;

Try / catch

try
{
    var celt = new Celt(sampleRate, bufferSize, channels, decoderOnly);
}
catch (Exception ex) when (ex.Message.Contains("Failed to create Celt custom mode"))
{
    logger.Error($"Unsupported Celt mode for rate={sampleRate} size={bufferSize}; falling back.");
    celt = new Celt(48000, bufferSize, channels, decoderOnly);
}

Prevention

When it happens

Trigger: Constructing Celt with a sample rate outside the codec's supported range or a bufferSize that is not a valid frame size for that rate (e.g. unusual sample rates on iOS/AVFoundation path).

Common situations: Configuring audio on iOS/macOS with hardware-reported sample rates that don't match the expected Celt constants; typos in sample rate constants; memory exhaustion in native allocation (rare).

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/d5838c99c9c6b920. Report an issue: GitHub.

Appendix: source

Thrown at sources/engine/Stride.Audio/Native/Celt.AVFoundation.cs:47

        private const int OPUS_GET_LOOKAHEAD_REQUEST = 4027;

        public int SampleRate { get; set; }
        public int BufferSize { get; set; }
        public int Channels { get; set; }

        private IntPtr mode;
        private IntPtr decoder;
        private IntPtr encoder;

        public Celt(int sampleRate, int bufferSize, int channels, bool decoderOnly)
        {
            SampleRate = sampleRate;
            BufferSize = bufferSize;
            Channels = channels;

            mode = opus_custom_mode_create(sampleRate, bufferSize, IntPtr.Zero);
            if (mode == IntPtr.Zero)
                throw new Exception("Failed to create Celt custom mode.");

            decoder = opus_custom_decoder_create(mode, channels, IntPtr.Zero);
            if (decoder == IntPtr.Zero)
                throw new Exception("Failed to create Celt decoder.");

            if (!decoderOnly)
            {
                encoder = opus_custom_encoder_create(mode, channels, IntPtr.Zero);
                if (encoder == IntPtr.Zero)
                    throw new Exception("Failed to create Celt encoder.");
            }
        }

        public void Dispose()
        {
            if (encoder != IntPtr.Zero) { opus_custom_encoder_destroy(encoder); encoder = IntPtr.Zero; }
            if (decoder != IntPtr.Zero) { opus_custom_decoder_destroy(decoder); decoder = IntPtr.Zero; }
            if (mode != IntPtr.Zero) { opus_custom_mode_destroy(mode); mode = IntPtr.Zero; }

View on GitHub (pinned to 96fad776d2)