onInit method

  1. @override
void onInit()
override

Called immediately after the widget is allocated in memory. You might use this to initialize something for the controller.

Implementation

@override
void onInit() async {
  super.onInit();
  _sineEngine.painterEngine = painterEngine;
  try {
    final rawArgs = Sint.arguments;

    // Support Map arguments from levitation module
    if (rawArgs is Map<String, dynamic>) {
      _loadFromMapArguments(rawArgs);
    } else {
      final arguments = (rawArgs as List<dynamic>?) ?? [];
      if(arguments.isNotEmpty) {
        if(arguments.elementAt(0) is Incienso) {
          // Incienso preset from experiences page — defer loading until after init
          _activeIncienso = arguments.elementAt(0) as Incienso;
        } else if(arguments.elementAt(0) is NeomChamberPreset) {
          chamberPreset =  arguments.elementAt(0);
        } else if(arguments.elementAt(0) is NeomFrequency) {
          chamberPreset.mainFrequency = arguments.elementAt(0);
        }
      }
    }

    if(Sint.isRegistered<UserService>()) userServiceImpl = Sint.find<UserService>();
    if(Sint.isRegistered<FrequencyService>()) frequencyServiceImpl = Sint.find<FrequencyService>();

    profile = userServiceImpl?.profile;
    isAdmin = (userServiceImpl?.user.userRole.value ?? UserRole.subscriber.value) <= UserRole.admin.value;
    chambers.value = profile?.chambers ?? {};

    chamberPreset.mainFrequency ??= NeomFrequency();
    chamberPreset.neomParameter ??= NeomParameter();
    // Inicializar valores locales desde el preset
    currentFreq.value = chamberPreset.mainFrequency?.frequency ?? NeomGeneratorConstants.defaultFrequency;
    currentVol.value = chamberPreset.neomParameter?.volume ?? 0.5;

    // Ahora verificamos directamente la propiedad binauralFrequency
    if (chamberPreset.binauralFrequency != null) {
      double bFreq = chamberPreset.binauralFrequency!.frequency;
      currentBeat.value = (bFreq - currentFreq.value).abs();
    } else {
      currentBeat.value = 0;
    }

    // Inicializar Player y Recorder
    await _sineEngine.init();
    await initializeRecorder();

    // Inicializar Ticker para animación
    _waveTicker = Ticker((elapsed) {
      if (!isPlaying.value) return;

      final dt = elapsed.inMilliseconds / 1000.0;

      wavePhase.value += dt * currentFreq.value * 0.02;
      wavePhase.value %= (2 * pi);

      painterEngine.updateFromAudio(
        phase: wavePhase.value,
        amplitude: currentVol.value,
        pan: posX.value,
        breath: breathDepth.value,
        modulation: modulationDepth.value,
        neuro: neuroState.value.index / NeomNeuroState.values.length,
        frequency: currentFreq.value,
      );

      painterEngine.tickBinaural(currentBeat.value.abs(), dt);

      // ── Incienso hooks ──
      final coherence = painterEngine.hemisphericCoherence;

      // Detect breath cycle completion (phase wrap)
      final breathPhase = _sineEngine.breathEngine.currentValue;
      if (_prevBreathPhase > 0.8 && breathPhase < 0.2
          && _sineEngine.breathEngine.mode != NeomBreathMode.off) {
        inciensoTracker.onBreathCycle(coherence: coherence);
      }
      _prevBreathPhase = breathPhase;

      // Continuous coherence reading (~every frame)
      inciensoTracker.onCoherenceReading(coherence);

      // Feed recorder with current values
      if (inciensoRecorder.isRecording) {
        inciensoRecorder.updateValues(
          leftHz: currentFreq.value,
          rightHz: currentFreq.value + currentBeat.value,
          coherence: coherence,
          volume: currentVol.value,
          neuroState: neuroState.value,
          breathPhase: breathPhase,
        );
      }

    });

  } catch(e, st) {
    NeomErrorLogger.recordError(e, st, module: 'neom_generator', operation: 'onInit');
  }

}