// // puzzleweave/audio/audio_controller.dart // import 'package:flutter/widgets.dart'; // import 'package:audioplayers/audioplayers.dart'; // import 'package:puzzleweave/settings/settings_controller.dart'; // import 'package:logging/logging.dart'; // enum SfxType { drop, click, tap, pop, appear, alert, star, success, flip, card, cardShort, panstart, panend, panend2 } // /// 允许播放音乐和声音效果。 // class AudioControllerX { // static final _log = Logger('AudioController'); // SettingsController? _settings; // ValueNotifier? _lifecycleNotifier; // // 1. BGM 播放器 (使用常规模式进行流式传输,专用于音乐) // final AudioPlayer _musicPlayer = AudioPlayer(); // // 2. 音效音频池 (用于低延迟播放 SFX) // // Key: SfxType, Value: AudioPool 实例 // final Map _sfxPools = {}; // // 预加载的 BGM 文件路径 // final String _bgmAsset = 'audio/bgm/canon.mp3'; // // 所有音效文件映射 // static const Map _sfxPaths = { // SfxType.drop: 'audio/sfx/button_click8.mp3', // SfxType.click: 'audio/sfx/click2.mp3', // SfxType.tap: 'audio/sfx/tap.mp3', // SfxType.pop: 'audio/sfx/pop.mp3', // SfxType.appear: 'audio/sfx/appear.mp3', // SfxType.alert: 'audio/sfx/alert.mp3', // SfxType.star: 'audio/sfx/star.mp3', // SfxType.success: 'audio/sfx/win.mp3', // SfxType.card: 'audio/sfx/card.mp3', // SfxType.cardShort: 'audio/sfx/card2.mp3', // SfxType.flip: 'audio/sfx/flip.mp3', // SfxType.panstart: 'audio/sfx/pan_start.mp3', // SfxType.panend: 'audio/sfx/pan_end.mp3', // SfxType.panend2: 'audio/sfx/pan_end2.mp3', // }; // AudioControllerX() { // // 配置 BGM 播放器:设置为循环模式 // _musicPlayer.setReleaseMode(ReleaseMode.loop); // } // /// 在应用启动时异步调用,用于预加载所有音乐和音效。 // Future initialize() async { // // 1. 预加载 BGM // await _musicPlayer.setSource(AssetSource(_bgmAsset)); // // 2. 预加载所有 SFX 到 AudioPool 中 (实现真正的低延迟) // final futures = _sfxPaths.entries.map((entry) async { // final type = entry.key; // final path = entry.value; // // ⚠️ 修复:使用 AudioPool.createFromAssetSource 替换 fromAsset // final pool = await AudioPool.createFromAsset( // path: path, // 直接传入 String 路径 // maxPlayers: type == SfxType.card ? 10 : 3, // ); // _sfxPools[type] = pool; // }).toList(); // await Future.wait(futures); // _log.info('All sounds and music preloaded successfully via AudioPool.'); // } // void dispose() { // _lifecycleNotifier?.removeListener(_handleAppLifecycle); // stopMusic(); // // 停止并清理所有的音频池,释放原生资源 // for (final pool in _sfxPools.values) { // pool.dispose(); // } // _sfxPools.clear(); // _musicPlayer.dispose(); // } // /// Enables the [AudioController] to listen to [AppLifecycleState] events... // void attachLifecycleNotifier(ValueNotifier lifecycleNotifier) { // _lifecycleNotifier?.removeListener(_handleAppLifecycle); // lifecycleNotifier.addListener(_handleAppLifecycle); // _lifecycleNotifier = lifecycleNotifier; // } // /// Enables the [AudioController] to track changes to settings... // void attachSettings(SettingsController settingsController) { // if (_settings == settingsController) return; // final oldSettings = _settings; // if (oldSettings != null) { // oldSettings.music.removeListener(_musicOnHandler); // oldSettings.sound.removeListener(_soundOnHandler); // } // _settings = settingsController; // settingsController.music.addListener(_musicOnHandler); // settingsController.sound.addListener(_soundOnHandler); // } // /// Plays a single sound effect, defined by [type]. // /// 使用 AudioPool 实现极低延迟播放。 // void playSfx(SfxType type, {Duration? duration}) async { // final soundsOn = _settings?.sound.value ?? false; // if (!soundsOn) { // _log.info(() => 'Ignoring playing sound ($type) because sounds are turned off.'); // return; // } // final pool = _sfxPools[type]; // if (pool == null) { // _log.severe('Missing audio pool for SFX type: $type'); // return; // } // // 核心优化:从 AudioPool 快速启动播放。 // await pool.start(volume: 1.0); // if (duration != null) { // _log.warning('Duration control is complex with AudioPool; generally SFX should be short.'); // } // } // void _handleAppLifecycle() { // switch (_lifecycleNotifier!.value) { // case AppLifecycleState.paused: // case AppLifecycleState.detached: // case AppLifecycleState.hidden: // case AppLifecycleState.inactive: // pauseMusic(); // break; // case AppLifecycleState.resumed: // startMusic(); // break; // } // } // void _musicOnHandler() { // if (_settings!.music.value) { // startMusic(); // } else { // stopMusic(); // } // } // void _soundOnHandler() { // // 声音设置关闭时,不需要特殊处理 AudioPool 播放的短音效 // } // void setMusicVolume(double volume) { // _musicPlayer.setVolume(volume); // _log.info('Music volume set to $volume'); // } // void startMusic() async { // _log.info('starting music'); // final musicOn = _settings?.music.value ?? false; // if (!musicOn) { // _log.info(() => 'Ignoring playing music because music are turned off.'); // return; // } // // 假设我们希望 BGM 默认音量为 0.5 // const double defaultBGMVolume = 0.1; // final state = _musicPlayer.state; // if (state == PlayerState.playing) return; // // 如果音乐已经停止或未播放,则重新设置源并播放 // if (state == PlayerState.stopped || state == PlayerState.disposed) { // await _musicPlayer.setSource(AssetSource(_bgmAsset)); // await _musicPlayer.setVolume(defaultBGMVolume); // await _musicPlayer.resume(); // } else { // // 从暂停状态恢复 // await _musicPlayer.resume(); // } // } // void stopMusic() { // _log.info('Stopping music'); // _musicPlayer.stop(); // } // void pauseMusic() { // _log.info('pause music'); // _musicPlayer.pause(); // } // Future resumeMusic() async { // _log.info('Resuming music'); // final musicOn = _settings?.music.value ?? false; // if (musicOn) { // _musicPlayer.resume(); // } // } // void _stopSound() { // // AudioPool 播放的短音效不需要手动停止 // } // }