1. 完成了对音频播放类的完整C++封装,测试通过
2. 修复了LVGL渲染类当中的一些小bug 3. 增加了一些CPU资源占用的日志打印函数,运行在主线程当中 4. 完善了底层通信类的封装,基于websocket,尚未测试
This commit is contained in:
@@ -0,0 +1,248 @@
|
||||
//
|
||||
// Created by misaki on 2025/9/9.
|
||||
//
|
||||
|
||||
#include "AudioOutput.h"
|
||||
#include "esp_log.h"
|
||||
#include <memory>
|
||||
#include "PCM5101.h"
|
||||
|
||||
|
||||
// 初始化静态成员
|
||||
AudioOutput* AudioOutput::instance = nullptr;
|
||||
std::mutex AudioOutput::instanceMutex;
|
||||
|
||||
AudioOutput* AudioOutput::getInstance() {
|
||||
std::lock_guard<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> lock(stateMutex);
|
||||
return currentState;
|
||||
}
|
||||
|
||||
bool AudioOutput::isPlaying() const {
|
||||
std::lock_guard<std::mutex> lock(stateMutex);
|
||||
return currentState == AudioState::PLAYING;
|
||||
}
|
||||
|
||||
bool AudioOutput::isPaused() const {
|
||||
std::lock_guard<std::mutex> lock(stateMutex);
|
||||
return currentState == AudioState::PAUSED;
|
||||
}
|
||||
|
||||
bool AudioOutput::isStopped() const {
|
||||
std::lock_guard<std::mutex> 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<std::mutex> lock(stateMutex);
|
||||
currentState = newState;
|
||||
}
|
||||
Reference in New Issue
Block a user