onInit method
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');
}
}