// // Created by misaki on 2025/9/9. // #include "AudioOutput.h" #include "esp_log.h" #include #include "PCM5101.h" // 初始化静态成员 AudioOutput* AudioOutput::instance = nullptr; std::mutex AudioOutput::instanceMutex; AudioOutput* AudioOutput::getInstance() { std::lock_guard lock(instanceMutex); if (instance == nullptr) { instance = new AudioOutput(); } return instance; } AudioOutput::AudioOutput() : currentState(AudioState::IDLE), currentVolume(Volume_MAX - 2), hardwareInitialized(false) { // 初始化硬件 init(); } AudioOutput::~AudioOutput() { // 停止播放并清理资源 stop(); } bool AudioOutput::init() { std::lock_guard lock(stateMutex); if (hardwareInitialized) { ESP_LOGI("AudioOutput", "Audio hardware already initialized"); return true; } // 初始化SD卡 SDFileManager::getInstance()->tryInitSDCard(); // 初始化音频硬件 Audio_Init(); hardwareInitialized = true; ESP_LOGI("AudioOutput", "Audio hardware initialized successfully"); return hardwareInitialized; } void AudioOutput::tryInitAudioOutput() { ESP_LOGI("AudioOutput", "Trying to initialize audio output......"); } bool AudioOutput::playSync(const char* directory, const char* fileName) { std::lock_guard lock(stateMutex); if (!hardwareInitialized) { ESP_LOGE("AudioOutput", "Audio hardware not initialized"); return false; } // 停止当前播放 TODO:有bug,需要fix // stop(); // 播放新文件 Play_Music(directory, fileName); if (audio_player_get_state() == AUDIO_PLAYER_STATE_PLAYING) { currentState = AudioState::PLAYING; currentFilePath = std::string(directory) + "/" + fileName; return true; } currentState = AudioState::ERROR; return false; } void AudioOutput::playAsync(const char* directory, const char* fileName, AudioCallback callback) { ThreadConfig config = getThreadConfig("play_async"); ThreadManager::createThread(config, [this, directory = std::string(directory), fileName = std::string(fileName), callback]() { this->playInternal(directory.c_str(), fileName.c_str(), callback); }).detach(); } void AudioOutput::playInternal(const char* directory, const char* fileName, AudioCallback callback) { bool success = false; AudioState finalState = AudioState::ERROR; { std::lock_guard lock(stateMutex); if (!hardwareInitialized) { ESP_LOGE("AudioOutput", "Audio hardware not initialized"); finalState = AudioState::ERROR; } else { // 停止当前播放 // stop(); // 播放新文件 Play_Music(directory, fileName); if (audio_player_get_state() == AUDIO_PLAYER_STATE_PLAYING) { currentState = AudioState::PLAYING; currentFilePath = std::string(directory) + "/" + fileName; success = true; finalState = AudioState::PLAYING; } else { currentState = AudioState::ERROR; finalState = AudioState::ERROR; } } } if (callback) { callback(finalState, success ? currentFilePath.c_str() : nullptr); } } bool AudioOutput::pause() { std::lock_guard lock(stateMutex); if (currentState != AudioState::PLAYING) { return false; } Music_pause(); if (audio_player_get_state() == AUDIO_PLAYER_STATE_PAUSE) { currentState = AudioState::PAUSED; return true; } return false; } bool AudioOutput::resume() { std::lock_guard lock(stateMutex); if (currentState != AudioState::PAUSED) { return false; } Music_resume(); if (audio_player_get_state() == AUDIO_PLAYER_STATE_PLAYING) { currentState = AudioState::PLAYING; return true; } return false; } bool AudioOutput::stop() { std::lock_guard lock(stateMutex); if (currentState == AudioState::IDLE || currentState == AudioState::STOPPED) { // 如果当前状态为IDLE或STOPPED,则直接返回成功 return true; } // 暂停播放 Music_pause(); // 内部已经完成关闭文件的操作了 currentState = AudioState::STOPPED; currentFilePath.clear(); return true; } bool AudioOutput::setVolume(uint8_t volume) { std::lock_guard lock(stateMutex); if (volume > Volume_MAX) { ESP_LOGE("AudioOutput", "Volume value %d is out of range (0-%d)", volume, Volume_MAX); return false; } Volume_adjustment(volume); currentVolume = volume; return true; } uint8_t AudioOutput::getVolume() const { std::lock_guard lock(stateMutex); return currentVolume; } uint8_t AudioOutput::getMaxVolume() const { return Volume_MAX; } uint32_t AudioOutput::getDuration() const { return Music_Duration(); } uint32_t AudioOutput::getElapsed() const { return Music_Elapsed(); } uint16_t AudioOutput::getEnergy() const { return Music_Energy(); } AudioState AudioOutput::getState() const { std::lock_guard lock(stateMutex); return currentState; } bool AudioOutput::isPlaying() const { std::lock_guard lock(stateMutex); return currentState == AudioState::PLAYING; } bool AudioOutput::isPaused() const { std::lock_guard lock(stateMutex); return currentState == AudioState::PAUSED; } bool AudioOutput::isStopped() const { std::lock_guard lock(stateMutex); return currentState == AudioState::STOPPED || currentState == AudioState::IDLE; } bool AudioOutput::isFinished() const { return Music_Next_Flag; } ThreadConfig AudioOutput::getThreadConfig(const char* operation) { ThreadConfig config; config.name = "audio_" + std::string(operation); config.core_id = -1; // 不绑定核心 config.stack_size = 4096; config.priority = 5; config.inherit_cfg = false; return config; } void AudioOutput::setState(AudioState newState) { std::lock_guard lock(stateMutex); currentState = newState; }