This commit is contained in:
2025-10-24 18:17:58 +08:00
commit c98e7e61b3
48 changed files with 10175 additions and 0 deletions

192
CMakeLists.txt Normal file
View File

@@ -0,0 +1,192 @@
# ================================================================================================
# C++23 跨平台音频后端系统 - 主CMake配置文件
# ================================================================================================
# 项目: Audio Backend Framework
# 描述: 跨平台Windows、Linux、macOSC++23音频后端系统
# 架构: 多进程架构插件沙盒隔离ZeroMQ + Boost共享内存通信
# ================================================================================================
cmake_minimum_required(VERSION 3.20)
# ================================================================================================
# 项目定义
# ================================================================================================
project(AudioBackend
VERSION 1.0.0
DESCRIPTION "Cross-platform C++23 Audio Backend System with Plugin Sandboxing"
LANGUAGES CXX C
)
# ================================================================================================
# C++标准配置
# ================================================================================================
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
message(STATUS "")
message(STATUS "========================================")
message(STATUS " ${PROJECT_NAME} v${PROJECT_VERSION}")
message(STATUS "========================================")
message(STATUS "C++ 标准: C++${CMAKE_CXX_STANDARD}")
message(STATUS "构建系统: CMake ${CMAKE_VERSION}")
message(STATUS "编译器: ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}")
message(STATUS "操作系统: ${CMAKE_SYSTEM_NAME}")
message(STATUS "架构: ${CMAKE_SYSTEM_PROCESSOR}")
# ================================================================================================
# 构建输出目录配置
# ================================================================================================
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
# 多配置生成器的输出目录
foreach(OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES})
string(TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/lib)
endforeach()
# ================================================================================================
# CMake模块路径
# ================================================================================================
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
# ================================================================================================
# 包含CMake模块
# ================================================================================================
include(detect_os) # 操作系统检测
include(project_cpp_standard) # C++标准配置
include(build_options) # 构建选项
include(compiler_options) # 编译器选项
include(dependencies) # 依赖管理
include(install_config) # 安装配置
# ================================================================================================
# 配置构建类型
# ================================================================================================
configure_build_type()
# ================================================================================================
# 定义构建选项
# ================================================================================================
define_feature_options()
# ================================================================================================
# 打印构建选项摘要
# ================================================================================================
print_build_options()
# ================================================================================================
# Conan依赖集成
# ================================================================================================
# 检查Conan 2.x工具链文件
if(EXISTS "${CMAKE_BINARY_DIR}/build/generators/conan_toolchain.cmake")
include(${CMAKE_BINARY_DIR}/build/generators/conan_toolchain.cmake)
message(STATUS "使用Conan 2.x工具链: build/generators/conan_toolchain.cmake")
elseif(EXISTS "${CMAKE_BINARY_DIR}/generators/conan_toolchain.cmake")
include(${CMAKE_BINARY_DIR}/generators/conan_toolchain.cmake)
message(STATUS "使用Conan 2.x工具链: generators/conan_toolchain.cmake")
elseif(EXISTS "${CMAKE_BINARY_DIR}/conan_toolchain.cmake")
include(${CMAKE_BINARY_DIR}/conan_toolchain.cmake)
message(STATUS "使用Conan 2.x工具链: conan_toolchain.cmake")
endif()
# ================================================================================================
# 配置所有依赖项
# ================================================================================================
setup_all_dependencies()
# ================================================================================================
# 应用编译器配置
# ================================================================================================
apply_compiler_configuration()
# ================================================================================================
# 创建项目配置接口库
# ================================================================================================
setup_project_options(
STANDARD 23
INTERFACE_TARGET audio_backend_project_options
)
# ================================================================================================
# 全局编译定义
# ================================================================================================
add_compile_definitions(
$<$<CONFIG:Debug>:AUDIO_BACKEND_DEBUG>
$<$<CONFIG:Release>:AUDIO_BACKEND_RELEASE>
AUDIO_BACKEND_VERSION_MAJOR=${PROJECT_VERSION_MAJOR}
AUDIO_BACKEND_VERSION_MINOR=${PROJECT_VERSION_MINOR}
AUDIO_BACKEND_VERSION_PATCH=${PROJECT_VERSION_PATCH}
)
# ================================================================================================
# 平台特定配置
# ================================================================================================
if(WIN32)
add_compile_definitions(
NOMINMAX # 防止Windows.h定义min/max宏
WIN32_LEAN_AND_MEAN # 减少Windows.h包含的内容
_WIN32_WINNT=0x0A00 # Windows 10
)
endif()
# ================================================================================================
# 注意: 每个模块将有自己的CMakeLists.txt文件管理自己的包含路径
# 不再使用全局include_directories而是在各模块内使用target_include_directories
# ================================================================================================
# ================================================================================================
# 子目录
# ================================================================================================
message(STATUS "")
message(STATUS "=== 配置子模块 ===")
# 源代码目录
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src)
add_subdirectory(src)
message(STATUS "添加源代码目录: src/")
endif()
# 测试目录
if(DAW_ENABLE_TESTS AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/tests)
enable_testing()
add_subdirectory(tests)
message(STATUS "添加测试目录: tests/")
endif()
# 示例目录
if(DAW_ENABLE_EXAMPLES AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/examples)
add_subdirectory(examples)
message(STATUS "添加示例目录: examples/")
endif()
# 文档目录
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/docs)
message(STATUS "文档目录: docs/")
endif()
# ================================================================================================
# 安装和打包配置
# ================================================================================================
setup_install_and_packaging()
# ================================================================================================
# 构建摘要
# ================================================================================================
message(STATUS "")
message(STATUS "========================================")
message(STATUS " 构建配置完成")
message(STATUS "========================================")
message(STATUS "项目名称: ${PROJECT_NAME}")
message(STATUS "项目版本: ${PROJECT_VERSION}")
message(STATUS "构建类型: ${CMAKE_BUILD_TYPE}")
message(STATUS "C++标准: C++${CMAKE_CXX_STANDARD}")
message(STATUS "安装前缀: ${CMAKE_INSTALL_PREFIX}")
message(STATUS "二进制输出: ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
message(STATUS "库输出: ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}")
message(STATUS "========================================")
message(STATUS "")

213
build.bat Normal file
View File

@@ -0,0 +1,213 @@
@echo off
REM ================================================================================================
REM Audio Backend Framework - Windows构建脚本
REM ================================================================================================
REM 描述: Windows平台的自动化构建脚本
REM 功能: Conan依赖安装、CMake配置、项目编译
REM 用法: build.bat [Debug|Release|clean|help]
REM ================================================================================================
setlocal EnableDelayedExpansion
REM 设置项目根目录
set PROJECT_ROOT=%~dp0
cd /d %PROJECT_ROOT%
REM 默认构建类型
set BUILD_TYPE=Release
set CLEAN_BUILD=0
REM 解析命令行参数
if "%1"=="" goto :parse_done
if /i "%1"=="Debug" set BUILD_TYPE=Debug
if /i "%1"=="Release" set BUILD_TYPE=Release
if /i "%1"=="clean" set CLEAN_BUILD=1
if /i "%1"=="help" goto :show_help
if /i "%1"=="-h" goto :show_help
if /i "%1"=="--help" goto :show_help
:parse_done
echo.
echo ========================================
echo Audio Backend Framework 构建系统
echo ========================================
echo 项目目录: %PROJECT_ROOT%
echo 构建类型: %BUILD_TYPE%
echo.
REM ================================================================================================
REM 清理构建
REM ================================================================================================
if %CLEAN_BUILD%==1 (
echo [清理] 正在清理构建目录...
if exist build (
rmdir /s /q build
echo [清理] 已删除 build 目录
)
if exist CMakeCache.txt (
del /f /q CMakeCache.txt
echo [清理] 已删除 CMakeCache.txt
)
echo [清理] 清理完成
goto :end
)
REM ================================================================================================
REM 检查必要工具
REM ================================================================================================
echo [检查] 验证必要工具...
where cmake >nul 2>nul
if %ERRORLEVEL% neq 0 (
echo [错误] 未找到 CMake请先安装 CMake
echo 下载地址: https://cmake.org/download/
goto :error
)
where conan >nul 2>nul
if %ERRORLEVEL% neq 0 (
echo [错误] 未找到 Conan请先安装 Conan
echo 安装命令: pip install conan
goto :error
)
echo [检查] ✓ CMake 已安装
echo [检查] ✓ Conan 已安装
REM ================================================================================================
REM 安装Conan依赖
REM ================================================================================================
echo.
echo [Conan] 正在安装依赖包...
echo [Conan] 构建类型: %BUILD_TYPE%
echo [Conan] C++标准: C++23
echo.
REM 创建build目录
if not exist build mkdir build
cd build
REM 执行Conan安装
conan install .. --output-folder=. --build=missing --settings=build_type=%BUILD_TYPE% --settings=compiler.cppstd=23
if %ERRORLEVEL% neq 0 (
echo [错误] Conan依赖安装失败
cd ..
goto :error
)
echo.
echo [Conan] ✓ 依赖安装成功
echo.
REM ================================================================================================
REM 配置CMake项目
REM ================================================================================================
echo [CMake] 正在配置项目...
echo [CMake] 构建类型: %BUILD_TYPE%
echo.
REM CMake配置
cmake .. -G "Visual Studio 17 2022" ^
-DCMAKE_BUILD_TYPE=%BUILD_TYPE% ^
-DCMAKE_TOOLCHAIN_FILE=generators/conan_toolchain.cmake ^
-DDAW_ENABLE_SIMD=ON ^
-DDAW_ENABLE_AVX512=ON ^
-DDAW_ENABLE_TESTS=ON ^
-DDAW_ENABLE_EXAMPLES=ON
if %ERRORLEVEL% neq 0 (
echo [错误] CMake配置失败
cd ..
goto :error
)
echo.
echo [CMake] ✓ 项目配置成功
echo.
REM ================================================================================================
REM 编译项目
REM ================================================================================================
echo [编译] 正在编译项目...
echo [编译] 配置: %BUILD_TYPE%
echo.
cmake --build . --config %BUILD_TYPE% --parallel
if %ERRORLEVEL% neq 0 (
echo [错误] 项目编译失败
cd ..
goto :error
)
echo.
echo [编译] ✓ 项目编译成功
echo.
REM 返回项目根目录
cd ..
REM ================================================================================================
REM 构建成功
REM ================================================================================================
echo.
echo ========================================
echo 构建成功!
echo ========================================
echo 构建类型: %BUILD_TYPE%
echo 输出目录: %PROJECT_ROOT%build\bin
echo 库目录: %PROJECT_ROOT%build\lib
echo.
echo 运行测试: cd build ^&^& ctest -C %BUILD_TYPE%
echo.
goto :end
REM ================================================================================================
REM 帮助信息
REM ================================================================================================
:show_help
echo.
echo Audio Backend Framework - Windows 构建脚本
echo.
echo 用法:
echo build.bat [选项]
echo.
echo 选项:
echo Debug - 构建Debug版本包含调试符号
echo Release - 构建Release版本默认优化编译
echo clean - 清理所有构建文件
echo help - 显示此帮助信息
echo.
echo 示例:
echo build.bat # 构建Release版本
echo build.bat Debug # 构建Debug版本
echo build.bat clean # 清理构建文件
echo.
echo 依赖要求:
echo - CMake 3.20+
echo - Conan 2.x
echo - Visual Studio 2022 或更高版本
echo - C++23 支持的编译器
echo.
goto :end
REM ================================================================================================
REM 错误处理
REM ================================================================================================
:error
echo.
echo ========================================
echo 构建失败!
echo ========================================
echo.
exit /b 1
REM ================================================================================================
REM 正常退出
REM ================================================================================================
:end
endlocal
exit /b 0

310
build.sh Normal file
View File

@@ -0,0 +1,310 @@
#!/bin/bash
# ================================================================================================
# Audio Backend Framework - Linux/macOS构建脚本
# ================================================================================================
# 描述: Linux和macOS平台的自动化构建脚本
# 功能: Conan依赖安装、CMake配置、项目编译
# 用法: ./build.sh [Debug|Release|clean|help]
# ================================================================================================
set -e # 遇到错误立即退出
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 项目配置
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BUILD_TYPE="Release"
CLEAN_BUILD=0
JOBS=$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4)
# 检测操作系统
detect_os() {
if [[ "$OSTYPE" == "darwin"* ]]; then
OS="macOS"
CMAKE_GENERATOR="Unix Makefiles"
elif [[ "$OSTYPE" == "linux"* ]]; then
OS="Linux"
CMAKE_GENERATOR="Unix Makefiles"
else
echo -e "${RED}[错误] 不支持的操作系统: $OSTYPE${NC}"
exit 1
fi
}
# 显示帮助信息
show_help() {
echo
echo "Audio Backend Framework - Linux/macOS 构建脚本"
echo
echo "用法:"
echo " ./build.sh [选项]"
echo
echo "选项:"
echo " Debug - 构建Debug版本包含调试符号"
echo " Release - 构建Release版本默认优化编译"
echo " clean - 清理所有构建文件"
echo " help - 显示此帮助信息"
echo
echo "示例:"
echo " ./build.sh # 构建Release版本"
echo " ./build.sh Debug # 构建Debug版本"
echo " ./build.sh clean # 清理构建文件"
echo
echo "依赖要求:"
echo " - CMake 3.20+"
echo " - Conan 2.x"
echo " - GCC 13+ 或 Clang 17+"
echo " - C++23 支持的编译器"
echo
echo "系统包依赖 (Ubuntu/Debian):"
echo " sudo apt install build-essential cmake python3-pip"
echo " sudo apt install libasound2-dev libpulse-dev libjack-jackd2-dev"
echo
echo "系统包依赖 (macOS):"
echo " brew install cmake conan"
echo
}
# 解析命令行参数
parse_args() {
case "${1:-}" in
"Debug"|"debug")
BUILD_TYPE="Debug"
;;
"Release"|"release"|"")
BUILD_TYPE="Release"
;;
"clean")
CLEAN_BUILD=1
;;
"help"|"-h"|"--help")
show_help
exit 0
;;
*)
echo -e "${RED}[错误] 未知参数: $1${NC}"
echo "使用 './build.sh help' 查看帮助"
exit 1
;;
esac
}
# 打印标题
print_header() {
echo
echo "========================================"
echo " Audio Backend Framework 构建系统"
echo "========================================"
echo "项目目录: $PROJECT_ROOT"
echo "操作系统: $OS"
echo "构建类型: $BUILD_TYPE"
echo "并行任务: $JOBS"
echo
}
# 清理构建
clean_build() {
echo -e "${YELLOW}[清理] 正在清理构建目录...${NC}"
if [ -d "build" ]; then
rm -rf build
echo -e "${GREEN}[清理] ✓ 已删除 build 目录${NC}"
fi
if [ -f "CMakeCache.txt" ]; then
rm -f CMakeCache.txt
echo -e "${GREEN}[清理] ✓ 已删除 CMakeCache.txt${NC}"
fi
echo -e "${GREEN}[清理] ✓ 清理完成${NC}"
exit 0
}
# 检查必要工具
check_tools() {
echo -e "${BLUE}[检查] 验证必要工具...${NC}"
# 检查CMake
if ! command -v cmake &> /dev/null; then
echo -e "${RED}[错误] 未找到 CMake请先安装 CMake${NC}"
if [[ "$OS" == "macOS" ]]; then
echo " 安装命令: brew install cmake"
else
echo " 安装命令: sudo apt install cmake"
fi
exit 1
fi
# 检查Conan
if ! command -v conan &> /dev/null; then
echo -e "${RED}[错误] 未找到 Conan请先安装 Conan${NC}"
echo " 安装命令: pip3 install conan"
exit 1
fi
# 检查编译器
if [[ "$OS" == "macOS" ]]; then
if ! command -v clang++ &> /dev/null; then
echo -e "${RED}[错误] 未找到 Clang++,请安装 Xcode Command Line Tools${NC}"
echo " 安装命令: xcode-select --install"
exit 1
fi
else
if ! command -v g++ &> /dev/null && ! command -v clang++ &> /dev/null; then
echo -e "${RED}[错误] 未找到 G++ 或 Clang++,请安装编译器${NC}"
echo " 安装令: sudo apt install build-essential"
exit 1
fi
fi
echo -e "${GREEN}[检查] ✓ CMake 已安装$(cmake --version | head -n1 | cut -d' ' -f3)${NC}"
echo -e "${GREEN}[检查] ✓ Conan 已安装$(conan --version 2>/dev/null | cut -d' ' -f3)${NC}"
echo -e "${GREEN}[检查] ✓ 编译器已安装${NC}"
}
# 安装系统依赖提示
check_system_deps() {
if [[ "$OS" == "Linux" ]]; then
echo -e "${YELLOW}[提示] 确保已安装音频开发库:${NC}"
echo " sudo apt install libasound2-dev libpulse-dev libjack-jackd2-dev"
echo " sudo apt install libfftw3-dev libsndfile1-dev libsamplerate0-dev"
echo
fi
}
# 安装Conan依赖
install_dependencies() {
echo
echo -e "${BLUE}[Conan] 正在安装依赖包...${NC}"
echo -e "${BLUE}[Conan] 构建类型: $BUILD_TYPE${NC}"
echo -e "${BLUE}[Conan] C++标准: C++23${NC}"
echo
# 创建build目录
mkdir -p build
cd build
# 执行Conan安装
conan install .. \
--output-folder=. \
--build=missing \
--settings=build_type="$BUILD_TYPE" \
--settings=compiler.cppstd=23
echo
echo -e "${GREEN}[Conan] ✓ 依赖安装成功${NC}"
echo
}
# 配置CMake项目
configure_cmake() {
echo -e "${BLUE}[CMake] 正在配置项目...${NC}"
echo -e "${BLUE}[CMake] 构建类型: $BUILD_TYPE${NC}"
echo -e "${BLUE}[CMake] 生成器: $CMAKE_GENERATOR${NC}"
echo
# 设置平台特定的选项
CMAKE_ARGS=()
CMAKE_ARGS+=("-G" "$CMAKE_GENERATOR")
CMAKE_ARGS+=("-DCMAKE_BUILD_TYPE=$BUILD_TYPE")
CMAKE_ARGS+=("-DCMAKE_TOOLCHAIN_FILE=generators/conan_toolchain.cmake")
CMAKE_ARGS+=("-DDAW_ENABLE_SIMD=ON")
CMAKE_ARGS+=("-DDAW_ENABLE_TESTS=ON")
CMAKE_ARGS+=("-DDAW_ENABLE_EXAMPLES=ON")
# 根据系统架构设置AVX512支持
if [[ $(uname -m) == "x86_64" ]]; then
CMAKE_ARGS+=("-DDAW_ENABLE_AVX512=ON")
else
CMAKE_ARGS+=("-DDAW_ENABLE_AVX512=OFF")
fi
# macOS特定配置
if [[ "$OS" == "macOS" ]]; then
CMAKE_ARGS+=("-DCMAKE_OSX_DEPLOYMENT_TARGET=11.0")
fi
# 执行CMake配置
cmake .. "${CMAKE_ARGS[@]}"
echo
echo -e "${GREEN}[CMake] ✓ 项目配置成功${NC}"
echo
}
# 编译项目
build_project() {
echo -e "${BLUE}[编译] 正在编译项目...${NC}"
echo -e "${BLUE}[编译] 配置: $BUILD_TYPE${NC}"
echo -e "${BLUE}[编译] 并行任务: $JOBS${NC}"
echo
# 编译项目
cmake --build . --config "$BUILD_TYPE" --parallel "$JOBS"
echo
echo -e "${GREEN}[编译] ✓ 项目编译成功${NC}"
echo
}
# 显示构建结果
show_results() {
cd "$PROJECT_ROOT"
echo
echo "========================================"
echo " 构建成功!"
echo "========================================"
echo "构建类型: $BUILD_TYPE"
echo "输出目录: $PROJECT_ROOT/build/bin"
echo "库目录: $PROJECT_ROOT/build/lib"
echo
echo "运行测试: cd build && ctest -C $BUILD_TYPE"
echo "安装项目: cd build && make install"
echo
}
# 主函数
main() {
cd "$PROJECT_ROOT"
# 检测操作系统
detect_os
# 解析参数
parse_args "$1"
# 显示标题
print_header
# 处理清理
if [ $CLEAN_BUILD -eq 1 ]; then
clean_build
fi
# 检查工具
check_tools
# 检查系统依赖
check_system_deps
# 安装依赖
install_dependencies
# 配置项目
configure_cmake
# 编译项目
build_project
# 显示结果
show_results
}
# 执行主函数
main "$@"

103
cmake/build_options.cmake Normal file
View File

@@ -0,0 +1,103 @@
# ================================================================================================
# DAW Backend Framework - 构建选项配置模块
# 描述: 定义所有项目构建选项,包括功能开关、插件支持和开发工具
# ================================================================================================
# ================================================================================================
# 构建类型配置
# ================================================================================================
function(configure_build_type)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING
"Choose build type: Debug Release RelWithDebInfo MinSizeRel" FORCE)
message(STATUS "未指定构建类型,默认使用: Release")
endif()
message(STATUS "当前构建类型: ${CMAKE_BUILD_TYPE}")
endfunction()
# ================================================================================================
# 功能选项定义
# ================================================================================================
function(define_feature_options)
# 功能选项
option(DAW_ENABLE_TESTS "Enable building tests" ON)
option(DAW_ENABLE_EXAMPLES "Enable building examples" ON)
option(DAW_ENABLE_TOOLS "Enable building tools" ON)
option(DAW_ENABLE_BENCHMARKS "Enable building benchmarks" ON)
# 插件支持选项
option(DAW_ENABLE_VST2 "Enable VST2 plugin support" ON)
option(DAW_ENABLE_VST3 "Enable VST3 plugin support" ON)
option(DAW_ENABLE_CLAP "Enable CLAP plugin support" ON)
# 系统特性选项
option(DAW_ENABLE_SANDBOX "Enable plugin sandboxing" ON)
option(DAW_ENABLE_NETWORK "Enable network communication" ON)
option(DAW_ENABLE_SIMD "Enable SIMD optimizations" ON)
option(DAW_ENABLE_AVX512 "Enable AVX512 optimizations" ON)
option(DAW_ENABLE_PROFILING "Enable profiling support" OFF)
# IPC系统选项
option(ENABLE_ENHANCED_IPC "Enable enhanced IPC system (ZeroMQ + Shared Memory)" ON)
# 开发选项
option(DAW_ENABLE_ASAN "Enable AddressSanitizer" OFF)
option(DAW_ENABLE_TSAN "Enable ThreadSanitizer" OFF)
option(DAW_ENABLE_UBSAN "Enable UndefinedBehaviorSanitizer" OFF)
option(DAW_ENABLE_COVERAGE "Enable code coverage" OFF)
# 将选项提升到父作用域
set(DAW_ENABLE_TESTS ${DAW_ENABLE_TESTS} PARENT_SCOPE)
set(DAW_ENABLE_EXAMPLES ${DAW_ENABLE_EXAMPLES} PARENT_SCOPE)
set(DAW_ENABLE_TOOLS ${DAW_ENABLE_TOOLS} PARENT_SCOPE)
set(DAW_ENABLE_BENCHMARKS ${DAW_ENABLE_BENCHMARKS} PARENT_SCOPE)
set(DAW_ENABLE_VST2 ${DAW_ENABLE_VST2} PARENT_SCOPE)
set(DAW_ENABLE_VST3 ${DAW_ENABLE_VST3} PARENT_SCOPE)
set(DAW_ENABLE_CLAP ${DAW_ENABLE_CLAP} PARENT_SCOPE)
set(DAW_ENABLE_SANDBOX ${DAW_ENABLE_SANDBOX} PARENT_SCOPE)
set(DAW_ENABLE_NETWORK ${DAW_ENABLE_NETWORK} PARENT_SCOPE)
set(DAW_ENABLE_SIMD ${DAW_ENABLE_SIMD} PARENT_SCOPE)
set(DAW_ENABLE_AVX512 ${DAW_ENABLE_AVX512} PARENT_SCOPE)
set(DAW_ENABLE_PROFILING ${DAW_ENABLE_PROFILING} PARENT_SCOPE)
set(ENABLE_ENHANCED_IPC ${ENABLE_ENHANCED_IPC} PARENT_SCOPE)
set(DAW_ENABLE_ASAN ${DAW_ENABLE_ASAN} PARENT_SCOPE)
set(DAW_ENABLE_TSAN ${DAW_ENABLE_TSAN} PARENT_SCOPE)
set(DAW_ENABLE_UBSAN ${DAW_ENABLE_UBSAN} PARENT_SCOPE)
set(DAW_ENABLE_COVERAGE ${DAW_ENABLE_COVERAGE} PARENT_SCOPE)
message(STATUS "构建选项配置完成")
endfunction()
# ================================================================================================
# 打印构建选项摘要
# ================================================================================================
function(print_build_options)
message(STATUS "")
message(STATUS "=== 功能选项 ===")
message(STATUS " 测试: ${DAW_ENABLE_TESTS}")
message(STATUS " 示例: ${DAW_ENABLE_EXAMPLES}")
message(STATUS " 工具: ${DAW_ENABLE_TOOLS}")
message(STATUS " 基准测试: ${DAW_ENABLE_BENCHMARKS}")
message(STATUS "")
message(STATUS "=== 插件支持 ===")
message(STATUS " VST2: ${DAW_ENABLE_VST2}")
message(STATUS " VST3: ${DAW_ENABLE_VST3}")
message(STATUS " CLAP: ${DAW_ENABLE_CLAP}")
message(STATUS "")
message(STATUS "=== 系统特性 ===")
message(STATUS " 沙盒: ${DAW_ENABLE_SANDBOX}")
message(STATUS " 网络: ${DAW_ENABLE_NETWORK}")
message(STATUS " SIMD优化: ${DAW_ENABLE_SIMD}")
message(STATUS " AVX512优化: ${DAW_ENABLE_AVX512}")
message(STATUS " 性能分析: ${DAW_ENABLE_PROFILING}")
message(STATUS "")
message(STATUS "=== IPC系统 ===")
message(STATUS " 增强型IPC: ${ENABLE_ENHANCED_IPC}")
message(STATUS "")
message(STATUS "=== 开发工具 ===")
message(STATUS " ASAN: ${DAW_ENABLE_ASAN}")
message(STATUS " TSAN: ${DAW_ENABLE_TSAN}")
message(STATUS " UBSAN: ${DAW_ENABLE_UBSAN}")
message(STATUS " 覆盖率: ${DAW_ENABLE_COVERAGE}")
endfunction()

View File

@@ -0,0 +1,170 @@
# ================================================================================================
# DAW Backend Framework - 编译器选项配置模块
# 描述: 配置编译器特定选项、警告级别和优化设置
# ================================================================================================
# ================================================================================================
# 配置编译器选项
# ================================================================================================
function(configure_compiler_options)
# 使用生成器表达式为多配置生成器如Visual Studio正确配置选项
if(MSVC)
# Debug配置特定设置
add_compile_options(
$<$<CONFIG:Debug>:/Zi> # 调试信息
$<$<CONFIG:Debug>:/Od> # 禁用优化
$<$<CONFIG:Debug>:/RTC1> # 运行时检查
$<$<CONFIG:Debug>:/W4> # 严格警告
)
add_compile_definitions(
$<$<CONFIG:Debug>:DAW_DEBUG_BUILD>
)
# Release配置特定设置
add_compile_options(
$<$<CONFIG:Release>:/O2> # 最大优化
$<$<CONFIG:Release>:/Ob2> # 内联展开
$<$<CONFIG:Release>:/Zi> # 调试信息用于调试Release版本
)
add_compile_definitions(
$<$<CONFIG:Release>:DAW_RELEASE_BUILD>
$<$<CONFIG:Release>:NDEBUG>
)
# RelWithDebInfo配置
add_compile_options(
$<$<CONFIG:RelWithDebInfo>:/O2>
$<$<CONFIG:RelWithDebInfo>:/Ob1>
$<$<CONFIG:RelWithDebInfo>:/Zi>
)
add_compile_definitions(
$<$<CONFIG:RelWithDebInfo>:DAW_RELEASE_BUILD>
$<$<CONFIG:RelWithDebInfo>:NDEBUG>
)
# MinSizeRel配置
add_compile_options(
$<$<CONFIG:MinSizeRel>:/O1>
$<$<CONFIG:MinSizeRel>:/Ob1>
$<$<CONFIG:MinSizeRel>:/Zi>
)
add_compile_definitions(
$<$<CONFIG:MinSizeRel>:DAW_RELEASE_BUILD>
$<$<CONFIG:MinSizeRel>:NDEBUG>
)
message(STATUS "MSVC编译器选项已配置支持多配置生成器")
else()
# 非MSVC编译器的传统配置
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
add_compile_definitions(DAW_DEBUG_BUILD)
add_compile_options(-g -O0 -fno-omit-frame-pointer)
add_compile_options(-Wall -Wextra -Wpedantic)
message(STATUS "Debug模式: 启用调试符号,禁用优化,启用严格警告")
else()
add_compile_definitions(DAW_RELEASE_BUILD NDEBUG)
add_compile_options(-O3 -DNDEBUG -march=native)
message(STATUS "Release模式: 启用最高级别优化")
endif()
# 启用更好的诊断信息
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
add_compile_options(-fdiagnostics-color=always)
add_compile_options(-ftemplate-backtrace-limit=0)
message(STATUS "启用彩色诊断和完整模板回溯")
endif()
endif()
endfunction()
# ================================================================================================
# 配置SIMD优化扩展AVX512支持
# ================================================================================================
function(configure_simd_optimizations)
if(DAW_ENABLE_SIMD)
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64")
# 检测编译器支持
include(CheckCXXCompilerFlag)
# AVX2支持保持现有
if(MSVC)
check_cxx_compiler_flag("/arch:AVX2" COMPILER_SUPPORTS_AVX2)
if(COMPILER_SUPPORTS_AVX2)
add_compile_options(/arch:AVX2)
add_compile_definitions(DAW_ENABLE_AVX2)
message(STATUS "SIMD优化: 启用AVX2指令集")
endif()
else()
check_cxx_compiler_flag("-mavx2" COMPILER_SUPPORTS_AVX2)
if(COMPILER_SUPPORTS_AVX2)
add_compile_options(-mavx2 -mfma)
add_compile_definitions(DAW_ENABLE_AVX2)
message(STATUS "SIMD优化: 启用AVX2指令集")
endif()
endif()
# AVX512支持新增
if(DAW_ENABLE_AVX512)
if(MSVC)
check_cxx_compiler_flag("/arch:AVX512" COMPILER_SUPPORTS_AVX512)
if(COMPILER_SUPPORTS_AVX512)
add_compile_options(/arch:AVX512)
add_compile_definitions(DAW_ENABLE_AVX512)
message(STATUS "SIMD优化: 启用AVX512指令集")
else()
message(WARNING "编译器不支持AVX512降级到AVX2")
endif()
else()
check_cxx_compiler_flag("-mavx512f" COMPILER_SUPPORTS_AVX512F)
check_cxx_compiler_flag("-mavx512vl" COMPILER_SUPPORTS_AVX512VL)
check_cxx_compiler_flag("-mavx512bw" COMPILER_SUPPORTS_AVX512BW)
if(COMPILER_SUPPORTS_AVX512F AND COMPILER_SUPPORTS_AVX512VL)
add_compile_options(-mavx512f -mavx512vl)
add_compile_definitions(DAW_ENABLE_AVX512)
if(COMPILER_SUPPORTS_AVX512BW)
add_compile_options(-mavx512bw)
add_compile_definitions(DAW_ENABLE_AVX512BW)
endif()
message(STATUS "SIMD优化: 启用AVX512指令集")
else()
message(WARNING "编译器不支持完整AVX512降级到AVX2")
endif()
endif()
endif()
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "arm|aarch64|ARM64")
# ARM平台检测NEON支持
include(CheckCXXCompilerFlag)
if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|ARM64")
# AArch64: NEON默认可用
add_compile_definitions(DAW_ENABLE_NEON)
message(STATUS "SIMD优化: 启用ARM64 NEON指令集")
else()
# ARM32: 检测NEON支持
check_cxx_compiler_flag("-mfpu=neon" COMPILER_SUPPORTS_NEON)
if(COMPILER_SUPPORTS_NEON)
add_compile_options(-mfpu=neon)
add_compile_definitions(DAW_ENABLE_NEON)
message(STATUS "SIMD优化: 启用ARM32 NEON指令集")
else()
message(STATUS "SIMD优化: ARM32平台不支持NEON")
endif()
endif()
else()
message(STATUS "SIMD优化: 当前架构(${CMAKE_SYSTEM_PROCESSOR})不支持SIMD优化")
endif()
else()
message(STATUS "SIMD优化: 已禁用")
endif()
endfunction()
# ================================================================================================
# 应用编译器配置
# ================================================================================================
function(apply_compiler_configuration)
configure_compiler_options()
configure_simd_optimizations()
message(STATUS "编译器配置完成")
endfunction()

41
cmake/config_macos.cmake Normal file
View File

@@ -0,0 +1,41 @@
# 如果是Macos
if (APPLE)
# 获取 Homebrew 安装的 libomp 路径
execute_process(
COMMAND brew --prefix libomp
OUTPUT_VARIABLE HOMEBREW_LIBOMP_PATH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
# 设置 OpenMP 路径变量
set(OpenMP_CXX_FLAGS "-Xpreprocessor -fopenmp -I${HOMEBREW_LIBOMP_PATH}/include")
set(OpenMP_CXX_LIB_NAMES "omp")
set(OpenMP_omp_LIBRARY "${HOMEBREW_LIBOMP_PATH}/lib/libomp.dylib")
enable_language(OBJC OBJCXX)
# ============================================================================================
# Apple Accelerate框架支持 (包含AMX向量指令集)
# ============================================================================================
# 检测是否为Apple Silicon (ARM64)
if(CMAKE_SYSTEM_PROCESSOR MATCHES "arm64|aarch64")
message(STATUS "Detected Apple Silicon (${CMAKE_SYSTEM_PROCESSOR})")
# 查找Accelerate框架macOS系统自带
find_library(ACCELERATE_FRAMEWORK Accelerate)
if(ACCELERATE_FRAMEWORK)
message(STATUS "Found Accelerate framework: ${ACCELERATE_FRAMEWORK}")
# 设置全局变量供其他模块使用
set(APPLE_ACCELERATE_LIBRARY ${ACCELERATE_FRAMEWORK} PARENT_SCOPE)
set(HAS_ACCELERATE TRUE PARENT_SCOPE)
# 启用Accelerate编译选项
add_compile_definitions(DAW_ENABLE_ACCELERATE)
else()
message(WARNING "Accelerate framework not found on macOS")
set(HAS_ACCELERATE FALSE PARENT_SCOPE)
endif()
else()
message(STATUS "Not Apple Silicon, Accelerate framework disabled")
set(HAS_ACCELERATE FALSE PARENT_SCOPE)
endif()
endif ()

147
cmake/dependencies.cmake Normal file
View File

@@ -0,0 +1,147 @@
# ================================================================================================
# DAW Backend Framework - 依赖项管理模块
# 描述: 管理项目的系统依赖、第三方库和平台特定依赖
# ================================================================================================
# ================================================================================================
# 查找系统依赖
# ================================================================================================
function(find_system_dependencies)
# 查找线程库(必需)
find_package(Threads REQUIRED)
if(Threads_FOUND)
message(STATUS "找到Threads库")
endif()
# 设置全局变量供外部使用
set(THREADS_LIB Threads::Threads PARENT_SCOPE)
endfunction()
# ================================================================================================
# 配置Conan依赖管理
# ================================================================================================
function(configure_conan_dependencies)
# 检查是否使用CMakeDeps (Conan 2.x风格)
if(EXISTS ${CMAKE_BINARY_DIR}/generators/conan_toolchain.cmake)
message(STATUS "使用Conan 2.x CMakeDeps")
set(USING_CONAN TRUE PARENT_SCOPE)
# 设置CMAKE_PREFIX_PATH以便CMake可以找到Conan生成的包配置文件
list(APPEND CMAKE_PREFIX_PATH ${CMAKE_BINARY_DIR}/generators)
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} PARENT_SCOPE)
# 查找核心必需的Conan包
find_package(spdlog REQUIRED)
find_package(fmt REQUIRED)
find_package(nlohmann_json REQUIRED)
find_package(GTest REQUIRED)
find_package(Boost REQUIRED)
find_package(Eigen3 REQUIRED)
find_package(Protobuf REQUIRED)
find_package(TBB REQUIRED)
find_package(ZeroMQ REQUIRED)
find_package(cppzmq REQUIRED)
if(NOT TARGET TBB::tbb)
find_package(oneTBB REQUIRED)
endif()
# Boost组件 - 增强型IPC需要
find_package(Boost REQUIRED COMPONENTS
system
interprocess
circular_buffer
filesystem
thread
chrono
atomic
date_time)
# 查找可选的Conan包
find_package(yaml-cpp QUIET)
find_package(benchmark QUIET)
message(STATUS "Conan依赖配置完成:")
message(STATUS " - spdlog: ${spdlog_VERSION}")
message(STATUS " - fmt: ${fmt_VERSION}")
message(STATUS " - nlohmann_json: ${nlohmann_json_VERSION}")
message(STATUS " - GTest: 已配置")
message(STATUS " - Boost: ${Boost_VERSION}")
message(STATUS " - Eigen3: ${Eigen3_VERSION}")
message(STATUS " - Protobuf: ${Protobuf_VERSION}")
message(STATUS " - TBB/oneTBB: ${TBB_VERSION}")
message(STATUS " - ZeroMQ: ${zeroMQ_VERSION}")
message(STATUS " - cppzmq: ${cppzmq_VERSION}")
if(TARGET yaml-cpp::yaml-cpp)
message(STATUS " - yaml-cpp: 已找到")
endif()
if(TARGET benchmark::benchmark)
message(STATUS " - benchmark: 已找到")
endif()
# 检查是否使用Conan 1.x风格
elseif(EXISTS ${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup(TARGETS)
message(STATUS "使用Conan 1.x依赖管理")
set(USING_CONAN TRUE PARENT_SCOPE)
else()
message(STATUS "未检测到Conan将使用系统依赖")
set(USING_CONAN FALSE PARENT_SCOPE)
endif()
endfunction()
# ================================================================================================
# 配置平台特定依赖
# ================================================================================================
function(configure_platform_dependencies)
if(WIN32)
# Windows平台依赖
set(PLATFORM_LIBS wsock32 ws2_32 winmm)
message(STATUS "Windows平台: 添加wsock32, ws2_32, winmm库")
elseif(APPLE)
# macOS平台依赖
find_library(COREFOUNDATION_LIBRARY CoreFoundation)
find_library(COREAUDIO_LIBRARY CoreAudio QUIET)
set(PLATFORM_LIBS ${COREFOUNDATION_LIBRARY})
if(COREAUDIO_LIBRARY)
list(APPEND PLATFORM_LIBS ${COREAUDIO_LIBRARY})
message(STATUS "macOS平台: 找到CoreFoundation和CoreAudio框架")
else()
message(STATUS "macOS平台: 找到CoreFoundation框架")
endif()
else()
# Linux平台依赖
set(PLATFORM_LIBS ${CMAKE_DL_LIBS})
message(STATUS "Linux平台: 添加动态链接库支持")
endif()
# 将平台库设置为全局变量
set(PLATFORM_LIBS ${PLATFORM_LIBS} PARENT_SCOPE)
endfunction()
# ================================================================================================
# 配置所有依赖项
# ================================================================================================
function(setup_all_dependencies)
message(STATUS "")
message(STATUS "=== 配置依赖项 ===")
# 查找系统依赖
find_system_dependencies()
set(THREADS_LIB ${THREADS_LIB} PARENT_SCOPE)
# 配置Conan
configure_conan_dependencies()
set(USING_CONAN ${USING_CONAN} PARENT_SCOPE)
# 配置平台特定依赖
configure_platform_dependencies()
set(PLATFORM_LIBS ${PLATFORM_LIBS} PARENT_SCOPE)
message(STATUS "依赖项配置完成")
endfunction()

161
cmake/detect_os.cmake Normal file
View File

@@ -0,0 +1,161 @@
# 定义一个函数,为指定的目标添加操作系统和架构相关的预处理器定义
function(add_os_definitions target)
# 检查 target 参数是否提供
if(NOT target)
message(FATAL_ERROR "函数 add_os_definitions 需要一个 target 参数。")
return()
endif()
# --- 阶段 1: 确定宏的值 ---
# 初始化所有平台、架构和特性宏的值为 0
set(alicho_def_windows 0)
set(alicho_def_macos 0)
set(alicho_def_linux 0)
set(alicho_def_freebsd 0)
set(alicho_def_ios 0)
set(alicho_def_android 0)
set(alicho_def_cygwin 0)
set(alicho_def_unix 0)
set(alicho_def_posix 0)
set(alicho_def_mobile 0)
set(alicho_def_arch_64bit 0)
set(alicho_def_arch_32bit 0)
set(alicho_def_x86 0)
set(alicho_def_arm 0)
set(alicho_def_riscv 0)
set(alicho_def_apple 0) # 用于 iOS 和 macOS 的通用定义
set(alicho_def_debug 0) # 当前是否处于调试模式
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(alicho_def_debug 1)
endif ()
# -- 操作系统检测与赋值 --
# 注意检测顺序:优先检测更具体的平台
if(CYGWIN)
# Cygwin 环境比较特殊,它在 Windows 上模拟 Unix
set(alicho_def_windows 1) # 基础是 Windows
set(alicho_def_cygwin 1) # 明确是 Cygwin
set(alicho_def_unix 1) # 提供 Unix API
set(alicho_def_posix 1) # 提供 POSIX API
message(STATUS "检测到 **Cygwin** 环境 (运行于 Windows)")
elseif(WIN32)
# 非 Cygwin 的 Windows 环境 (MSVC, MinGW, etc.)
set(alicho_def_windows 1)
message(STATUS "检测到 **Windows** 操作系统 (非 Cygwin)")
elseif(ANDROID)
# Android 平台 (通常需要特定工具链设置 ANDROID 变量)
set(alicho_def_android 1)
set(alicho_def_unix 1) # Android NDK 基于 Unix
set(alicho_def_posix 1) # NDK 提供 POSIX API
set(alicho_def_mobile 1) # 移动平台
message(STATUS "检测到 **Android** 操作系统")
elseif(IOS)
# iOS 平台 (通常需要特定工具链设置 IOS 变量)
# 需要在 APPLE 之前判断,因为 iOS 下 APPLE 也为 TRUE
set(alicho_def_ios 1)
set(alicho_def_unix 1) # iOS (Darwin) 基于 Unix
set(alicho_def_posix 1) # 提供 POSIX API
set(alicho_def_mobile 1) # 移动平台
set(alicho_def_apple 1) # iOS 是 Apple 生态的一部分
message(STATUS "检测到 **iOS** 操作系统")
elseif(APPLE)
# 此时排除了 iOS确定是 macOS
set(alicho_def_macos 1)
set(alicho_def_unix 1) # macOS (Darwin) 基于 Unix
set(alicho_def_posix 1) # 提供 POSIX API
set(alicho_def_apple 1) # macOS 是 Apple 生态的一部分
message(STATUS "检测到 **macOS** 操作系统")
elseif(UNIX)
# 此时排除了 Apple, Android, Cygwin 的其他 Unix-like 系统
set(alicho_def_unix 1)
set(alicho_def_posix 1)
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
set(alicho_def_linux 1)
message(STATUS "检测到 **Linux** 操作系统")
elseif(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
set(alicho_def_freebsd 1)
message(STATUS "检测到 **FreeBSD** 操作系统")
else()
message(WARNING "检测到未知的 类Unix 操作系统: ${CMAKE_SYSTEM_NAME}")
endif()
else()
message(WARNING "检测到未知的操作系统: ${CMAKE_SYSTEM_NAME}")
endif()
# -- 架构检测与赋值 --
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(alicho_def_arch_64bit 1)
set(alicho_def_arch_32bit 0) # 明确设置为 0
message(STATUS "检测到 **64-bit** 架构")
elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
set(alicho_def_arch_64bit 0) # 明确设置为 0
set(alicho_def_arch_32bit 1)
message(STATUS "检测到 **32-bit** 架构")
else()
# 对于未知或未定义的指针大小,两者都保持 0
message(WARNING "无法明确检测到 32-bit 或 64-bit 架构 (CMAKE_SIZEOF_VOID_P = ${CMAKE_SIZEOF_VOID_P})。将两者都设置为 0。")
endif()
# 检测特定架构类型
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86|i386|i486|i586|i686|i786|x86_64|AMD64")
set(alicho_def_x86 1)
message(STATUS "检测到 **x86/x64** 架构")
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "arm|aarch64|ARM64")
set(alicho_def_arm 1)
message(STATUS "检测到 **ARM** 架构")
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "riscv|riscv64|riscv32")
set(alicho_def_riscv 1)
message(STATUS "检测到 **RISC-V** 架构")
else()
# --- 阶段 2: 组装定义列表 ---
set(definitions_list "") # 初始化空列表
# 添加平台定义
list(APPEND definitions_list "ALICHO_PLATFORM_WINDOWS=${alicho_def_windows}")
list(APPEND definitions_list "ALICHO_PLATFORM_MACOS=${alicho_def_macos}")
list(APPEND definitions_list "ALICHO_PLATFORM_LINUX=${alicho_def_linux}")
list(APPEND definitions_list "ALICHO_PLATFORM_FREEBSD=${alicho_def_freebsd}")
list(APPEND definitions_list "ALICHO_PLATFORM_IOS=${alicho_def_ios}")
list(APPEND definitions_list "ALICHO_PLATFORM_ANDROID=${alicho_def_android}")
list(APPEND definitions_list "ALICHO_PLATFORM_CYGWIN=${alicho_def_cygwin}")
list(APPEND definitions_list "ALICHO_PLATFORM_APPLE=${alicho_def_apple}") # 用于 iOS 和 macOS 的通用定义
# 添加架构定义
list(APPEND definitions_list "ALICHO_PLATFORM_ARCH_64BIT=${alicho_def_arch_64bit}")
list(APPEND definitions_list "ALICHO_PLATFORM_ARCH_32BIT=${alicho_def_arch_32bit}")
# 添加特性定义
list(APPEND definitions_list "ALICHO_PLATFORM_UNIX=${alicho_def_unix}")
list(APPEND definitions_list "ALICHO_PLATFORM_POSIX=${alicho_def_posix}")
list(APPEND definitions_list "ALICHO_PLATFORM_IS_MOBILE=${alicho_def_mobile}")
list(APPEND definitions_list "ALICHO_DEBUG=${alicho_def_debug}") # 当前是否处于调试模式
list(APPEND definitions_list "ALICHO_PLATFORM_X86=${alicho_def_x86}")
list(APPEND definitions_list "ALICHO_PLATFORM_ARM=${alicho_def_arm}")
list(APPEND definitions_list "ALICHO_PLATFORM_RISCV=${alicho_def_riscv}")
# --- 阶段 3: 应用所有定义 ---
# **关键:使用一次调用将所有定义添加到目标**
if(definitions_list) # 确保列表非空
target_compile_definitions(${target} PUBLIC ${definitions_list})
endif()
# 函数作用域结束时alicho_def_* 变量会自动销毁,无需显式 unset
endfunction()
# --- 使用示例 ---
# project(MyProject)
# add_executable(my_app main.c)
#
# # 调用函数为 my_app 添加平台定义
# add_os_definitions(my_app)
#
# # 你也可以为库调用
# # add_library(my_lib STATIC my_lib.c)
# # add_os_definitions(my_lib)

110
cmake/install_config.cmake Normal file
View File

@@ -0,0 +1,110 @@
# ================================================================================================
# DAW Backend Framework - 安装和打包配置模块
# 描述: 配置项目的安装规则和跨平台打包
# ================================================================================================
# ================================================================================================
# 配置安装规则
# ================================================================================================
function(configure_install_rules)
include(GNUInstallDirs)
# 安装头文件
install(DIRECTORY ${CMAKE_SOURCE_DIR}/include/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp")
message(STATUS "安装规则: 头文件将安装到 ${CMAKE_INSTALL_INCLUDEDIR}")
# 安装配置文件(如果存在)
if(EXISTS ${CMAKE_SOURCE_DIR}/config)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/config/
DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/daw-backend)
message(STATUS "安装规则: 配置文件将安装到 ${CMAKE_INSTALL_SYSCONFDIR}/daw-backend")
endif()
# 安装文档
set(DOC_FILES
README.md
architecture_design.md
pattern_system_design.md
)
foreach(DOC_FILE ${DOC_FILES})
if(EXISTS ${CMAKE_SOURCE_DIR}/${DOC_FILE})
install(FILES ${CMAKE_SOURCE_DIR}/${DOC_FILE}
DESTINATION ${CMAKE_INSTALL_DOCDIR})
endif()
endforeach()
message(STATUS "安装规则: 文档将安装到 ${CMAKE_INSTALL_DOCDIR}")
endfunction()
# ================================================================================================
# 配置CPack打包
# ================================================================================================
function(configure_cpack)
# 基础包信息
set(CPACK_PACKAGE_NAME "DAWBackend" PARENT_SCOPE)
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION} PARENT_SCOPE)
set(CPACK_PACKAGE_DESCRIPTION ${PROJECT_DESCRIPTION} PARENT_SCOPE)
set(CPACK_PACKAGE_CONTACT "daw-backend@example.com" PARENT_SCOPE)
set(CPACK_PACKAGE_VENDOR "DAW Backend Team" PARENT_SCOPE)
# 平台特定打包器
if(WIN32)
set(CPACK_GENERATOR "NSIS;ZIP" PARENT_SCOPE)
set(CPACK_NSIS_DISPLAY_NAME "DAW Backend Framework" PARENT_SCOPE)
set(CPACK_NSIS_PACKAGE_NAME "DAWBackend" PARENT_SCOPE)
message(STATUS "打包配置: Windows (NSIS + ZIP)")
elseif(APPLE)
set(CPACK_GENERATOR "DragNDrop;TGZ" PARENT_SCOPE)
set(CPACK_DMG_VOLUME_NAME "DAW Backend" PARENT_SCOPE)
message(STATUS "打包配置: macOS (DragNDrop + TGZ)")
else()
# Linux
set(CPACK_GENERATOR "DEB;RPM;TGZ" PARENT_SCOPE)
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6, libstdc++6" PARENT_SCOPE)
set(CPACK_RPM_PACKAGE_REQUIRES "glibc, libstdc++" PARENT_SCOPE)
message(STATUS "打包配置: Linux (DEB + RPM + TGZ)")
endif()
endfunction()
# ================================================================================================
# 应用安装和打包配置
# ================================================================================================
function(setup_install_and_packaging)
message(STATUS "")
message(STATUS "=== 配置安装和打包 ===")
# 配置安装规则
configure_install_rules()
# 配置CPack
configure_cpack()
# 导出CPack设置到父作用域
set(CPACK_PACKAGE_NAME ${CPACK_PACKAGE_NAME} PARENT_SCOPE)
set(CPACK_PACKAGE_VERSION ${CPACK_PACKAGE_VERSION} PARENT_SCOPE)
set(CPACK_PACKAGE_DESCRIPTION ${CPACK_PACKAGE_DESCRIPTION} PARENT_SCOPE)
set(CPACK_PACKAGE_CONTACT ${CPACK_PACKAGE_CONTACT} PARENT_SCOPE)
set(CPACK_PACKAGE_VENDOR ${CPACK_PACKAGE_VENDOR} PARENT_SCOPE)
set(CPACK_GENERATOR ${CPACK_GENERATOR} PARENT_SCOPE)
if(WIN32)
set(CPACK_NSIS_DISPLAY_NAME ${CPACK_NSIS_DISPLAY_NAME} PARENT_SCOPE)
set(CPACK_NSIS_PACKAGE_NAME ${CPACK_NSIS_PACKAGE_NAME} PARENT_SCOPE)
elseif(APPLE)
set(CPACK_DMG_VOLUME_NAME ${CPACK_DMG_VOLUME_NAME} PARENT_SCOPE)
else()
set(CPACK_DEBIAN_PACKAGE_DEPENDS ${CPACK_DEBIAN_PACKAGE_DEPENDS} PARENT_SCOPE)
set(CPACK_RPM_PACKAGE_REQUIRES ${CPACK_RPM_PACKAGE_REQUIRES} PARENT_SCOPE)
endif()
# 包含CPack模块
include(CPack)
message(STATUS "安装和打包配置完成")
endfunction()

41
cmake/mingw_dll.cmake Normal file
View File

@@ -0,0 +1,41 @@
function(auto_copy_mingw_dll target)
if(MINGW)
# 获取MinGW目录
get_filename_component(MINGW_DIR ${CMAKE_CXX_COMPILER} PATH)
# 根据你的环境调整DLL列表
set(MINGW_DLLS
"libstdc++-6.dll"
# "libgcc_s_dw2-1.dll"
"libgcc_s_seh-1.dll"
"libwinpthread-1.dll"
"libbz2-1.dll"
"libbrotlidec.dll"
"libbrotlicommon.dll"
"libharfbuzz-0.dll"
"libpng16-16.dll"
"zlib1.dll"
"libglib-2.0-0.dll"
"libfreetype-6.dll"
"libgraphite2.dll"
"libintl-8.dll"
"libpcre2-8-0.dll"
"libiconv-2.dll"
)
foreach(DLL ${MINGW_DLLS})
# 检查文件是否存在
if(EXISTS "${MINGW_DIR}/${DLL}")
add_custom_command(TARGET ${target} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${MINGW_DIR}/${DLL}"
"$<TARGET_FILE_DIR:${target}>"
COMMENT "Copying ${DLL} to output directory"
VERBATIM)
else()
message(WARNING "DLL not found: ${MINGW_DIR}/${DLL}")
endif()
endforeach()
endif()
endfunction()

44
cmake/mirage_utils.cmake Normal file
View File

@@ -0,0 +1,44 @@
# 定义一个函数来配置项目的默认设置
# 这包括设置输出目录和项目根目录变量
function(configure_project_defaults)
# 检查是否在顶层 CMakeLists.txt 中调用 (可选但推荐)
# 确保 CMAKE_SOURCE_DIR 和 CMAKE_CURRENT_SOURCE_DIR 相同
if(NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
message(WARNING "configure_project_defaults() 应该在项目的根 CMakeLists.txt 中调用。")
# 如果您确实需要在子目录中设置不同的根目录,请调整此逻辑
endif()
# --- 配置输出目录 ---
# 使用 CMAKE_BINARY_DIR 作为基础构建目录
# ${CMAKE_BINARY_DIR} 指向您配置 CMake 时指定的构建目录
# 例如,在 CLion 中通常是 cmake-build-debug 或 cmake-build-release
# 如果手动运行 cmake ..,它就是您运行 cmake 命令的目录
# **设置可执行文件输出路径**:
# 对于单配置生成器 (如 Makefiles, Ninja), 可执行文件将位于 <build>/bin/
# 对于多配置生成器 (如 Visual Studio, Xcode), CMake 通常会自动在此路径下附加配置名称
# (例如 <build>/bin/Debug/, <build>/bin/Release/)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin CACHE PATH "Directory for runtime executables")
message(STATUS "运行时输出目录设置为: ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
# **设置库文件输出路径 (共享库和静态库)**:
# 规则同上,库文件将位于 <build>/lib/ 或 <build>/lib/<Config>/
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib CACHE PATH "Directory for shared libraries")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib CACHE PATH "Directory for static libraries")
message(STATUS "库输出目录设置为: ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}")
message(STATUS "存档输出目录设置为: ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}")
# --- 提示 ---
# 这种全局设置输出目录的方法对于中小型项目是常见的。
# 对于更复杂的项目或需要更细粒度控制的情况可以考虑为每个目标target单独设置输出目录属性
# 例如:
# add_executable(my_app main.cpp)
# set_target_properties(my_app PROPERTIES
# RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/executables"
# )
# add_library(my_lib STATIC my_lib.cpp)
# set_target_properties(my_lib PROPERTIES
# ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/static_libs"
# )
endfunction()

View File

@@ -0,0 +1,138 @@
# 文件: cmake/CompilerSetup.cmake
# ==============================================================================
# 函数setup_project_options
# 描述:配置项目级的 C++ 标准、编译器警告、定义和依赖。
# 此函数遵循现代 CMake 实践,将所有配置封装到一个 INTERFACE 库中。
#
# 参数:
# standard - (必选) C++ 标准版本 (例如 17, 20, 23)。
# INTERFACE_TARGET - (必选) 用于接收创建的 INTERFACE 库名称的变量名。
#
# 用法:
# include(cmake/CompilerSetup.cmake)
# setup_project_options(
# STANDARD 20
# INTERFACE_TARGET my_project_options
# )
# # ... 定义你的可执行文件或库
# add_executable(my_app main.cpp)
# # ... 将配置应用到目标上
# target_link_libraries(my_app PRIVATE ${my_project_options})
# ==============================================================================
function(setup_project_options)
# --- 参数解析 ---
set(options "") # 无单值选项
set(oneValueArgs STANDARD INTERFACE_TARGET) # 定义接收单个值的参数
set(multiValueArgs "") # 无多值选项
cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
# --- 参数验证 ---
if(NOT ARG_STANDARD OR NOT ARG_INTERFACE_TARGET)
message(FATAL_ERROR "setup_project_options 必须提供 STANDARD 和 INTERFACE_TARGET 参数。")
endif()
set(VALID_STANDARDS 11 14 17 20 23)
list(FIND VALID_STANDARDS ${ARG_STANDARD} _standard_index)
if(_standard_index EQUAL -1)
message(FATAL_ERROR "不支持的 C++ 标准: ${ARG_STANDARD}。有效值: ${VALID_STANDARDS}")
endif()
# --- 创建 INTERFACE 库 ---
# 这是现代 CMake 的核心:创建一个虚拟目标来承载所有配置属性。
add_library(${ARG_INTERFACE_TARGET} INTERFACE)
message(STATUS "创建配置接口库: ${ARG_INTERFACE_TARGET}")
# --- 设置 C++ 标准 (应用到接口库) ---
target_compile_features(${ARG_INTERFACE_TARGET} INTERFACE cxx_std_${ARG_STANDARD})
# --- 设置通用编译定义和选项 ---
# 使用 target_compile_definitions 和 target_compile_options并指定 INTERFACE
# 这样任何链接到此库的目标都会继承这些属性。
# --- 平台特定设置 ---
if(WIN32)
target_compile_definitions(${ARG_INTERFACE_TARGET} INTERFACE UNICODE _UNICODE)
message(STATUS "为 Windows 添加 UNICODE 定义")
endif()
# --- 编译器特定设置 ---
if(MSVC)
# MSVC 特定选项
target_compile_options(${ARG_INTERFACE_TARGET} INTERFACE
/W4 # 更高警告等级
# /WX # 将警告视为错误 (可选,但推荐)
/EHsc
/utf-8 # 源码和执行字符集设为 UTF-8
/Zc:__cplusplus # 修正 __cplusplus 宏
/wd4100 # 禁用警告: 未使用的形参
/wd4996 # 禁用警告: 使用了被标记为否决的函数
)
message(STATUS "为 MSVC 添加特定编译选项")
else() # GCC / Clang / AppleClang
# 通用于 GCC 和 Clang 的选项
target_compile_options(${ARG_INTERFACE_TARGET} INTERFACE
-Wall
-Wextra
-Wpedantic # 更加严格的警告
-Werror # 将所有警告视为错误 (可选,但推荐)
-Wno-unused-parameter
)
# C++17 及以上标准的额外警告
if(${ARG_STANDARD} GREATER_EQUAL 17)
target_compile_options(${ARG_INTERFACE_TARGET} INTERFACE
-Wshadow
-Wnon-virtual-dtor
)
endif()
# 【核心修复】区分处理 AppleClang 和标准 Clang/GCC
# AppleClang 不支持 -finput-charset/-fexec-charset并默认源码为 UTF-8
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "AppleClang")
target_compile_options(${ARG_INTERFACE_TARGET} INTERFACE
-finput-charset=UTF-8
-fexec-charset=UTF-8
)
message(STATUS "为 GCC/Clang 添加 UTF-8 字符集选项")
else()
message(STATUS "检测到 AppleClang源码假定为 UTF-8跳过字符集选项")
endif()
message(STATUS "为 GCC/Clang 添加特定编译选项")
endif()
# --- MinGW 特定设置 ---
if(MINGW)
# 为 C++17 及以上的 <filesystem> 支持添加链接库
if(${ARG_STANDARD} GREATER_EQUAL 17)
# 使用 target_link_libraries这才是正确的方式
target_link_libraries(${ARG_INTERFACE_TARGET} INTERFACE -lstdc++fs)
message(STATUS "为 MinGW C++${ARG_STANDARD} 添加 libstdc++fs 依赖 (用于 <filesystem>)")
endif()
endif()
# --- 将 INTERFACE 库的名称返回给调用者 ---
set(${ARG_INTERFACE_TARGET} ${ARG_INTERFACE_TARGET} PARENT_SCOPE)
message(STATUS "C++${ARG_STANDARD} 项目配置完成,请链接到 ${ARG_INTERFACE_TARGET} 目标。")
endfunction()
# ==============================================================================
# 函数set_cpp_standard
# 描述:设置全局 C++ 标准的简化包装函数
# 参数:
# standard - (必选) C++ 标准版本 (例如 17, 20, 23)
# ==============================================================================
function(set_cpp_standard standard)
set(VALID_STANDARDS 11 14 17 20 23)
list(FIND VALID_STANDARDS ${standard} _standard_index)
if(_standard_index EQUAL -1)
message(FATAL_ERROR "不支持的 C++ 标准: ${standard}。有效值: ${VALID_STANDARDS}")
endif()
set(CMAKE_CXX_STANDARD ${standard} PARENT_SCOPE)
set(CMAKE_CXX_STANDARD_REQUIRED ON PARENT_SCOPE)
set(CMAKE_CXX_EXTENSIONS OFF PARENT_SCOPE)
message(STATUS "设置 C++ 标准为 C++${standard}")
endfunction()

545
cmake/retrieve_files.cmake Normal file
View File

@@ -0,0 +1,545 @@
#[=======================================================================[
:
platform: 平台标识符 (windows|linux|mac|mobile|desktop)
is_match:
#]=======================================================================]
function(is_current_platform platform is_match)
# 设置默认值为TRUE用于未知平台
set(matches FALSE)
if(platform STREQUAL "windows")
if(WIN32 OR CYGWIN)
set(matches TRUE)
endif()
elseif(platform STREQUAL "linux")
if(UNIX AND NOT APPLE)
set(matches TRUE)
endif()
elseif(platform STREQUAL "macos")
if(APPLE AND NOT IOS)
set(matches TRUE)
endif()
elseif(platform STREQUAL "ios")
if(IOS)
set(matches TRUE)
endif()
elseif(platform STREQUAL "android")
if(ANDROID)
set(matches TRUE)
endif()
# 添加对unix平台的支持
elseif(platform STREQUAL "unix")
if(UNIX)
set(matches TRUE)
endif()
elseif(platform STREQUAL "mobile")
if(ANDROID OR IOS)
set(matches TRUE)
endif()
elseif(platform STREQUAL "desktop")
if(WIN32 OR (UNIX AND NOT APPLE) OR (APPLE AND NOT IOS))
set(matches TRUE)
endif()
elseif(platform STREQUAL "web")
if(EMSCRIPTEN)
set(matches TRUE)
endif()
else()
# 未知平台标识,默认匹配
set(matches TRUE)
endif()
set(${is_match} ${matches} PARENT_SCOPE)
endfunction()
#[=======================================================================[
:
path:
extension:
out_files:
#]=======================================================================]
function(retrieve_files_custom path extension out_files)
# 1. 参数验证
if(NOT IS_DIRECTORY "${path}")
message(WARNING "错误:目录 '${path}' 不存在")
return()
endif()
message(STATUS "正在检索目录: ${path}")
# 2. 构建文件匹配模式
set(file_patterns "")
foreach(ext IN LISTS extension)
list(APPEND file_patterns "${path}/*.${ext}")
endforeach()
# 3. 递归查找所有匹配的文件
file(GLOB_RECURSE found_files
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
CONFIGURE_DEPENDS ${file_patterns}
)
# 4. 处理找到的文件
set(filtered_files "")
foreach(current_file IN LISTS found_files)
# 4.1 获取文件所在目录
get_filename_component(file_dir "${current_file}" DIRECTORY)
string(REPLACE "/" ";" dir_components "${file_dir}")
# 4.2 检查平台兼容性
set(should_skip_file FALSE)
set(found_platform_dir FALSE)
foreach(dir_name IN LISTS dir_components)
# 检查是否是平台相关目录
if(dir_name MATCHES "^(windows|linux|mac|ios|android|unix|mobile|desktop|web)$")
set(found_platform_dir TRUE)
is_current_platform(${dir_name} platform_matches)
if(NOT platform_matches)
set(should_skip_file TRUE)
break()
endif()
endif()
endforeach()
# 如果文件需要跳过,继续处理下一个文件
if(should_skip_file)
continue()
endif()
# 4.3 添加符合条件的文件
list(APPEND filtered_files "${current_file}")
# 4.4 设置IDE文件分组
# 计算相对路径作为分组名称
get_filename_component(root_abs_path "${path}" ABSOLUTE)
get_filename_component(file_dir_abs_path "${file_dir}" ABSOLUTE)
file(RELATIVE_PATH group_path "${root_abs_path}" "${file_dir_abs_path}")
# 处理根目录的特殊情况
if(group_path STREQUAL ".")
set(group_name "")
else()
string(REPLACE "/" "\\" group_name "${group_path}")
endif()
# 创建IDE分组
source_group("${group_name}" FILES "${current_file}")
endforeach()
# 5. 设置输出变量
set(${out_files} ${filtered_files} PARENT_SCOPE)
endfunction()
#[=======================================================================[
便
#]=======================================================================]
function(retrieve_files path out_files)
# 设置基础文件类型
set(file_extensions
"h" # 头文件
"hpp" # C++头文件
"ini" # 配置文件
"cpp" # C++源文件
"c" # C源文件
"cc"
"ixx" # C++20模块文件
)
# 针对Mac平台添加额外文件类型
if(APPLE)
list(APPEND file_extensions "mm") # Objective-C++源文件
endif()
# 执行文件检索
set(temp_files "")
retrieve_files_custom(${path} "${file_extensions}" temp_files)
# 合并结果到输出变量
set(${out_files} ${${out_files}} ${temp_files} PARENT_SCOPE)
endfunction()
#[=======================================================================[
ProtogRPC
:
TARGET_NAME: () -
PROTO_PATH: () - .proto
OUTPUT_PATH: () - ${CMAKE_CURRENT_BINARY_DIR}/generated
GRPC_ENABLED: () - gRPCTRUE
PROTO_IMPORT_DIRS:() - proto
EXPORT_MACRO: () - Windows DLL
:
compile_proto_files(
TARGET_NAME my_proto_lib
PROTO_PATH ${CMAKE_CURRENT_SOURCE_DIR}/protos
OUTPUT_PATH ${CMAKE_BINARY_DIR}/proto_gen
GRPC_ENABLED TRUE
PROTO_IMPORT_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/third_party/protos
)
#]=======================================================================]
function(compile_proto_files)
# 定义预期的参数
set(options GRPC_ENABLED)
set(oneValueArgs TARGET_NAME PROTO_PATH OUTPUT_PATH EXPORT_MACRO)
set(multiValueArgs PROTO_IMPORT_DIRS)
# 解析传递给函数的参数
cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
# 参数验证
if(NOT ARG_TARGET_NAME)
message(FATAL_ERROR "**compile_proto_files**: **缺少必需参数** **TARGET_NAME**.")
endif()
if(NOT ARG_PROTO_PATH)
message(FATAL_ERROR "**compile_proto_files**: **缺少必需参数** **PROTO_PATH**.")
endif()
# 设置默认值
if(NOT DEFINED ARG_GRPC_ENABLED)
set(ARG_GRPC_ENABLED TRUE)
endif()
if(NOT ARG_OUTPUT_PATH)
set(ARG_OUTPUT_PATH "${CMAKE_CURRENT_BINARY_DIR}/generated")
endif()
# 查找Protobuf和gRPC
find_package(Protobuf REQUIRED)
if(ARG_GRPC_ENABLED)
find_package(gRPC QUIET)
if(NOT gRPC_FOUND)
# 如果找不到gRPC包尝试手动查找
find_program(GRPC_CPP_PLUGIN grpc_cpp_plugin)
if(NOT GRPC_CPP_PLUGIN)
message(FATAL_ERROR "**compile_proto_files**: **找不到gRPC C++插件**. 请确保已安装gRPC.")
endif()
else()
set(GRPC_CPP_PLUGIN $<TARGET_FILE:gRPC::grpc_cpp_plugin>)
endif()
endif()
# 创建输出目录
file(MAKE_DIRECTORY ${ARG_OUTPUT_PATH})
get_filename_component(PROTO_PATH "${ARG_PROTO_PATH}" ABSOLUTE)
# 递归查找所有.proto文件
file(GLOB_RECURSE PROTO_FILES
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
CONFIGURE_DEPENDS
"${PROTO_PATH}/*.proto"
)
if(NOT PROTO_FILES)
message(WARNING "**compile_proto_files**: 在 '${PROTO_PATH}' 中未找到任何.proto文件")
return()
endif()
message(STATUS "找到 ${CMAKE_CURRENT_SOURCE_DIR} Proto文件: ${PROTO_FILES}")
# 准备生成的文件列表
set(PROTO_SRCS)
set(PROTO_HDRS)
set(GRPC_SRCS)
set(GRPC_HDRS)
# 构建导入路径参数
set(PROTO_IMPORT_ARGS)
list(APPEND PROTO_IMPORT_ARGS "-I${PROTO_PATH}")
foreach(IMPORT_DIR ${ARG_PROTO_IMPORT_DIRS})
list(APPEND PROTO_IMPORT_ARGS "-I${IMPORT_DIR}")
endforeach()
# 为每个proto文件生成代码
foreach(PROTO_FILE ${PROTO_FILES})
# 获取proto文件的绝对路径
get_filename_component(PROTO_FILE_ABS "${PROTO_FILE}" ABSOLUTE BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
get_filename_component(PROTO_NAME_WE "${PROTO_FILE}" NAME_WE)
get_filename_component(PROTO_DIR "${PROTO_FILE}" DIRECTORY)
# 计算相对路径以保持目录结构
if(PROTO_DIR)
file(RELATIVE_PATH REL_DIR "${PROTO_PATH}" "${CMAKE_CURRENT_SOURCE_DIR}/${PROTO_DIR}")
set(OUTPUT_SUBDIR "${ARG_OUTPUT_PATH}/${REL_DIR}")
else()
set(OUTPUT_SUBDIR "${ARG_OUTPUT_PATH}")
endif()
# 创建输出子目录
file(MAKE_DIRECTORY ${OUTPUT_SUBDIR})
# 生成的文件路径
set(PROTO_SRC "${OUTPUT_SUBDIR}/${PROTO_NAME_WE}.pb.cc")
set(PROTO_HDR "${OUTPUT_SUBDIR}/${PROTO_NAME_WE}.pb.h")
list(APPEND PROTO_SRCS ${PROTO_SRC})
list(APPEND PROTO_HDRS ${PROTO_HDR})
# 基础protobuf生成命令
set(PROTOC_ARGS
${PROTO_IMPORT_ARGS}
"--cpp_out=${ARG_OUTPUT_PATH}"
"${PROTO_FILE_ABS}"
)
if(ARG_GRPC_ENABLED)
set(GRPC_SRC "${OUTPUT_SUBDIR}/${PROTO_NAME_WE}.grpc.pb.cc")
set(GRPC_HDR "${OUTPUT_SUBDIR}/${PROTO_NAME_WE}.grpc.pb.h")
list(APPEND GRPC_SRCS ${GRPC_SRC})
list(APPEND GRPC_HDRS ${GRPC_HDR})
# 添加自定义命令生成protobuf和gRPC代码
add_custom_command(
OUTPUT ${PROTO_SRC} ${PROTO_HDR} ${GRPC_SRC} ${GRPC_HDR}
COMMAND ${Protobuf_PROTOC_EXECUTABLE}
${PROTOC_ARGS}
COMMAND ${Protobuf_PROTOC_EXECUTABLE}
${PROTO_IMPORT_ARGS}
"--grpc_out=${ARG_OUTPUT_PATH}"
"--plugin=protoc-gen-grpc=${GRPC_CPP_PLUGIN}"
"${PROTO_FILE_ABS}"
DEPENDS ${PROTO_FILE_ABS}
COMMENT "生成Protobuf和gRPC代码: ${PROTO_FILE}"
VERBATIM
)
else()
# 只生成protobuf代码
add_custom_command(
OUTPUT ${PROTO_SRC} ${PROTO_HDR}
COMMAND ${Protobuf_PROTOC_EXECUTABLE}
${PROTOC_ARGS}
DEPENDS ${PROTO_FILE_ABS}
COMMENT "生成Protobuf代码: ${PROTO_FILE}"
VERBATIM
)
endif()
endforeach()
# 创建库目标
add_library(${ARG_TARGET_NAME} STATIC
${PROTO_SRCS}
${PROTO_HDRS}
${GRPC_SRCS}
${GRPC_HDRS}
)
# 设置包含目录
target_include_directories(${ARG_TARGET_NAME}
PUBLIC
$<BUILD_INTERFACE:${ARG_OUTPUT_PATH}>
$<INSTALL_INTERFACE:include>
)
# 链接必要的库
target_link_libraries(${ARG_TARGET_NAME}
PUBLIC
protobuf::libprotobuf
)
if(ARG_GRPC_ENABLED)
if(gRPC_FOUND)
target_link_libraries(${ARG_TARGET_NAME}
PUBLIC
gRPC::grpc++
gRPC::grpc++_reflection
)
else()
# 手动查找并链接gRPC库
find_library(GRPC_LIBRARY grpc++)
find_library(GRPC_REFLECTION_LIBRARY grpc++_reflection)
if(GRPC_LIBRARY AND GRPC_REFLECTION_LIBRARY)
target_link_libraries(${ARG_TARGET_NAME}
PUBLIC
${GRPC_LIBRARY}
${GRPC_REFLECTION_LIBRARY}
)
else()
message(WARNING "**compile_proto_files**: 无法找到gRPC库请手动链接")
endif()
endif()
endif()
# 设置导出宏(如果提供)
if(ARG_EXPORT_MACRO)
target_compile_definitions(${ARG_TARGET_NAME}
PRIVATE ${ARG_EXPORT_MACRO}_EXPORTS
INTERFACE ${ARG_EXPORT_MACRO}_IMPORTS
)
endif()
# 设置C++标准
target_compile_features(${ARG_TARGET_NAME} PUBLIC cxx_std_11)
# IDE文件分组
source_group("Proto Files" FILES ${PROTO_FILES})
source_group("Generated Files\\Protobuf" FILES ${PROTO_SRCS} ${PROTO_HDRS})
if(ARG_GRPC_ENABLED)
source_group("Generated Files\\gRPC" FILES ${GRPC_SRCS} ${GRPC_HDRS})
endif()
# 输出信息
message(STATUS "创建Proto库目标: ${ARG_TARGET_NAME}")
message(STATUS " Proto文件数量: ${CMAKE_CURRENT_SOURCE_DIR} list length: ${PROTO_FILES}")
message(STATUS " 输出目录: ${ARG_OUTPUT_PATH}")
message(STATUS " gRPC支持: ${ARG_GRPC_ENABLED}")
endfunction()
#[=======================================================================[
# 用于添加资源文件并在编译后复制到最终可执行文件所在目录
# 注意:此函数依赖于 CMAKE_RUNTIME_OUTPUT_DIRECTORY 或 EXECUTABLE_OUTPUT_PATH
# 变量的设置,以确定可执行文件的输出目录。请确保在项目中设置了其中之一。
#
# 参数:
# TARGET_NAME: (必需) - 关联的目标 (库或可执行文件) 的名称。
# 资源复制命令将在 TARGET_NAME 构建后执行。
# RESOURCE_FILES: (必需) - 一个或多个要复制的资源文件的路径列表 (相对或绝对)
# OUTPUT_SUBDIR: (可选) - 相对于可执行文件输出目录的子目录路径 (例如 "assets")
#
# 例子:
# # 确保设置了可执行文件输出目录 (通常在顶层 CMakeLists.txt)
# set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
#
# # 添加库
# add_library(my_lib STATIC src/my_lib.cpp)
#
# # 添加资源到 my_lib但复制到最终可执行文件的输出目录下的 'config' 子目录
# add_resource_file(
# TARGET_NAME my_lib
# RESOURCE_FILES config/settings.json config/defaults.ini
# OUTPUT_SUBDIR config
# )
#
# # 添加可执行文件
# add_executable(my_app main.cpp)
# target_link_libraries(my_app PRIVATE my_lib)
#
# # 添加 my_app 的资源,复制到可执行文件输出目录的根目录
# add_resource_file(
# TARGET_NAME my_app
# RESOURCE_FILES assets/icon.png
# )
#]=======================================================================]
function(add_resource_file)
# 定义预期的参数
set(options "") # 无布尔选项
set(oneValueArgs TARGET_NAME OUTPUT_SUBDIR)
set(multiValueArgs RESOURCE_FILES)
# 解析传递给函数的参数
cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
# --- 参数验证 ---
if(NOT ARG_TARGET_NAME)
message(FATAL_ERROR "**add_resource_file**: **缺少必需参数** **TARGET_NAME**.")
endif()
if(NOT ARG_RESOURCE_FILES)
message(FATAL_ERROR "**add_resource_file**: **缺少必需参数** **RESOURCE_FILES**.")
endif()
if(NOT TARGET ${ARG_TARGET_NAME})
message(WARNING "**add_resource_file**: 目标 '${ARG_TARGET_NAME}' (尚)不存在。请确保在调用 add_executable/add_library('${ARG_TARGET_NAME}') 之后调用此函数。")
# 即使目标尚不存在仍然尝试配置命令。CMake通常能处理好依赖关系。
endif()
# --- 确定最终可执行文件的目标基础目录 ---
set(DESTINATION_BASE "")
if(DEFINED CMAKE_RUNTIME_OUTPUT_DIRECTORY AND CMAKE_RUNTIME_OUTPUT_DIRECTORY)
set(DESTINATION_BASE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
elseif(DEFINED EXECUTABLE_OUTPUT_PATH AND EXECUTABLE_OUTPUT_PATH)
# EXECUTABLE_OUTPUT_PATH 是旧变量,但也检查一下
set(DESTINATION_BASE "${EXECUTABLE_OUTPUT_PATH}")
else()
# 如果是多配置生成器(如 Visual Studio, Xcode需要考虑配置类型
get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(is_multi_config)
# 对于多配置,没有单一的顶级运行时目录变量。
# 可以考虑使用 $<OUTPUT_DIRECTORY> 配合一个已知的可执行文件名,但这会使函数复杂化。
# 最好的做法是要求用户设置 CMAKE_RUNTIME_OUTPUT_DIRECTORY_<CONFIG>
# 或者我们直接报错,强制用户设置 CMAKE_RUNTIME_OUTPUT_DIRECTORY
message(FATAL_ERROR "**add_resource_file**: **无法确定可执行文件输出目录**。请在您的项目中设置 **CMAKE_RUNTIME_OUTPUT_DIRECTORY** 变量 (例如 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY \"\${CMAKE_BINARY_DIR}/bin\"))。对于多配置生成器,可能需要设置 CMAKE_RUNTIME_OUTPUT_DIRECTORY_<CONFIG> 变量。")
else()
# 对于单配置生成器(如 Makefiles, Ninja可以默认到 CMAKE_BINARY_DIR
set(DESTINATION_BASE "${CMAKE_BINARY_DIR}")
message(WARNING "**add_resource_file**: **未设置 CMAKE_RUNTIME_OUTPUT_DIRECTORY**。默认将资源复制到 CMAKE_BINARY_DIR ('${CMAKE_BINARY_DIR}')。强烈建议设置 CMAKE_RUNTIME_OUTPUT_DIRECTORY 以获得可预测的行为。")
endif()
# message(FATAL_ERROR "**add_resource_file**: **无法确定可执行文件输出目录**。请在您的项目中设置 **CMAKE_RUNTIME_OUTPUT_DIRECTORY** 变量 (例如 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY \"\${CMAKE_BINARY_DIR}/bin\"))。")
endif()
# 处理子目录
set(DESTINATION_DIR "${DESTINATION_BASE}") # 默认目标目录
if(ARG_OUTPUT_SUBDIR)
# 清理子目录路径字符串
string(STRIP "${ARG_OUTPUT_SUBDIR}" _subdir)
if(IS_ABSOLUTE "${_subdir}")
message(FATAL_ERROR "**add_resource_file**: **OUTPUT_SUBDIR** ('${ARG_OUTPUT_SUBDIR}') **必须是相对路径**。")
else()
# 移除可能存在的前导/后导斜杠,以便干净地拼接路径
string(REGEX REPLACE "^[/\\\\]+" "" _subdir "${_subdir}")
string(REGEX REPLACE "[/\\\\]+$" "" _subdir "${_subdir}")
if(_subdir) # 仅当子目录清理后非空时才追加
set(DESTINATION_DIR "${DESTINATION_BASE}/${_subdir}")
endif()
endif()
endif()
# --- 准备源文件路径 ---
set(ABS_RESOURCE_FILES "")
foreach(RESOURCE_FILE ${ARG_RESOURCE_FILES})
get_filename_component(RESOURCE_FILE_REALPATH "${RESOURCE_FILE}" REALPATH BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
# if(IS_ABSOLUTE "${RESOURCE_FILE}")
# # 如果已经是绝对路径,直接使用
# list(APPEND ABS_RESOURCE_FILES "${RESOURCE_FILE}")
# else()
# # 如果是相对路径,相对于当前源目录进行解析
# list(APPEND ABS_RESOURCE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/${RESOURCE_FILE}")
# endif()
list(APPEND ABS_RESOURCE_FILES "${RESOURCE_FILE_REALPATH}")
# 检查文件是否存在 (在配置时发出警告,有助于早期发现错误)
# list(GET ABS_RESOURCE_FILES -1 _current_abs_file) # 获取刚才添加的绝对路径
if(NOT EXISTS "${RESOURCE_FILE_REALPATH}")
message(WARNING "**add_resource_file**: **资源文件** '${RESOURCE_FILE}' (解析为 '${RESOURCE_FILE_REALPATH}') **在配置时不存在**。")
endif()
endforeach()
# --- 添加自定义命令 ---
# 使用 add_custom_command 在目标构建完成后执行复制操作
if(ABS_RESOURCE_FILES) # 确保有文件需要复制
# 注意DESTINATION_DIR 可能包含特定于配置的路径(例如,如果 CMAKE_RUNTIME_OUTPUT_DIRECTORY
# 设置为 ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin
# add_custom_command 的 COMMAND 参数在构建时执行,此时这些变量/生成器表达式已解析。
add_custom_command(
TARGET ${ARG_TARGET_NAME}
POST_BUILD # 指定在目标构建之后执行
# 步骤 1: 确保目标目录存在 (copy_if_different 不会创建目录)
COMMAND ${CMAKE_COMMAND} -E make_directory "${DESTINATION_DIR}"
# 步骤 2: 复制文件
COMMAND ${CMAKE_COMMAND} -E copy_if_different # 使用CMake内置命令复制仅当文件不同时
${ABS_RESOURCE_FILES} # 要复制的源文件列表(绝对路径)
"${DESTINATION_DIR}" # 最终可执行文件所在的目标目录 (带引号以处理空格)
COMMENT "为 ${ARG_TARGET_NAME} 将资源复制到可执行文件目录: ${DESTINATION_DIR}..." # 构建时显示的注释
VERBATIM # 确保参数(尤其是路径和生成器表达式)被正确处理
)
else()
message(WARNING "**add_resource_file**: 没有有效的资源文件提供给目标 '${ARG_TARGET_NAME}'。")
endif()
# --- 可选: 将资源文件添加到 IDE 项目结构中 ---
if(ABS_RESOURCE_FILES)
set(_source_group_name "Resource Files") # 基础组名
if(ARG_OUTPUT_SUBDIR)
# 使用与目标目录结构匹配的组名
string(STRIP "${ARG_OUTPUT_SUBDIR}" _clean_subdir)
string(REPLACE "\\" "/" _clean_subdir "${_clean_subdir}") # 统一使用正斜杠
string(REGEX REPLACE "^[/]+" "" _clean_subdir "${_clean_subdir}")
string(REGEX REPLACE "[/]+$" "" _clean_subdir "${_clean_subdir}")
if(_clean_subdir)
set(_source_group_name "Resource Files/${_clean_subdir}")
endif()
endif()
# 使用 source_group 将文件添加到 IDE 的指定组下
source_group(${_source_group_name} FILES ${ABS_RESOURCE_FILES})
endif()
endfunction()

109
conanfile.txt Normal file
View File

@@ -0,0 +1,109 @@
[requires]
# ================================================================================================
# DAW Backend Framework - Conan依赖配置 (完整版本)
# ================================================================================================
# 核心依赖
spdlog/1.14.1 # 高性能日志库
fmt/10.2.1 # 格式化库 (spdlog依赖)
nlohmann_json/3.11.3 # JSON处理
# 序列化和数据结构
yaml-cpp/0.8.0 # YAML配置文件支持
protobuf/3.21.12 # 消息序列化
flatbuffers/24.3.25 # 高性能序列化 (零拷贝)
# 测试框架
gtest/1.14.0 # 单元测试
benchmark/1.8.3 # 性能测试
# 基础工具库
boost/1.88.0 # 提供进程管理、IPC、共享内存等核心组件
# 通信组件
zeromq/4.3.5 # 高性能异步消息库
cppzmq/4.11.0 # ZeroMQ C++绑定
zstd/1.5.5 # 高性能压缩库 (网络传输优化)
# 数学和信号处理
eigen/3.4.0 # 矩阵计算和DSP处理
fftw/3.3.10 # 快速傅里叶变换
libsamplerate/0.2.2 # 高质量采样率转换
# 线程和并发
onetbb/2022.2.0 # Intel线程构建块 (并行处理)
# 音频处理支持
portaudio/19.7.0 # 跨平台音频I/O库
libsndfile/1.2.2 # 音频文件格式读写
rtmidi/5.0.0 # MIDI处理
[options]
# Boost配置 - 启用IPC和零拷贝相关组件
boost/*:shared=False
boost/*:without_test=False
boost/*:without_filesystem=False
boost/*:without_system=False
boost/*:without_thread=False
boost/*:without_chrono=False
boost/*:without_atomic=False
boost/*:without_date_time=False
boost/*:without_regex=False
boost/*:without_context=False # 提供上下文切换支持process依赖
boost/*:without_coroutine=True
boost/*:without_fiber=True
boost/*:without_graph=True
boost/*:without_iostreams=False # process依赖
boost/*:without_locale=True
boost/*:without_log=True
boost/*:without_math=True
boost/*:without_mpi=True
boost/*:without_program_options=False # 命令行参数解析
boost/*:without_python=True
boost/*:without_random=False
boost/*:without_serialization=False # 需要序列化支持
boost/*:without_wave=True
boost/*:without_asio=False # process依赖
# ZeroMQ配置 - 增强版本支持更多特性
zeromq/*:shared=False
cppzmq/*:shared=False
# 日志库配置
spdlog/*:shared=False
spdlog/*:header_only=False
fmt/*:shared=False
fmt/*:header_only=False
# 测试框架配置
gtest/*:shared=False
gtest/*:no_main=False
benchmark/*:shared=False
# 序列化库配置
protobuf/*:shared=False
yaml-cpp/*:shared=False
flatbuffers/*:shared=False
# 数学库配置
eigen/*:shared=False
onetbb/*:shared=False
fftw/*:shared=False
fftw/*:precision=double
# 音频库配置
portaudio/*:shared=False
libsndfile/*:shared=False
libsndfile/*:with_external_libs=True
rtmidi/*:shared=False
libsamplerate/*:shared=False
# 压缩库配置
zstd/*:shared=False
[generators]
CMakeDeps
CMakeToolchain
[layout]
cmake_layout

82
docs/README.md Normal file
View File

@@ -0,0 +1,82 @@
# AI 项目编码规范
为了统一项目编码风格,提高代码的可读性、可维护性和团队协作效率,特制定本规范。所有项目参与者均需严格遵守。
## 1. 终端命令
在本项目中,所有终端操作,包括但不限于编译、运行、脚本执行等,均需使用 **PowerShell** 命令。
- **目的**: 确保在 Windows 主开发环境下命令的一致性。
- **要求**: 请确保你的开发环境已正确配置 PowerShell并使用 PowerShell Core (7.x+) 以获得最佳的跨平台兼容性体验。
## 2. 跨平台宏定义
项目中所有的跨平台宏定义和操作系统判断逻辑,请统一参考和使用根目录 `cmake/detect_os.cmake` 文件中提供的宏。
- **目的**: 集中管理平台相关逻辑,避免在业务代码中出现分散的、重复的平台判断代码。
- **示例**: 在 CMakeLists.txt 中需要根据操作系统执行不同操作时,应使用 `detect_os.cmake` 中定义的 `IS_WINDOWS`, `IS_LINUX` 等变量。
## 3. 目录结构与头文件管理
本项目不设立顶层的 `include` 文件夹用于存放公共头文件。每个模块所需的头文件(`.h`, `.hpp`)和源文件(`.cpp`)应全部放置在该模块自身的文件夹下。
- **目的**: 提高模块的内聚性,使得模块可以被轻松地移植或复用。
- **正确结构示例**:
```
project/
├── src/
│ ├── moduleA/
│ │ ├── a.h
│ │ └── a.cpp
│ ├── moduleB/
│ │ ├── b.h
│ │ └── b.cpp
│ └── common/
│ ├── logger.h
│ └── error.h
└── cmake/
├── detect_os.cmake
└── retrieve_files.cmake
```
## 4. 跨平台文件包含
当需要根据不同操作系统包含不同的源文件时,应遵循 `cmake/retrieve_files.cmake` 文件中定义的规范和函数。
- **目的**: 将文件包含的平台差异性逻辑收敛到 CMake 构建系统中,保持 `CMakeLists.txt` 的整洁。
- **要求**: 请勿在业务模块的 `CMakeLists.txt` 中自行编写 `if(WIN32)` 等逻辑来添加源文件,应调用 `retrieve_files.cmake` 中提供的函数来获取平台相关的文件列表。
## 5. 错误码与异常处理
项目中所有的错误码定义和异常抛出机制,均已在 `common` 模块的 `error.h` 文件中统一规定。
- **目的**: 统一全项目的错误处理方式,便于问题的定位和跟踪。
- **要求**:
- 在进行错误处理或抛出异常时,必须查阅并使用此文件中已有的定义。
- 如需新增错误类型,也应在此文件中进行统一扩展,并附上清晰的注释说明。
## 6. 日志打印
严禁使用 `printf`、`std::cout` 等标准输出函数进行调试和日志打印。所有日志信息必须通过 `common` 模块下的 `logger.h` 提供的日志接口进行输出。
- **目的**: 便于统一管理日志级别(如 DEBUG, INFO, WARNING, ERROR、输出格式和输出目标如控制台、文件方便在不同环境下进行调试和部署。
- **示例**:
```cpp
// 错误示范
// std::cout << "加载模型失败" << std::endl;
// 正确示范
#include "logger.h"
...
log_err("模型加载失败,文件路径:%s", model_path.c_str());
```
## 7. 注释与日志语言
为了方便团队所有成员的阅读和理解,项目所有的**代码注释**、**日志信息**以及**代码提交信息Commit Message** **必须全部使用中文**。
- **目的**: 消除语言障碍,降低沟通成本,确保信息的准确传达。
- **要求**:
- **代码注释**: 对复杂的函数、算法或业务逻辑,必须添加清晰的中文注释。
- **日志内容**: `logger.h` 输出的日志消息必须为中文。
- **Git Commit**: 每次提交的说明信息都应使用中文描述本次变更的内容。

1256
docs/architecture-design.md Normal file

File diff suppressed because it is too large Load Diff

4
setup_conan.bat Normal file
View File

@@ -0,0 +1,4 @@
conan install . --build=missing --settings=build_type=Debug --settings=compiler.cppstd=23
@REM conan install . --output-folder=build --build=missing --settings=build_type=Release --settings=compiler.cppstd=23
pause

63
src/CMakeLists.txt Normal file
View File

@@ -0,0 +1,63 @@
# ================================================================================================
# Audio Backend Framework - 源代码目录CMake配置
# ================================================================================================
# 描述: 协调管理各个音频后端模块的构建
# 架构: 模块化设计,每个模块独立管理自己的包含路径和依赖
# ================================================================================================
message(STATUS "")
message(STATUS "=== 配置源代码模块 ===")
# ================================================================================================
# 核心模块 - 按依赖顺序添加
# ================================================================================================
# 公共组件模块 (最底层,其他模块依赖)
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/common/CMakeLists.txt)
add_subdirectory(common)
message(STATUS "✓ 添加公共组件模块: common/")
endif()
# 通信模块 (IPC和网络通信)
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/communication/CMakeLists.txt)
add_subdirectory(communication)
message(STATUS "✓ 添加通信模块: communication/")
endif()
# SIMD优化模块 (性能关键路径)
if(DAW_ENABLE_SIMD AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/simd/CMakeLists.txt)
add_subdirectory(simd)
message(STATUS "✓ 添加SIMD优化模块: simd/")
endif()
# 音频引擎核心模块
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/engine/CMakeLists.txt)
add_subdirectory(engine)
message(STATUS "✓ 添加音频引擎模块: engine/")
endif()
# 插件沙盒宿主模块
if(DAW_ENABLE_SANDBOX AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/plugin_host/CMakeLists.txt)
add_subdirectory(plugin_host)
message(STATUS "✓ 添加插件沙盒模块: plugin_host/")
endif()
# 前端进程模块
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/frontend/CMakeLists.txt)
add_subdirectory(frontend)
message(STATUS "✓ 添加前端进程模块: frontend/")
endif()
# ================================================================================================
# 模块配置摘要
# ================================================================================================
message(STATUS "")
message(STATUS "=== 源代码模块配置摘要 ===")
message(STATUS "架构设计: 模块化多进程系统")
message(STATUS "核心特性:")
message(STATUS " - 进程隔离: 音频引擎 | 插件沙盒 | 前端UI")
message(STATUS " - 双通道通信: ZeroMQ + Boost共享内存")
message(STATUS " - SIMD优化: ${DAW_ENABLE_SIMD}")
message(STATUS " - 插件沙盒: ${DAW_ENABLE_SANDBOX}")
message(STATUS " - 网络通信: ${DAW_ENABLE_NETWORK}")
message(STATUS "")

98
src/common/CMakeLists.txt Normal file
View File

@@ -0,0 +1,98 @@
# ================================================================================================
# Audio Backend - 公共组件模块
# ================================================================================================
# 描述: 提供基础工具类、数据结构和所有模块共享的功能
# 依赖: Boost、spdlog、fmt、nlohmann_json
# ================================================================================================
# ================================================================================================
# 自动收集源文件和头文件
# ================================================================================================
set(MODULE_SOURCES "")
retrieve_files(${CMAKE_CURRENT_SOURCE_DIR} MODULE_SOURCES)
# 如果当前没有源文件,创建一个空目标占位
if(NOT MODULE_SOURCES)
message(STATUS "Common模块: 当前无源文件,创建接口库占位")
add_library(audio_backend_common INTERFACE)
add_library(AudioBackend::Common ALIAS audio_backend_common)
# 设置接口包含路径
target_include_directories(audio_backend_common INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}
)
# 设置接口依赖
target_link_libraries(audio_backend_common INTERFACE
${audio_backend_project_options}
Boost::boost
Boost::filesystem
Boost::system
Boost::thread
spdlog::spdlog
fmt::fmt
nlohmann_json::nlohmann_json
yaml-cpp::yaml-cpp
)
return()
endif()
# ================================================================================================
# 库目标定义
# ================================================================================================
add_library(audio_backend_common STATIC ${MODULE_SOURCES})
# 设置别名,使其他模块可以使用命名空间风格引用此库
add_library(AudioBackend::Common ALIAS audio_backend_common)
# ================================================================================================
# 目标属性配置
# ================================================================================================
target_include_directories(audio_backend_common
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)
# ================================================================================================
# 依赖关系配置
# ================================================================================================
target_link_libraries(audio_backend_common
PUBLIC
${audio_backend_project_options}
Boost::boost
Boost::filesystem
Boost::system
Boost::thread
PRIVATE
spdlog::spdlog
fmt::fmt
nlohmann_json::nlohmann_json
yaml-cpp::yaml-cpp
)
# ================================================================================================
# 目标编译定义
# ================================================================================================
target_compile_definitions(audio_backend_common
PRIVATE
AUDIO_BACKEND_COMMON_EXPORTS
PUBLIC
$<$<BOOL:${DAW_ENABLE_PROFILING}>:AUDIO_BACKEND_ENABLE_PROFILING>
)
# ================================================================================================
# 操作系统平台定义
# ================================================================================================
add_os_definitions(audio_backend_common)
# ================================================================================================
# 安装规则
# ================================================================================================
install(TARGETS audio_backend_common
EXPORT AudioBackendTargets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
message(STATUS "Common模块: 已配置 ${MODULE_SOURCES}个文件")

297
src/common/error.cpp Normal file
View File

@@ -0,0 +1,297 @@
// ================================================================================================
// Audio Backend - 错误处理和异常类实现
// ================================================================================================
#include "error.h"
#include <algorithm>
#include <unordered_map>
#if ALICHO_PLATFORM_WINDOWS
#include <windows.h>
#elif ALICHO_PLATFORM_UNIX
#include <errno.h>
#endif
namespace audio_backend::common {
// ================================================================================================
// 错误码描述映射
// ================================================================================================
static const std::unordered_map<ErrorCode, std::string> error_descriptions = {
// 通用错误
{ErrorCode::SUCCESS, "操作成功"},
{ErrorCode::UNKNOWN_ERROR, "未知错误"},
{ErrorCode::INVALID_ARGUMENT, "无效参数"},
{ErrorCode::INVALID_OPERATION, "无效操作"},
{ErrorCode::NOT_IMPLEMENTED, "功能未实现"},
{ErrorCode::OUT_OF_MEMORY, "内存不足"},
{ErrorCode::OPERATION_TIMED_OUT, "操作超时"},
{ErrorCode::NOT_INITIALIZED, "未初始化"},
{ErrorCode::ALREADY_INITIALIZED, "已经初始化"},
// 文件和I/O错误
{ErrorCode::FILE_NOT_FOUND, "文件未找到"},
{ErrorCode::FILE_ACCESS_DENIED, "文件访问被拒绝"},
{ErrorCode::FILE_READ_ERROR, "文件读取错误"},
{ErrorCode::FILE_WRITE_ERROR, "文件写入错误"},
{ErrorCode::FILE_FORMAT_ERROR, "文件格式错误"},
// 音频处理错误
{ErrorCode::AUDIO_FORMAT_ERROR, "音频格式错误"},
{ErrorCode::AUDIO_DEVICE_ERROR, "音频设备错误"},
{ErrorCode::AUDIO_BUFFER_UNDERRUN, "音频缓冲区欠载"},
{ErrorCode::AUDIO_BUFFER_OVERRUN, "音频缓冲区溢出"},
{ErrorCode::AUDIO_SAMPLE_RATE_MISMATCH, "采样率不匹配"},
{ErrorCode::AUDIO_CHANNEL_COUNT_MISMATCH, "声道数不匹配"},
// 插件错误
{ErrorCode::PLUGIN_LOAD_ERROR, "插件加载错误"},
{ErrorCode::PLUGIN_NOT_FOUND, "插件未找到"},
{ErrorCode::PLUGIN_VERSION_MISMATCH, "插件版本不匹配"},
{ErrorCode::PLUGIN_INITIALIZATION_ERROR, "插件初始化错误"},
{ErrorCode::PLUGIN_COMMUNICATION_ERROR, "插件通信错误"},
{ErrorCode::PLUGIN_EXECUTION_ERROR, "插件执行错误"},
{ErrorCode::PLUGIN_TIMEOUT, "插件超时"},
// 通信错误
{ErrorCode::COMMUNICATION_ERROR, "通信错误"},
{ErrorCode::CONNECTION_ERROR, "连接错误"},
{ErrorCode::DISCONNECTED, "连接已断开"},
{ErrorCode::MESSAGE_FORMAT_ERROR, "消息格式错误"},
{ErrorCode::PROTOCOL_ERROR, "协议错误"},
{ErrorCode::TIMEOUT, "超时"},
// 系统错误
{ErrorCode::SYSTEM_ERROR, "系统错误"},
{ErrorCode::PERMISSION_DENIED, "权限被拒绝"},
{ErrorCode::NOT_ENOUGH_RESOURCES, "资源不足"}
};
// ================================================================================================
// 错误分类映射
// ================================================================================================
static const std::unordered_map<ErrorCode, ErrorCategory> error_categories = {
// 通用错误
{ErrorCode::SUCCESS, ErrorCategory::GENERAL},
{ErrorCode::UNKNOWN_ERROR, ErrorCategory::GENERAL},
{ErrorCode::INVALID_ARGUMENT, ErrorCategory::GENERAL},
{ErrorCode::INVALID_OPERATION, ErrorCategory::GENERAL},
{ErrorCode::NOT_IMPLEMENTED, ErrorCategory::GENERAL},
{ErrorCode::OUT_OF_MEMORY, ErrorCategory::GENERAL},
{ErrorCode::OPERATION_TIMED_OUT, ErrorCategory::GENERAL},
{ErrorCode::NOT_INITIALIZED, ErrorCategory::GENERAL},
{ErrorCode::ALREADY_INITIALIZED, ErrorCategory::GENERAL},
// 文件错误
{ErrorCode::FILE_NOT_FOUND, ErrorCategory::FILE},
{ErrorCode::FILE_ACCESS_DENIED, ErrorCategory::FILE},
{ErrorCode::FILE_READ_ERROR, ErrorCategory::FILE},
{ErrorCode::FILE_WRITE_ERROR, ErrorCategory::FILE},
{ErrorCode::FILE_FORMAT_ERROR, ErrorCategory::FILE},
// 音频错误
{ErrorCode::AUDIO_FORMAT_ERROR, ErrorCategory::AUDIO},
{ErrorCode::AUDIO_DEVICE_ERROR, ErrorCategory::AUDIO},
{ErrorCode::AUDIO_BUFFER_UNDERRUN, ErrorCategory::AUDIO},
{ErrorCode::AUDIO_BUFFER_OVERRUN, ErrorCategory::AUDIO},
{ErrorCode::AUDIO_SAMPLE_RATE_MISMATCH, ErrorCategory::AUDIO},
{ErrorCode::AUDIO_CHANNEL_COUNT_MISMATCH, ErrorCategory::AUDIO},
// 插件错误
{ErrorCode::PLUGIN_LOAD_ERROR, ErrorCategory::PLUGIN},
{ErrorCode::PLUGIN_NOT_FOUND, ErrorCategory::PLUGIN},
{ErrorCode::PLUGIN_VERSION_MISMATCH, ErrorCategory::PLUGIN},
{ErrorCode::PLUGIN_INITIALIZATION_ERROR, ErrorCategory::PLUGIN},
{ErrorCode::PLUGIN_COMMUNICATION_ERROR, ErrorCategory::PLUGIN},
{ErrorCode::PLUGIN_EXECUTION_ERROR, ErrorCategory::PLUGIN},
{ErrorCode::PLUGIN_TIMEOUT, ErrorCategory::PLUGIN},
// 通信错误
{ErrorCode::COMMUNICATION_ERROR, ErrorCategory::COMMUNICATION},
{ErrorCode::CONNECTION_ERROR, ErrorCategory::COMMUNICATION},
{ErrorCode::DISCONNECTED, ErrorCategory::COMMUNICATION},
{ErrorCode::MESSAGE_FORMAT_ERROR, ErrorCategory::COMMUNICATION},
{ErrorCode::PROTOCOL_ERROR, ErrorCategory::COMMUNICATION},
{ErrorCode::TIMEOUT, ErrorCategory::COMMUNICATION},
// 系统错误
{ErrorCode::SYSTEM_ERROR, ErrorCategory::SYSTEM},
{ErrorCode::PERMISSION_DENIED, ErrorCategory::SYSTEM},
{ErrorCode::NOT_ENOUGH_RESOURCES, ErrorCategory::SYSTEM}
};
// ================================================================================================
// 公共函数实现
// ================================================================================================
ErrorCategory get_error_category(ErrorCode code) {
auto it = error_categories.find(code);
if (it != error_categories.end()) {
return it->second;
}
return ErrorCategory::GENERAL;
}
std::string get_error_description(ErrorCode code) {
auto it = error_descriptions.find(code);
if (it != error_descriptions.end()) {
return it->second;
}
return "未知错误代码: " + std::to_string(static_cast<int>(code));
}
std::exception_ptr create_exception(ErrorCode code,
const std::string& message,
const std::string& details) {
ErrorCategory category = get_error_category(code);
try {
switch (category) {
case ErrorCategory::FILE:
throw FileException(code, message, details);
case ErrorCategory::AUDIO:
throw AudioException(code, message, details);
case ErrorCategory::PLUGIN:
throw PluginException(code, message, details);
case ErrorCategory::COMMUNICATION:
throw CommunicationException(code, message, details);
case ErrorCategory::SYSTEM:
throw SystemException(code, message, details);
default:
throw AudioBackendException(code, message, details);
}
} catch (...) {
return std::current_exception();
}
}
void throw_exception(ErrorCode code,
const std::string& message,
const std::string& details) {
std::rethrow_exception(create_exception(code, message, details));
}
void check_error(bool condition,
ErrorCode error_code,
const std::string& message,
const std::string& details) {
if (condition) {
throw_exception(error_code, message, details);
}
}
ErrorCode system_error_to_error_code(int system_error) {
#if ALICHO_PLATFORM_WINDOWS
switch (system_error) {
case ERROR_FILE_NOT_FOUND:
case ERROR_PATH_NOT_FOUND:
return ErrorCode::FILE_NOT_FOUND;
case ERROR_ACCESS_DENIED:
return ErrorCode::FILE_ACCESS_DENIED;
case ERROR_NOT_ENOUGH_MEMORY:
case ERROR_OUTOFMEMORY:
return ErrorCode::OUT_OF_MEMORY;
case ERROR_TIMEOUT:
return ErrorCode::OPERATION_TIMED_OUT;
case ERROR_INVALID_PARAMETER:
return ErrorCode::INVALID_ARGUMENT;
default:
return ErrorCode::SYSTEM_ERROR;
}
#elif ALICHO_PLATFORM_UNIX
switch (system_error) {
case ENOENT:
return ErrorCode::FILE_NOT_FOUND;
case EACCES:
case EPERM:
return ErrorCode::FILE_ACCESS_DENIED;
case ENOMEM:
return ErrorCode::OUT_OF_MEMORY;
case ETIMEDOUT:
return ErrorCode::OPERATION_TIMED_OUT;
case EINVAL:
return ErrorCode::INVALID_ARGUMENT;
default:
return ErrorCode::SYSTEM_ERROR;
}
#else
return ErrorCode::SYSTEM_ERROR;
#endif
}
ErrorCode std_error_to_error_code(const std::error_code& ec) {
if (ec.category() == std::generic_category()) {
return system_error_to_error_code(ec.value());
} else if (ec.category() == AudioBackendErrorCategory::instance()) {
return static_cast<ErrorCode>(ec.value());
} else {
return ErrorCode::SYSTEM_ERROR;
}
}
// ================================================================================================
// ErrorHandler实现
// ================================================================================================
void ErrorHandler::add_error_handler(const ErrorCallback& handler) {
handlers_.push_back(handler);
}
void ErrorHandler::remove_error_handler(const ErrorCallback& handler) {
// 注意这个比较可能不会按预期工作因为std::function的比较很复杂
// 在实际使用中可能需要使用其他方式来管理处理器比如返回ID
auto it = std::find_if(handlers_.begin(), handlers_.end(),
[&handler](const ErrorCallback& h) {
// 这里的比较不太可靠,应该考虑使用其他方式
return &h == &handler;
});
if (it != handlers_.end()) {
handlers_.erase(it);
}
}
void ErrorHandler::handle_error(const AudioBackendException& exception) {
for (const auto& handler : handlers_) {
try {
handler(exception);
} catch (...) {
// 忽略错误处理器中的异常,防止无限递归
}
}
}
void ErrorHandler::handle_error(ErrorCode code,
const std::string& message,
const std::string& details) {
try {
AudioBackendException exception(code, message, details);
handle_error(exception);
} catch (...) {
// 忽略创建异常时的错误
}
}
void ErrorHandler::handle_exception(std::exception_ptr eptr) {
if (!eptr) return;
try {
std::rethrow_exception(eptr);
} catch (const AudioBackendException& e) {
handle_error(e);
} catch (const std::exception& e) {
// 对于其他标准异常创建一个通用的AudioBackendException
AudioBackendException wrapper(ErrorCode::UNKNOWN_ERROR, e.what());
handle_error(wrapper);
} catch (...) {
// 对于其他异常,创建一个未知错误
AudioBackendException wrapper(ErrorCode::UNKNOWN_ERROR, "未知异常类型");
handle_error(wrapper);
}
}
void ErrorHandler::clear_handlers() {
handlers_.clear();
}
} // namespace audio_backend::common

382
src/common/error.h Normal file
View File

@@ -0,0 +1,382 @@
// ================================================================================================
// Audio Backend - 错误处理和异常类
// ================================================================================================
// 描述: 定义自定义异常层次结构和错误处理机制
// 功能: 提供统一的异常类型和错误码
// ================================================================================================
#pragma once
#include <stdexcept>
#include <string>
#include <system_error>
#include <vector>
#include <functional>
namespace audio_backend::common {
// ================================================================================================
// 错误码定义
// ================================================================================================
enum class ErrorCode {
// 通用错误 (0-999)
SUCCESS = 0,
UNKNOWN_ERROR = 1,
INVALID_ARGUMENT = 2,
INVALID_OPERATION = 3,
NOT_IMPLEMENTED = 4,
OUT_OF_MEMORY = 5,
OPERATION_TIMED_OUT = 6,
NOT_INITIALIZED = 7,
ALREADY_INITIALIZED = 8,
// 文件和I/O错误 (1000-1999)
FILE_NOT_FOUND = 1000,
FILE_ACCESS_DENIED = 1001,
FILE_READ_ERROR = 1002,
FILE_WRITE_ERROR = 1003,
FILE_FORMAT_ERROR = 1004,
// 音频处理错误 (2000-2999)
AUDIO_FORMAT_ERROR = 2000,
AUDIO_DEVICE_ERROR = 2001,
AUDIO_BUFFER_UNDERRUN = 2002,
AUDIO_BUFFER_OVERRUN = 2003,
AUDIO_SAMPLE_RATE_MISMATCH = 2004,
AUDIO_CHANNEL_COUNT_MISMATCH = 2005,
// 插件错误 (3000-3999)
PLUGIN_LOAD_ERROR = 3000,
PLUGIN_NOT_FOUND = 3001,
PLUGIN_VERSION_MISMATCH = 3002,
PLUGIN_INITIALIZATION_ERROR = 3003,
PLUGIN_COMMUNICATION_ERROR = 3004,
PLUGIN_EXECUTION_ERROR = 3005,
PLUGIN_TIMEOUT = 3006,
// 通信错误 (4000-4999)
COMMUNICATION_ERROR = 4000,
CONNECTION_ERROR = 4001,
DISCONNECTED = 4002,
MESSAGE_FORMAT_ERROR = 4003,
PROTOCOL_ERROR = 4004,
TIMEOUT = 4005,
// 系统错误 (5000-5999)
SYSTEM_ERROR = 5000,
PERMISSION_DENIED = 5001,
NOT_ENOUGH_RESOURCES = 5002
};
// ================================================================================================
// 错误分类定义
// ================================================================================================
enum class ErrorCategory {
GENERAL,
FILE,
AUDIO,
PLUGIN,
COMMUNICATION,
SYSTEM
};
// 获取错误分类
ErrorCategory get_error_category(ErrorCode code);
// 获取错误码对应的描述信息
std::string get_error_description(ErrorCode code);
// ================================================================================================
// 自定义错误类别std::error_category扩展
// ================================================================================================
class AudioBackendErrorCategory : public std::error_category {
public:
static const AudioBackendErrorCategory& instance() {
static AudioBackendErrorCategory instance;
return instance;
}
const char* name() const noexcept override {
return "audio_backend";
}
std::string message(int ev) const override {
return get_error_description(static_cast<ErrorCode>(ev));
}
private:
AudioBackendErrorCategory() = default;
};
// 创建error_code
inline std::error_code make_error_code(ErrorCode e) {
return {static_cast<int>(e), AudioBackendErrorCategory::instance()};
}
// ================================================================================================
// 基础异常类
// ================================================================================================
class AudioBackendException : public std::exception {
public:
explicit AudioBackendException(ErrorCode code,
const std::string& message = "",
const std::string& details = "")
: code_(code), message_(message), details_(details) {
// 如果没有提供消息,使用默认的错误描述
if (message_.empty()) {
message_ = get_error_description(code);
}
// 构建完整的错误消息
if (!details_.empty()) {
full_message_ = message_ + " - " + details_;
} else {
full_message_ = message_;
}
}
// 获取错误码
ErrorCode code() const noexcept {
return code_;
}
// 获取错误消息
const std::string& message() const noexcept {
return message_;
}
// 获取详细信息
const std::string& details() const noexcept {
return details_;
}
// 获取完整错误消息
const char* what() const noexcept override {
return full_message_.c_str();
}
// 获取错误分类
ErrorCategory category() const noexcept {
return get_error_category(code_);
}
// 获取std::error_code
std::error_code error_code() const noexcept {
return make_error_code(code_);
}
// 是否是某个错误码
bool is(ErrorCode code) const noexcept {
return code_ == code;
}
// 是否属于某个错误分类
bool is_category(ErrorCategory category) const noexcept {
return category == get_error_category(code_);
}
private:
ErrorCode code_;
std::string message_;
std::string details_;
std::string full_message_;
};
// ================================================================================================
// 具体异常类
// ================================================================================================
// 文件异常
class FileException : public AudioBackendException {
public:
explicit FileException(ErrorCode code,
const std::string& message = "",
const std::string& details = "")
: AudioBackendException(code, message, details) {
if (!is_category(ErrorCategory::FILE)) {
throw std::invalid_argument("错误码不属于文件异常类别");
}
}
};
// 音频异常
class AudioException : public AudioBackendException {
public:
explicit AudioException(ErrorCode code,
const std::string& message = "",
const std::string& details = "")
: AudioBackendException(code, message, details) {
if (!is_category(ErrorCategory::AUDIO)) {
throw std::invalid_argument("错误码不属于音频异常类别");
}
}
};
// 插件异常
class PluginException : public AudioBackendException {
public:
explicit PluginException(ErrorCode code,
const std::string& message = "",
const std::string& details = "")
: AudioBackendException(code, message, details) {
if (!is_category(ErrorCategory::PLUGIN)) {
throw std::invalid_argument("错误码不属于插件异常类别");
}
}
};
// 通信异常
class CommunicationException : public AudioBackendException {
public:
explicit CommunicationException(ErrorCode code,
const std::string& message = "",
const std::string& details = "")
: AudioBackendException(code, message, details) {
if (!is_category(ErrorCategory::COMMUNICATION)) {
throw std::invalid_argument("错误码不属于通信异常类别");
}
}
};
// 系统异常
class SystemException : public AudioBackendException {
public:
explicit SystemException(ErrorCode code,
const std::string& message = "",
const std::string& details = "")
: AudioBackendException(code, message, details) {
if (!is_category(ErrorCategory::SYSTEM)) {
throw std::invalid_argument("错误码不属于系统异常类别");
}
}
};
// ================================================================================================
// 错误处理工具函数
// ================================================================================================
// 根据错误码创建适当的异常
std::exception_ptr create_exception(ErrorCode code,
const std::string& message = "",
const std::string& details = "");
// 根据错误码抛出异常
[[noreturn]] void throw_exception(ErrorCode code,
const std::string& message = "",
const std::string& details = "");
// 错误检查函数条件为true时抛出异常
void check_error(bool condition,
ErrorCode error_code,
const std::string& message = "",
const std::string& details = "");
// 将系统错误码转换为AudioBackend错误码
ErrorCode system_error_to_error_code(int system_error);
// 将std::error_code转换为AudioBackend错误码
ErrorCode std_error_to_error_code(const std::error_code& ec);
// ================================================================================================
// 错误处理器(用于收集和处理错误)
// ================================================================================================
class ErrorHandler {
public:
// 错误处理回调函数类型
using ErrorCallback = std::function<void(const AudioBackendException&)>;
// 获取单例实例
static ErrorHandler& instance() {
static ErrorHandler instance;
return instance;
}
// 禁止拷贝和移动
ErrorHandler(const ErrorHandler&) = delete;
ErrorHandler& operator=(const ErrorHandler&) = delete;
ErrorHandler(ErrorHandler&&) = delete;
ErrorHandler& operator=(ErrorHandler&&) = delete;
// 添加全局错误处理回调
void add_error_handler(const ErrorCallback& handler);
// 移除错误处理回调
void remove_error_handler(const ErrorCallback& handler);
// 处理错误
void handle_error(const AudioBackendException& exception);
// 处理错误(从错误码创建异常)
void handle_error(ErrorCode code,
const std::string& message = "",
const std::string& details = "");
// 处理异常捕获
void handle_exception(std::exception_ptr eptr);
// 清除所有错误处理回调
void clear_handlers();
private:
ErrorHandler() = default;
~ErrorHandler() = default;
std::vector<ErrorCallback> handlers_;
};
// ================================================================================================
// RAII风格的错误处理辅助类
// ================================================================================================
class ScopedErrorHandler {
public:
explicit ScopedErrorHandler(ErrorHandler::ErrorCallback handler) {
ErrorHandler::instance().add_error_handler(handler);
}
~ScopedErrorHandler() {
ErrorHandler::instance().remove_error_handler(handler_);
}
// 禁止拷贝和移动
ScopedErrorHandler(const ScopedErrorHandler&) = delete;
ScopedErrorHandler& operator=(const ScopedErrorHandler&) = delete;
ScopedErrorHandler(ScopedErrorHandler&&) = delete;
ScopedErrorHandler& operator=(ScopedErrorHandler&&) = delete;
private:
ErrorHandler::ErrorCallback handler_;
};
// ================================================================================================
// 宏定义
// ================================================================================================
#define AUDIO_CHECK_ERROR(condition, error_code, message) \
audio_backend::common::check_error((condition), (error_code), (message), \
"文件: " __FILE__ ", 行: " + std::to_string(__LINE__))
#define AUDIO_THROW_ERROR(error_code, message) \
audio_backend::common::throw_exception((error_code), (message), \
"文件: " __FILE__ ", 行: " + std::to_string(__LINE__))
#define AUDIO_HANDLE_ERROR(error_code, message) \
audio_backend::common::ErrorHandler::instance().handle_error((error_code), (message), \
"文件: " __FILE__ ", 行: " + std::to_string(__LINE__))
#define AUDIO_TRY_CATCH_ALL() \
try
#define AUDIO_CATCH_ALL() \
catch(...) { \
audio_backend::common::ErrorHandler::instance().handle_exception(std::current_exception()); \
}
} // namespace audio_backend::common
// ================================================================================================
// 在std命名空间添加特化允许将ErrorCode作为错误码使用
// ================================================================================================
namespace std {
template<>
struct is_error_code_enum<audio_backend::common::ErrorCode> : public true_type {};
} // namespace std

181
src/common/logger.cpp Normal file
View File

@@ -0,0 +1,181 @@
// ================================================================================================
// Audio Backend - 日志系统实现
// ================================================================================================
#include "logger.h"
#include <filesystem>
#include <iostream>
#if ALICHO_PLATFORM_WINDOWS
#include <windows.h>
#endif
namespace audio_backend::common {
namespace fs = std::filesystem;
// ================================================================================================
// Logger实现
// ================================================================================================
Logger::Logger() = default;
Logger::~Logger() {
shutdown();
}
void Logger::initialize(const std::string& app_name,
LogLevel console_level,
bool file_logging,
const std::string& log_dir,
size_t max_file_size,
size_t max_files) {
if (initialized_) {
return; // 已经初始化
}
try {
// 创建控制台sink
console_sink_ = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
console_sink_->set_level(static_cast<spdlog::level::level_enum>(console_level));
console_sink_->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] [%n] %v");
std::vector<spdlog::sink_ptr> sinks;
sinks.push_back(console_sink_);
// 如果启用文件日志创建文件sink
if (file_logging) {
create_log_directory(log_dir);
log_directory_ = log_dir;
// 创建日志文件路径
fs::path log_file_path = fs::path(log_dir) / (app_name + ".log");
file_sink_ = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(
log_file_path.string(), max_file_size, max_files);
file_sink_->set_level(spdlog::level::trace); // 文件记录所有级别
file_sink_->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%l] [%n] [%t] %v");
sinks.push_back(file_sink_);
}
// 创建主日志器
logger_ = std::make_shared<spdlog::logger>(app_name, sinks.begin(), sinks.end());
logger_->set_level(spdlog::level::trace); // 总是记录所有级别
logger_->flush_on(spdlog::level::err); // 错误时立即刷新
// 设置为默认日志器
spdlog::set_default_logger(logger_);
// 设置异步刷新
spdlog::flush_every(std::chrono::seconds(3));
initialized_ = true;
logger_->info("音频后端日志系统已初始化");
logger_->info("控制台日志级别: {}", spdlog::level::to_string_view(console_sink_->level()));
if (file_logging) {
logger_->info("文件日志目录: {}", log_dir);
}
} catch (const spdlog::spdlog_ex& ex) {
std::cerr << "日志初始化失败: " << ex.what() << std::endl;
initialized_ = false;
}
}
void Logger::shutdown() {
if (!initialized_) {
return;
}
if (logger_) {
logger_->info("关闭日志系统");
logger_->flush();
logger_.reset();
}
console_sink_.reset();
file_sink_.reset();
spdlog::shutdown();
initialized_ = false;
}
void Logger::set_level(LogLevel level) {
if (logger_) {
logger_->set_level(static_cast<spdlog::level::level_enum>(level));
}
}
void Logger::set_console_level(LogLevel level) {
if (console_sink_) {
console_sink_->set_level(static_cast<spdlog::level::level_enum>(level));
}
}
void Logger::set_file_level(LogLevel level) {
if (file_sink_) {
file_sink_->set_level(static_cast<spdlog::level::level_enum>(level));
}
}
LogLevel Logger::get_level() const {
if (logger_) {
return static_cast<LogLevel>(logger_->level());
}
return LogLevel::INFO;
}
std::shared_ptr<spdlog::logger> Logger::get_module_logger(const std::string& module_name) {
// 检查是否已存在该模块的日志器
auto existing_logger = spdlog::get(module_name);
if (existing_logger) {
return existing_logger;
}
// 创建新的模块日志器
return create_logger(module_name);
}
void Logger::flush() {
if (logger_) {
logger_->flush();
}
}
std::shared_ptr<spdlog::logger> Logger::create_logger(const std::string& logger_name) {
std::vector<spdlog::sink_ptr> sinks;
if (console_sink_) {
sinks.push_back(console_sink_);
}
if (file_sink_) {
sinks.push_back(file_sink_);
}
auto new_logger = std::make_shared<spdlog::logger>(logger_name, sinks.begin(), sinks.end());
new_logger->set_level(spdlog::level::trace);
new_logger->flush_on(spdlog::level::err);
// 注册日志器
spdlog::register_logger(new_logger);
return new_logger;
}
void Logger::create_log_directory(const std::string& dir) {
try {
fs::path log_path(dir);
if (!fs::exists(log_path)) {
fs::create_directories(log_path);
}
} catch (const fs::filesystem_error& e) {
std::cerr << "创建日志目录失败: " << e.what() << std::endl;
}
}
} // namespace audio_backend::common

179
src/common/logger.h Normal file
View File

@@ -0,0 +1,179 @@
// ================================================================================================
// Audio Backend - 日志系统
// ================================================================================================
// 描述: 基于spdlog的日志系统封装
// 功能: 提供统一的日志接口,支持多种日志级别和格式
// ================================================================================================
#pragma once
#include <spdlog/spdlog.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/sinks/rotating_file_sink.h>
#include <spdlog/fmt/ostr.h>
#include <memory>
#include <string>
#include <string_view>
namespace audio_backend::common {
// ================================================================================================
// 日志级别枚举
// ================================================================================================
enum class LogLevel {
TRACE = spdlog::level::trace,
DEBUG = spdlog::level::debug,
INFO = spdlog::level::info,
WARN = spdlog::level::warn,
ERR = spdlog::level::err,
CRITICAL = spdlog::level::critical,
OFF = spdlog::level::off
};
// ================================================================================================
// 日志系统封装类(单例模式)
// ================================================================================================
class Logger {
public:
// 获取单例实例
static Logger& instance() {
static Logger instance;
return instance;
}
// 禁止拷贝和移动
Logger(const Logger&) = delete;
Logger& operator=(const Logger&) = delete;
Logger(Logger&&) = delete;
Logger& operator=(Logger&&) = delete;
// 初始化日志系统
void initialize(const std::string& app_name = "AudioBackend",
LogLevel console_level = LogLevel::INFO,
bool file_logging = true,
const std::string& log_dir = "logs",
size_t max_file_size = 5 * 1024 * 1024,
size_t max_files = 3);
// 关闭日志系统
void shutdown();
// 设置全局日志级别
void set_level(LogLevel level);
// 设置控制台日志级别
void set_console_level(LogLevel level);
// 设置文件日志级别
void set_file_level(LogLevel level);
// 获取当前日志级别
LogLevel get_level() const;
// 获取主日志器
std::shared_ptr<spdlog::logger> get_logger() const {
return logger_;
}
// 获取特定模块的日志器
std::shared_ptr<spdlog::logger> get_module_logger(const std::string& module_name);
// 刷新日志缓冲区
void flush();
// 便捷的日志记录方法
template<typename... Args>
void trace(std::string_view fmt, const Args&... args) {
if (logger_) logger_->trace(fmt, args...);
}
template<typename... Args>
void debug(std::string_view fmt, const Args&... args) {
if (logger_) logger_->debug(fmt, args...);
}
template<typename... Args>
void info(std::string_view fmt, const Args&... args) {
if (logger_) logger_->info(fmt, args...);
}
template<typename... Args>
void warn(std::string_view fmt, const Args&... args) {
if (logger_) logger_->warn(fmt, args...);
}
template<typename... Args>
void err(std::string_view fmt, const Args&... args) {
if (logger_) logger_->error(fmt, args...);
}
template<typename... Args>
void critical(std::string_view fmt, const Args&... args) {
if (logger_) logger_->critical(fmt, args...);
}
private:
Logger();
~Logger();
// 创建日志器
std::shared_ptr<spdlog::logger> create_logger(const std::string& logger_name);
// 创建日志目录
void create_log_directory(const std::string& dir);
std::shared_ptr<spdlog::logger> logger_;
std::shared_ptr<spdlog::sinks::stdout_color_sink_mt> console_sink_;
std::shared_ptr<spdlog::sinks::rotating_file_sink_mt> file_sink_;
std::string log_directory_;
bool initialized_ = false;
};
// ================================================================================================
// 全局日志函数
// ================================================================================================
template<typename... Args>
inline void log_trace(std::string_view fmt, const Args&... args) {
Logger::instance().trace(fmt, args...);
}
template<typename... Args>
inline void log_debug(std::string_view fmt, const Args&... args) {
Logger::instance().debug(fmt, args...);
}
template<typename... Args>
inline void log_info(std::string_view fmt, const Args&... args) {
Logger::instance().info(fmt, args...);
}
template<typename... Args>
inline void log_warn(std::string_view fmt, const Args&... args) {
Logger::instance().warn(fmt, args...);
}
template<typename... Args>
inline void log_err(std::string_view fmt, const Args&... args) {
Logger::instance().err(fmt, args...);
}
template<typename... Args>
inline void log_critical(std::string_view fmt, const Args&... args) {
Logger::instance().critical(fmt, args...);
}
// ================================================================================================
// 模块日志宏
// ================================================================================================
#define AUDIO_MODULE_LOGGER(module_name) \
static auto logger = audio_backend::common::Logger::instance().get_module_logger(module_name)
#define AUDIO_LOG_TRACE(...) if (logger) logger->trace(__VA_ARGS__)
#define AUDIO_LOG_DEBUG(...) if (logger) logger->debug(__VA_ARGS__)
#define AUDIO_LOG_INFO(...) if (logger) logger->info(__VA_ARGS__)
#define AUDIO_LOG_WARN(...) if (logger) logger->warn(__VA_ARGS__)
#define AUDIO_LOG_ERR(...) if (logger) logger->error(__VA_ARGS__)
#define AUDIO_LOG_CRITICAL(...) if (logger) logger->critical(__VA_ARGS__)
} // namespace audio_backend::common

View File

@@ -0,0 +1,112 @@
# ================================================================================================
# Audio Backend - 通信模块
# ================================================================================================
# 描述: 进程间通信IPC和网络通信实现
# 功能: ZeroMQ消息队列、Boost共享内存、网络协议栈
# 依赖: ZeroMQ、cppzmq、Boost::interprocess、protobuf
# ================================================================================================
# ================================================================================================
# 自动收集源文件和头文件
# ================================================================================================
set(MODULE_SOURCES "")
retrieve_files(${CMAKE_CURRENT_SOURCE_DIR} MODULE_SOURCES)
# 如果当前没有源文件,创建一个空目标占位
if(NOT MODULE_SOURCES)
message(STATUS "Communication模块: 当前无源文件,创建接口库占位")
add_library(audio_backend_communication INTERFACE)
add_library(AudioBackend::Communication ALIAS audio_backend_communication)
# 设置接口包含路径
target_include_directories(audio_backend_communication INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}
)
# 设置接口依赖
target_link_libraries(audio_backend_communication INTERFACE
AudioBackend::Common
zeromq::zeromq
cppzmq::cppzmq
Boost::interprocess
protobuf::protobuf
${PLATFORM_LIBS}
)
return()
endif()
# ================================================================================================
# 库目标定义
# ================================================================================================
add_library(audio_backend_communication STATIC ${MODULE_SOURCES})
# 设置别名
add_library(AudioBackend::Communication ALIAS audio_backend_communication)
# ================================================================================================
# 目标属性配置
# ================================================================================================
target_include_directories(audio_backend_communication
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)
# ================================================================================================
# 依赖关系配置
# ================================================================================================
target_link_libraries(audio_backend_communication
PUBLIC
${audio_backend_project_options}
AudioBackend::Common
zeromq::zeromq
cppzmq::cppzmq
Boost::interprocess
Boost::system
Boost::thread
PRIVATE
protobuf::protobuf
${PLATFORM_LIBS}
)
# ================================================================================================
# 条件性网络支持
# ================================================================================================
if(DAW_ENABLE_NETWORK)
target_compile_definitions(audio_backend_communication
PUBLIC DAW_ENABLE_NETWORK
)
# 网络相关的平台库
if(WIN32)
target_link_libraries(audio_backend_communication PRIVATE wsock32 ws2_32)
endif()
endif()
# ================================================================================================
# 目标编译定义
# ================================================================================================
target_compile_definitions(audio_backend_communication
PRIVATE
AUDIO_BACKEND_COMMUNICATION_EXPORTS
PUBLIC
$<$<BOOL:${ENABLE_ENHANCED_IPC}>:ENHANCED_IPC_ENABLED>
)
# ================================================================================================
# 操作系统平台定义
# ================================================================================================
add_os_definitions(audio_backend_communication)
# ================================================================================================
# 安装规则
# ================================================================================================
install(TARGETS audio_backend_communication
EXPORT AudioBackendTargets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
message(STATUS "Communication模块: 已配置 ${MODULE_SOURCES}个文件")

View File

@@ -0,0 +1,67 @@
# 音频后端通信模块
## 目录结构
```
src/communication/
├── proto/ # Protobuf消息定义
│ ├── common.proto # 公共类型和枚举
│ ├── control.proto # 控制消息
│ ├── audio_meta.proto # 音频元数据
│ ├── plugin_mgmt.proto # 插件管理
│ └── status.proto # 状态同步
├── zmq/ # ZeroMQ通信实现
│ ├── socket.h/cpp # 套接字抽象
│ ├── context.h/cpp # ZMQ上下文管理
│ ├── publisher.h/cpp # 发布者实现
│ ├── subscriber.h/cpp # 订阅者实现
│ ├── requester.h/cpp # 请求者实现
│ ├── responder.h/cpp # 响应者实现
│ ├── poller.h/cpp # 事件轮询
│ └── monitor.h/cpp # 连接监控
├── shm/ # Boost共享内存实现
│ ├── memory_pool.h/cpp # 共享内存池
│ ├── ring_buffer.h/cpp # 无锁环形缓冲区
│ ├── triple_buffer.h/cpp # 三缓冲机制
│ ├── sync.h/cpp # 跨进程同步原语
│ └── allocator.h/cpp # 共享内存分配器
├── net/ # 网络通信功能
│ ├── transport.h/cpp # 传输层抽象
│ ├── discovery.h/cpp # 网络发现
│ ├── session.h/cpp # 会话管理
│ ├── stream.h/cpp # 音频流协议
│ └── security.h/cpp # 安全功能
├── core/ # 核心通信组件
│ ├── message.h/cpp # 消息抽象
│ ├── serializer.h/cpp # 序列化器
│ ├── router.h/cpp # 消息路由
│ ├── endpoint.h/cpp # 通信端点
│ └── error.h/cpp # 通信错误处理
└── manager.h/cpp # 通信管理器(统一接口)
```
## 通信策略
根据架构设计文档,系统采用双通道策略:
1. **控制通道 (ZeroMQ)**
- 用于小消息 (<4KB)
- 用例:插件状态通知、控制命令、参数更新、错误报告
- 特点:灵活的消息模式、自动重连、跨平台兼容性
2. **数据通道 (Boost共享内存)**
- 用于大数据传输 (>=4KB)
- 用例:音频缓冲区、批量参数数据、音频流
- 特点:零拷贝、低延迟、高吞吐量
## 实现概述
- **ZeroMQ通信层**封装ZeroMQ的不同消息模式(REQ-REP, PUB-SUB, PUSH-PULL),提供异步消息处理和回调机制
- **Boost共享内存**:实现共享内存池、无锁环形缓冲和三缓冲机制
- **统一通信接口**:通信管理器自动根据消息大小选择适当的传输通道
- **网络通信**实现TCP/UDP传输抽象和音频流协议

View File

@@ -0,0 +1,135 @@
// ================================================================================================
// Audio Backend - 消息抽象接口实现
// ================================================================================================
#include "message.h"
#include "logger.h"
#include <sstream>
#include <iomanip>
#include <random>
#include <atomic>
namespace audio_backend::communication {
// ================================================================================================
// Endpoint 实现
// ================================================================================================
std::string Endpoint::to_string() const {
std::ostringstream oss;
oss << "Endpoint{id=" << id
<< ", type=" << static_cast<int>(type)
<< ", address=" << address;
if (port > 0) {
oss << ", port=" << port;
}
oss << "}";
return oss.str();
}
// ================================================================================================
// IMessage 默认实现
// ================================================================================================
bool IMessage::should_use_shared_memory() const {
// 默认基于消息大小判断
return size() >= 4096; // 4KB阈值
}
TransportChannel IMessage::preferred_channel() const {
// 默认策略大消息使用共享内存小消息使用ZeroMQ
if (should_use_shared_memory()) {
return TransportChannel::SharedMemory;
}
// 根据优先级选择通道
if (priority() == MessagePriority::Realtime) {
return TransportChannel::SharedMemory; // 实时消息优先使用共享内存
}
return TransportChannel::ZmqControl; // 默认使用ZeroMQ控制通道
}
// ================================================================================================
// Message 实现
// ================================================================================================
Message::Message()
: message_id_(generate_message_id())
, source_()
, destination_()
, priority_(MessagePriority::Normal)
, timestamp_(std::chrono::system_clock::now())
, raw_data_()
{
}
Message::Message(const std::string& id, const Endpoint& source, const Endpoint& destination)
: message_id_(id)
, source_(source)
, destination_(destination)
, priority_(MessagePriority::Normal)
, timestamp_(std::chrono::system_clock::now())
, raw_data_()
{
if (message_id_.empty()) {
message_id_ = generate_message_id();
}
}
TransportChannel Message::preferred_channel() const {
// 基于消息大小选择通道
if (should_use_shared_memory()) {
return TransportChannel::SharedMemory;
}
// 实时优先级的消息优先使用共享内存以降低延迟
if (priority_ == MessagePriority::Realtime) {
return TransportChannel::SharedMemory;
}
// 关键消息使用可靠的ZeroMQ通道
if (priority_ == MessagePriority::Critical) {
return TransportChannel::ZmqControl;
}
return TransportChannel::ZmqControl;
}
bool Message::should_use_shared_memory() const {
return raw_data_.size() >= SHARED_MEMORY_THRESHOLD;
}
// ================================================================================================
// 消息ID生成
// ================================================================================================
std::string generate_message_id() {
// 使用原子计数器和时间戳生成唯一ID
static std::atomic<uint64_t> counter{0};
auto now = std::chrono::system_clock::now();
auto timestamp = std::chrono::duration_cast<std::chrono::microseconds>(
now.time_since_epoch()).count();
uint64_t count = counter.fetch_add(1, std::memory_order_relaxed);
// 格式: timestamp-counter-random
std::ostringstream oss;
oss << std::hex << std::setfill('0');
oss << std::setw(16) << timestamp;
oss << "-";
oss << std::setw(8) << count;
oss << "-";
// 添加随机部分以进一步确保唯一性
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<uint32_t> dis(0, 0xFFFFFFFF);
oss << std::setw(8) << dis(gen);
return oss.str();
}
} // namespace audio_backend::communication

View File

@@ -0,0 +1,199 @@
// ================================================================================================
// Audio Backend - 消息抽象接口
// ================================================================================================
// 描述: 定义通信模块消息的基础接口和结构
// 功能: 提供统一的消息处理方式,支持不同类型的消息传输
// ================================================================================================
#pragma once
#include <cstdint>
#include <string>
#include <vector>
#include <memory>
#include <chrono>
#include "error.h"
namespace audio_backend::communication {
// 消息优先级定义与Proto定义保持一致
enum class MessagePriority {
Low = 0, // 低优先级(日志、统计等)
Normal = 1, // 普通优先级(一般控制消息)
High = 2, // 高优先级(重要状态更新)
Critical = 3, // 关键优先级(错误、紧急停止)
Realtime = 4 // 实时优先级(音频处理相关)
};
// 传输通道类型与Proto定义保持一致
enum class TransportChannel {
ZmqControl = 0, // ZeroMQ控制通道
SharedMemory = 1, // 共享内存通道
NetworkTcp = 2, // 网络TCP通道
NetworkUdp = 3, // 网络UDP通道
LocalIpc = 4 // 本地IPC通道
};
// 端点类型与Proto定义保持一致
enum class EndpointType {
Unknown = 0,
AudioEngine = 1, // 音频引擎
PluginSandbox = 2, // 插件沙盒
Frontend = 3, // 前端进程
RemoteClient = 4, // 远程客户端
NetworkNode = 5 // 网络节点
};
// 通信端点定义
struct Endpoint {
std::string id; // 端点唯一标识符
EndpointType type; // 端点类型
std::string address; // 端点地址
int32_t port; // 端口号(网络通信时使用)
Endpoint() = default;
Endpoint(const std::string& id_, EndpointType type_,
const std::string& addr_, int32_t port_ = 0)
: id(id_), type(type_), address(addr_), port(port_) {}
bool operator==(const Endpoint& other) const {
return id == other.id && type == other.type &&
address == other.address && port == other.port;
}
bool operator!=(const Endpoint& other) const {
return !(*this == other);
}
// 转换为字符串表示,用于日志等
std::string to_string() const;
};
// 消息接口
class IMessage {
public:
virtual ~IMessage() = default;
// 获取消息类型标识
virtual std::string message_type() const = 0;
// 获取消息唯一标识符
virtual std::string message_id() const = 0;
// 获取消息来源端点
virtual Endpoint source() const = 0;
// 获取消息目标端点(如果有)
virtual Endpoint destination() const = 0;
// 获取消息优先级
virtual MessagePriority priority() const = 0;
// 获取消息创建时间戳
virtual std::chrono::system_clock::time_point timestamp() const = 0;
// 获取消息的原始数据
virtual const std::vector<uint8_t>& raw_data() const = 0;
// 消息大小(字节数)
virtual size_t size() const = 0;
// 克隆消息
virtual std::unique_ptr<IMessage> clone() const = 0;
// 确定此消息是否应该使用共享内存传输
virtual bool should_use_shared_memory() const;
// 获取首选传输通道
virtual TransportChannel preferred_channel() const;
// 消息转换为字符串表示,用于调试和日志
virtual std::string to_string() const = 0;
};
// 基础消息类,实现通用功能
class Message : public IMessage {
public:
Message();
Message(const std::string& id, const Endpoint& source,
const Endpoint& destination = Endpoint());
virtual ~Message() = default;
// IMessage 接口实现
std::string message_id() const override { return message_id_; }
Endpoint source() const override { return source_; }
Endpoint destination() const override { return destination_; }
MessagePriority priority() const override { return priority_; }
std::chrono::system_clock::time_point timestamp() const override { return timestamp_; }
const std::vector<uint8_t>& raw_data() const override { return raw_data_; }
size_t size() const override { return raw_data_.size(); }
// 设置方法
void set_message_id(const std::string& id) { message_id_ = id; }
void set_source(const Endpoint& source) { source_ = source; }
void set_destination(const Endpoint& destination) { destination_ = destination; }
void set_priority(MessagePriority priority) { priority_ = priority; }
void set_timestamp(const std::chrono::system_clock::time_point& time) { timestamp_ = time; }
void set_raw_data(const std::vector<uint8_t>& data) { raw_data_ = data; }
void set_raw_data(std::vector<uint8_t>&& data) { raw_data_ = std::move(data); }
// 默认首选通道实现
TransportChannel preferred_channel() const override;
// 基于消息大小确定是否使用共享内存
bool should_use_shared_memory() const override;
protected:
std::string message_id_;
Endpoint source_;
Endpoint destination_;
MessagePriority priority_;
std::chrono::system_clock::time_point timestamp_;
std::vector<uint8_t> raw_data_;
// 消息大小阈值(大于此值使用共享内存)
static constexpr size_t SHARED_MEMORY_THRESHOLD = 4 * 1024; // 4KB
};
// 工厂函数创建新的消息ID
std::string generate_message_id();
// 消息工厂类
class MessageFactory {
public:
// 创建消息的工厂方法
template<typename MessageType, typename... Args>
static std::unique_ptr<MessageType> create(Args&&... args) {
auto message = std::make_unique<MessageType>(std::forward<Args>(args)...);
// 确保所有消息都有有效的消息ID
if (message->message_id().empty()) {
message->set_message_id(generate_message_id());
}
return message;
}
};
// 消息处理结果状态
enum class MessageHandleResult {
Success, // 成功处理
Error, // 处理出错
NotHandled, // 未处理(无对应处理器)
InvalidMessage, // 无效消息
Timeout // 处理超时
};
// 消息处理器接口
class IMessageHandler {
public:
virtual ~IMessageHandler() = default;
// 处理消息,返回处理结果
virtual MessageHandleResult handle_message(const IMessage& message) = 0;
// 检查处理器是否可以处理此类型的消息
virtual bool can_handle(const IMessage& message) = 0;
};
} // namespace audio_backend::communication

View File

@@ -0,0 +1,222 @@
// ================================================================================================
// Audio Backend - 消息序列化器实现
// ================================================================================================
#include "serializer.h"
#include <cstring>
// 跨平台网络字节序转换
#ifdef _WIN32
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#else
#include <arpa/inet.h>
#endif
namespace audio_backend::communication {
// 使用全局日志函数
using audio_backend::common::log_info;
using audio_backend::common::log_warn;
using audio_backend::common::log_err;
using audio_backend::common::log_debug;
namespace audio_backend::communication {
// ================================================================================================
// ProtobufSerializer 实现
// ================================================================================================
ProtobufSerializer::ProtobufSerializer() {
log_info("初始化Protobuf序列化器");
}
SerializationError ProtobufSerializer::serialize(const IMessage& message, std::vector<uint8_t>& output) {
const std::string& type_name = message.message_type();
// 查找序列化函数
auto it = serialize_funcs_.find(type_name);
if (it == serialize_funcs_.end()) {
log_err("未找到消息类型 '%s' 的序列化函数", type_name.c_str());
return SerializationError::UnsupportedType;
}
// 序列化消息内容
std::vector<uint8_t> message_data;
SerializationError result = it->second(message, message_data);
if (result != SerializationError::Success) {
log_err("序列化消息类型 '%s' 失败: %d", type_name.c_str(), static_cast<int>(result));
return result;
}
// 构建完整的消息,包含消息头
MessageHeader header;
header.magic = htonl(HEADER_MAGIC);
header.version = htons(CURRENT_VERSION);
header.type_length = htons(static_cast<uint16_t>(type_name.length()));
// 计算总大小
size_t total_size = HEADER_SIZE + type_name.length() + message_data.size();
output.reserve(total_size);
output.clear();
// 写入消息头
const uint8_t* header_bytes = reinterpret_cast<const uint8_t*>(&header);
output.insert(output.end(), header_bytes, header_bytes + HEADER_SIZE);
// 写入消息类型
output.insert(output.end(), type_name.begin(), type_name.end());
// 写入消息数据
output.insert(output.end(), message_data.begin(), message_data.end());
log_debug("成功序列化消息类型 '%s', 大小: %zu 字节", type_name.c_str(), output.size());
return SerializationError::Success;
}
SerializationError ProtobufSerializer::deserialize(const std::vector<uint8_t>& data, std::unique_ptr<IMessage>& output) {
if (data.size() < HEADER_SIZE) {
log_err("数据大小不足以包含消息头: %zu < %zu", data.size(), HEADER_SIZE);
return SerializationError::InvalidInput;
}
// 解析消息头
MessageHeader header;
std::memcpy(&header, data.data(), HEADER_SIZE);
// 验证魔术数字
if (ntohl(header.magic) != HEADER_MAGIC) {
log_err("无效的消息头魔术数字: 0x%08X", ntohl(header.magic));
return SerializationError::InvalidFormat;
}
// 检查版本
uint16_t version = ntohs(header.version);
if (version != CURRENT_VERSION) {
log_warn("消息版本不匹配: %d != %d", version, CURRENT_VERSION);
// 暂时继续处理,但可能需要版本兼容性处理
}
// 提取消息类型
uint16_t type_length = ntohs(header.type_length);
if (data.size() < HEADER_SIZE + type_length) {
log_err("数据大小不足以包含消息类型: %zu < %zu", data.size(), HEADER_SIZE + type_length);
return SerializationError::InvalidInput;
}
std::string message_type(data.begin() + HEADER_SIZE, data.begin() + HEADER_SIZE + type_length);
// 查找反序列化函数
auto it = deserialize_funcs_.find(message_type);
if (it == deserialize_funcs_.end()) {
log_err("未找到消类型 '%s' 的反序列化函数", message_type.c_str());
return SerializationError::UnsupportedType;
}
// 提取消息数据
size_t message_data_offset = HEADER_SIZE + type_length;
std::vector<uint8_t> message_data(data.begin() + message_data_offset, data.end());
// 反序列化消息
SerializationError result = it->second(message_data, output);
if (result != SerializationError::Success) {
log_err("反序列化消息类型 '%s' 失败: %d", message_type.c_str(), static_cast<int>(result));
return result;
}
log_debug("成功反序列化消息类型 '%s', 数据大小: %zu 字节", message_type.c_str(), message_data.size());
return SerializationError::Success;
}
bool ProtobufSerializer::supports_message_type(const std::string& message_type) const {
return serialize_funcs_.find(message_type) != serialize_funcs_.end() &&
deserialize_funcs_.find(message_type) != deserialize_funcs_.end();
}
void ProtobufSerializer::register_message_type(const std::string& type_name,
const SerializeFunction& serialize_func,
const DeserializeFunction& deserialize_func) {
serialize_funcs_[type_name] = serialize_func;
deserialize_funcs_[type_name] = deserialize_func;
log_debug("注册消息类型: '%s'", type_name.c_str());
}
std::string ProtobufSerializer::extract_message_type(const std::vector<uint8_t>& data) {
if (data.size() < HEADER_SIZE) {
return "";
}
MessageHeader header;
std::memcpy(&header, data.data(), HEADER_SIZE);
if (ntohl(header.magic) != HEADER_MAGIC) {
return "";
}
uint16_t type_length = ntohs(header.type_length);
if (data.size() < HEADER_SIZE + type_length) {
return "";
}
return std::string(data.begin() + HEADER_SIZE, data.begin() + HEADER_SIZE + type_length);
}
// ================================================================================================
// SerializerFactory 实现
// ================================================================================================
SerializerFactory& SerializerFactory::instance() {
static SerializerFactory instance;
return instance;
}
void SerializerFactory::register_serializer(const std::string& name, std::unique_ptr<ISerializer> serializer) {
if (!serializer) {
log_err("尝试注册空的序列化器: '%s'", name.c_str());
return;
}
serializers_[name] = std::move(serializer);
log_info("注册序列化器: '%s'", name.c_str());
}
ISerializer* SerializerFactory::get_serializer(const std::string& name) {
auto it = serializers_.find(name);
if (it != serializers_.end()) {
return it->second.get();
}
log_warn("未找到序列化器: '%s'", name.c_str());
return nullptr;
}
ISerializer* SerializerFactory::get_serializer_for_message_type(const std::string& message_type) {
for (const auto& pair : serializers_) {
if (pair.second->supports_message_type(message_type)) {
return pair.second.get();
}
}
log_warn("未找到支持消息类型 '%s' 的序列化器", message_type.c_str());
return nullptr;
}
ISerializer* SerializerFactory::detect_serializer(const std::vector<uint8_t>& data) {
if (data.size() < sizeof(ProtobufSerializer::MessageHeader)) {
return nullptr;
}
// 检查是否为Protobuf格式
ProtobufSerializer::MessageHeader header;
std::memcpy(&header, data.data(), sizeof(header));
if (ntohl(header.magic) == ProtobufSerializer::HEADER_MAGIC) {
return get_serializer("protobuf");
}
// 可以在这里添加其他格式的检测逻辑
log_warn("无法识别数据格式");
return nullptr;
}
} // namespace audio_backend::communication

View File

@@ -0,0 +1,177 @@
// ================================================================================================
// Audio Backend - 消息序列化器
// ================================================================================================
// 描述: 定义消息序列化和反序列化接口
// 功能: 提供消息与二进制数据之间的转换机制支持Protocol Buffers格式
// ================================================================================================
#pragma once
#include <memory>
#include <string>
#include <vector>
#include <unordered_map>
#include <functional>
#include <typeindex>
#include "message.h"
#include "error.h"
#include "logger.h"
namespace audio_backend::communication {
// ================================================================================================
// 序列化错误码
// ================================================================================================
enum class SerializationError {
Success = 0,
InvalidInput = 1, // 输入数据无效
UnsupportedType = 2, // 不支持的消息类型
SerializeError = 3, // 序列化错误
DeserializeError = 4, // 反序列化错误
BufferTooSmall = 5, // 缓冲区过小
NotImplemented = 6, // 未实现
VersionMismatch = 7, // 版本不匹配
InvalidFormat = 8 // 格式无效
};
// ================================================================================================
// 序列化器接口
// ================================================================================================
class ISerializer {
public:
virtual ~ISerializer() = default;
// 序列化消息为二进制数据
virtual SerializationError serialize(const IMessage& message, std::vector<uint8_t>& output) = 0;
// 反序列化二进制数据为消息
virtual SerializationError deserialize(const std::vector<uint8_t>& data, std::unique_ptr<IMessage>& output) = 0;
// 获取序列化器名称
virtual std::string name() const = 0;
// 检查序列化器是否支持指定的消息类型
virtual bool supports_message_type(const std::string& message_type) const = 0;
};
// ================================================================================================
// Protobuf序列化器基类
// ================================================================================================
class ProtobufSerializer : public ISerializer {
public:
ProtobufSerializer();
virtual ~ProtobufSerializer() = default;
// ISerializer接口实现
SerializationError serialize(const IMessage& message, std::vector<uint8_t>& output) override;
SerializationError deserialize(const std::vector<uint8_t>& data, std::unique_ptr<IMessage>& output) override;
std::string name() const override { return "protobuf"; }
bool supports_message_type(const std::string& message_type) const override;
protected:
// 消息类型与序列化/反序列化函数的映射
using SerializeFunction = std::function<SerializationError(const IMessage&, std::vector<uint8_t>&)>;
using DeserializeFunction = std::function<SerializationError(const std::vector<uint8_t>&, std::unique_ptr<IMessage>&)>;
// 消息类型注册
void register_message_type(const std::string& type_name,
const SerializeFunction& serialize_func,
const DeserializeFunction& deserialize_func);
// 从二进制数据中提取消息类型(消息头)
static std::string extract_message_type(const std::vector<uint8_t>& data);
// 消息头设计:固定格式的消息头,包含消息类型和版本信息
struct MessageHeader {
uint32_t magic; // 魔术数字,用于标识格式 (AUDP)
uint16_t version; // 协议版本
uint16_t type_length; // 消息类型长度
// 后跟变长的消息类型字符串,然后是消息内容
};
// 常量定义
static constexpr uint32_t HEADER_MAGIC = 0x41554450; // 'AUDP'
static constexpr uint16_t CURRENT_VERSION = 0x0001; // 当前版本
static constexpr size_t HEADER_SIZE = sizeof(MessageHeader);
private:
std::unordered_map<std::string, SerializeFunction> serialize_funcs_;
std::unordered_map<std::string, DeserializeFunction> deserialize_funcs_;
};
// ================================================================================================
// 序列化器工厂
// ================================================================================================
class SerializerFactory {
public:
// 获取实例(单例)
static SerializerFactory& instance();
// 注册序列化器
void register_serializer(const std::string& name, std::unique_ptr<ISerializer> serializer);
// 获取序列化器
ISerializer* get_serializer(const std::string& name);
// 获取支持指定消息类型的序列化器
ISerializer* get_serializer_for_message_type(const std::string& message_type);
// 根据数据格式自动选择序列化器
ISerializer* detect_serializer(const std::vector<uint8_t>& data);
private:
SerializerFactory() = default;
~SerializerFactory() = default;
// 禁止拷贝和移动
SerializerFactory(const SerializerFactory&) = delete;
SerializerFactory& operator=(const SerializerFactory&) = delete;
SerializerFactory(SerializerFactory&&) = delete;
SerializerFactory& operator=(SerializerFactory&&) = delete;
std::unordered_map<std::string, std::unique_ptr<ISerializer>> serializers_;
};
// ================================================================================================
// 序列化辅助函数
// ================================================================================================
// 序列化任意消息
template<typename MessageType>
SerializationError serialize_message(const MessageType& message, std::vector<uint8_t>& output) {
auto serializer = SerializerFactory::instance().get_serializer_for_message_type(message.message_type());
if (!serializer) {
log_err("找不到支持消息类型 '%s' 的序列化器", message.message_type().c_str());
return SerializationError::UnsupportedType;
}
return serializer->serialize(message, output);
}
// 反序列化为特定类型的消息
template<typename MessageType>
SerializationError deserialize_message(const std::vector<uint8_t>& data, std::unique_ptr<MessageType>& output) {
std::unique_ptr<IMessage> base_message;
auto serializer = SerializerFactory::instance().detect_serializer(data);
if (!serializer) {
log_err("无法确定数据的序列化格式");
return SerializationError::InvalidFormat;
}
auto result = serializer->deserialize(data, base_message);
if (result != SerializationError::Success || !base_message) {
return result;
}
// 类型转换
auto* derived = dynamic_cast<MessageType*>(base_message.get());
if (!derived) {
log_err("消息类型转换失败: 期望 '%s'", typeid(MessageType).name());
return SerializationError::UnsupportedType;
}
output.reset(derived);
base_message.release(); // 防止双重释放
return SerializationError::Success;
}
} // namespace audio_backend::communication

View File

@@ -0,0 +1,219 @@
// ================================================================================================
// Audio Backend - 音频元数据协议定义
// ================================================================================================
// 描述: 定义音频处理相关的元数据和信息
// 用途: 音频流信息、缓冲区元数据、处理链配置
// ================================================================================================
syntax = "proto3";
package audio_backend.communication.proto;
import "common.proto";
option cc_enable_arenas = true;
option optimize_for = SPEED;
// ================================================================================================
// 音频流信息
// ================================================================================================
message AudioStreamInfo {
string stream_id = 1; // 流标识符
AudioFormat format = 2; // 音频格式
StreamDirection direction = 3; // 流方向
StreamState state = 4; // 流状态
uint64 total_frames = 5; // 总帧数
uint64 current_frame = 6; // 当前帧
double duration_seconds = 7; // 持续时间(秒)
Timestamp start_time = 8; // 开始时间
map<string, string> metadata = 9; // 流元数据
}
enum StreamDirection {
STREAM_INPUT = 0; // 输入流
STREAM_OUTPUT = 1; // 输出流
STREAM_BIDIRECTIONAL = 2; // 双向流
}
enum StreamState {
STREAM_STOPPED = 0; // 停止
STREAM_STARTING = 1; // 启动中
STREAM_RUNNING = 2; // 运行中
STREAM_PAUSED = 3; // 暂停
STREAM_STOPPING = 4; // 停止中
STREAM_ERROR = 5; // 错误状态
}
// ================================================================================================
// 音频缓冲区元数据
// ================================================================================================
message AudioBufferMetadata {
string buffer_id = 1; // 缓冲区ID
AudioFormat format = 2; // 音频格式
uint32 frame_count = 3; // 帧数
uint64 timestamp_samples = 4; // 时间戳(样本为单位)
double timestamp_seconds = 5; // 时间戳(秒为单位)
BufferFlags flags = 6; // 缓冲区标志
uint32 sequence_number = 7; // 序列号
repeated ChannelInfo channels = 8; // 声道信息
}
message BufferFlags {
bool is_silent = 1; // 是否静音
bool has_discontinuity = 2; // 是否有不连续性
bool is_last = 3; // 是否为最后一个缓冲区
bool needs_processing = 4; // 是否需要处理
bool is_real_time = 5; // 是否为实时数据
}
message ChannelInfo {
int32 channel_index = 1; // 声道索引
ChannelType type = 2; // 声道类型
double peak_level = 3; // 峰值电平
double rms_level = 4; // RMS电平
bool is_clipping = 5; // 是否削波
}
enum ChannelType {
CHANNEL_UNKNOWN = 0;
CHANNEL_MONO = 1; // 单声道
CHANNEL_LEFT = 2; // 左声道
CHANNEL_RIGHT = 3; // 右声道
CHANNEL_CENTER = 4; // 中央声道
CHANNEL_LFE = 5; // 低频声道
CHANNEL_SURROUND_LEFT = 6; // 环绕左声道
CHANNEL_SURROUND_RIGHT = 7; // 环绕右声道
}
// ================================================================================================
// 音频设备信息
// ================================================================================================
message AudioDeviceInfo {
string device_id = 1; // 设备ID
string name = 2; // 设备名称
string driver_name = 3; // 驱动名称
DeviceType type = 4; // 设备类型
DeviceState state = 5; // 设备状态
repeated AudioFormat supported_formats = 6; // 支持的格式
AudioFormat current_format = 7; // 当前格式
DeviceCapabilities capabilities = 8; // 设备能力
PerformanceMetrics metrics = 9; // 性能指标
}
enum DeviceType {
DEVICE_TYPE_UNKNOWN = 0;
DEVICE_TYPE_INPUT = 1; // 输入设备
DEVICE_TYPE_OUTPUT = 2; // 输出设备
DEVICE_TYPE_FULL_DUPLEX = 3; // 全双工设备
DEVICE_TYPE_LOOPBACK = 4; // 回环设备
}
message DeviceCapabilities {
bool supports_exclusive_mode = 1; // 支持独占模式
bool supports_shared_mode = 2; // 支持共享模式
bool supports_hardware_mixing = 3; // 支持硬件混音
bool supports_sample_rate_conversion = 4; // 支持采样率转换
int32 min_buffer_size = 5; // 最小缓冲区大小
int32 max_buffer_size = 6; // 最大缓冲区大小
repeated int32 supported_sample_rates = 7; // 支持的采样率
}
// ================================================================================================
// 音频处理链配置
// ================================================================================================
message ProcessingChainConfig {
string chain_id = 1; // 处理链ID
repeated ProcessingNode nodes = 2; // 处理节点
repeated Connection connections = 3; // 节点连接
map<string, string> global_params = 4; // 全局参数
bool enabled = 5; // 是否启用
}
message ProcessingNode {
string node_id = 1; // 节点ID
string processor_type = 2; // 处理器类型
map<string, ParameterValue> parameters = 3; // 节点参数
bool enabled = 4; // 是否启用
bool bypass = 5; // 是否旁路
NodeType type = 6; // 节点类型
}
enum NodeType {
NODE_UNKNOWN = 0;
NODE_INPUT = 1; // 输入节点
NODE_OUTPUT = 2; // 输出节点
NODE_EFFECT = 3; // 效果节点
NODE_GENERATOR = 4; // 生成器节点
NODE_ANALYZER = 5; // 分析器节点
NODE_MIXER = 6; // 混音器节点
}
message Connection {
string from_node = 1; // 源节点ID
int32 from_pin = 2; // 源节点引脚
string to_node = 3; // 目标节点ID
int32 to_pin = 4; // 目标节点引脚
double gain = 5; // 增益
bool muted = 6; // 是否静音
}
// ================================================================================================
// 音频分析数据
// ================================================================================================
message AudioAnalysisData {
string analysis_id = 1; // 分析ID
AnalysisType type = 2; // 分析类型
Timestamp timestamp = 3; // 时间戳
bytes data = 4; // 分析数据
AnalysisParams parameters = 5; // 分析参数
}
enum AnalysisType {
ANALYSIS_UNKNOWN = 0;
ANALYSIS_SPECTRUM = 1; // 频谱分析
ANALYSIS_WAVEFORM = 2; // 波形分析
ANALYSIS_LEVEL_METER = 3; // 电平表
ANALYSIS_PHASE_METER = 4; // 相位表
ANALYSIS_CORRELATION = 5; // 相关性分析
}
message AnalysisParams {
int32 fft_size = 1; // FFT大小
int32 overlap = 2; // 重叠率
WindowType window_type = 3; // 窗函数类型
double frequency_min = 4; // 最小频率
double frequency_max = 5; // 最大频率
}
enum WindowType {
WINDOW_RECTANGULAR = 0; // 矩形窗
WINDOW_HANNING = 1; // 汉宁窗
WINDOW_HAMMING = 2; // 汉明窗
WINDOW_BLACKMAN = 3; // 布莱克曼窗
WINDOW_KAISER = 4; // 凯泽窗
}
// ================================================================================================
// MIDI消息定义
// ================================================================================================
message MidiMessage {
uint32 timestamp = 1; // 时间戳
bytes data = 2; // MIDI数据
MidiMessageType type = 3; // 消息类型
int32 channel = 4; // MIDI通道
int32 note = 5; // 音符号
int32 velocity = 6; // 力度
int32 controller = 7; // 控制器号
int32 value = 8; // 控制器值
}
enum MidiMessageType {
MIDI_UNKNOWN = 0;
MIDI_NOTE_ON = 1; // 音符开始
MIDI_NOTE_OFF = 2; // 音符结束
MIDI_CONTROL_CHANGE = 3; // 控制器变化
MIDI_PROGRAM_CHANGE = 4; // 程序变化
MIDI_PITCH_BEND = 5; // 弯音
MIDI_AFTERTOUCH = 6; // 触后
MIDI_SYSTEM_EXCLUSIVE = 7; // 系统独占
}

View File

@@ -0,0 +1,161 @@
// ================================================================================================
// Audio Backend - 通用消息协议定义
// ================================================================================================
// 描述: 定义系统中通用的数据类型、枚举和结构
// 用途: 为其他协议文件提供基础类型定义
// ================================================================================================
syntax = "proto3";
package audio_backend.communication.proto;
option cc_enable_arenas = true;
option optimize_for = SPEED;
// ================================================================================================
// 时间戳定义
// ================================================================================================
message Timestamp {
int64 seconds = 1; // 自1970-01-01 00:00:00 UTC以来的秒数
int32 nanos = 2; // 秒内的纳秒数 [0-999,999,999]
}
// ================================================================================================
// 错误信息定义
// ================================================================================================
message ErrorInfo {
int32 code = 1; // 错误码对应ErrorCode枚举
string message = 2; // 错误描述
string details = 3; // 详细信息
string source = 4; // 错误来源(模块名)
Timestamp timestamp = 5; // 错误发生时间
}
// ================================================================================================
// 通信端点定义
// ================================================================================================
message Endpoint {
string id = 1; // 端点唯一标识符
EndpointType type = 2; // 端点类型
string address = 3; // 端点地址
int32 port = 4; // 端口号(网络通信时使用)
map<string, string> metadata = 5; // 端点元数据
}
enum EndpointType {
ENDPOINT_UNKNOWN = 0;
ENDPOINT_AUDIO_ENGINE = 1; // 音频引擎
ENDPOINT_PLUGIN_SANDBOX = 2; // 插件沙盒
ENDPOINT_FRONTEND = 3; // 前端进程
ENDPOINT_REMOTE_CLIENT = 4; // 远程客户端
ENDPOINT_NETWORK_NODE = 5; // 网络节点
}
// ================================================================================================
// 消息优先级定义
// ================================================================================================
enum MessagePriority {
PRIORITY_LOW = 0; // 低优先级(日志、统计等)
PRIORITY_NORMAL = 1; // 普通优先级(一般控制消息)
PRIORITY_HIGH = 2; // 高优先级(重要状态更新)
PRIORITY_CRITICAL = 3; // 关键优先级(错误、紧急停止)
PRIORITY_REALTIME = 4; // 实时优先级(音频处理相关)
}
// ================================================================================================
// 传输通道类型
// ================================================================================================
enum TransportChannel {
CHANNEL_ZMQ_CONTROL = 0; // ZeroMQ控制通道
CHANNEL_SHARED_MEMORY = 1; // 共享内存通道
CHANNEL_NETWORK_TCP = 2; // 网络TCP通道
CHANNEL_NETWORK_UDP = 3; // 网络UDP通道
CHANNEL_LOCAL_IPC = 4; // 本地IPC通道
}
// ================================================================================================
// 音频格式定义
// ================================================================================================
message AudioFormat {
int32 sample_rate = 1; // 采样率 (Hz)
int32 channels = 2; // 声道数
AudioSampleType sample_type = 3; // 采样类型
int32 buffer_size = 4; // 缓冲区大小(样本数)
bool interleaved = 5; // 是否交错格式
}
enum AudioSampleType {
SAMPLE_UNKNOWN = 0;
SAMPLE_INT16 = 1; // 16位整数
SAMPLE_INT24 = 2; // 24位整数
SAMPLE_INT32 = 3; // 32位整数
SAMPLE_FLOAT32 = 4; // 32位浮点
SAMPLE_FLOAT64 = 5; // 64位浮点
}
// ================================================================================================
// 设备状态枚举
// ================================================================================================
enum DeviceState {
DEVICE_UNKNOWN = 0;
DEVICE_DISCONNECTED = 1; // 设备断开
DEVICE_CONNECTED = 2; // 设备连接
DEVICE_ACTIVE = 3; // 设备活跃
DEVICE_ERROR = 4; // 设备错误
DEVICE_SUSPENDED = 5; // 设备挂起
}
// ================================================================================================
// 进程状态枚举
// ================================================================================================
enum ProcessState {
PROCESS_UNKNOWN = 0;
PROCESS_STARTING = 1; // 进程启动中
PROCESS_RUNNING = 2; // 进程运行中
PROCESS_STOPPING = 3; // 进程停止中
PROCESS_STOPPED = 4; // 进程已停止
PROCESS_ERROR = 5; // 进程错误
PROCESS_CRASHED = 6; // 进程崩溃
}
// ================================================================================================
// 版本信息定义
// ================================================================================================
message Version {
int32 major = 1; // 主版本号
int32 minor = 2; // 次版本号
int32 patch = 3; // 补丁版本号
string pre_release = 4; // 预发布标识
string build_metadata = 5; // 构建元数据
}
// ================================================================================================
// 性能统计信息
// ================================================================================================
message PerformanceMetrics {
double cpu_usage = 1; // CPU使用率 (0-100%)
uint64 memory_usage = 2; // 内存使用量 (字节)
double latency_ms = 3; // 延迟 (毫秒)
uint64 throughput_bps = 4; // 吞吐量 (字节/秒)
uint32 buffer_underruns = 5; // 缓冲区下溢次数
uint32 buffer_overruns = 6; // 缓冲区溢出次数
Timestamp last_updated = 7; // 最后更新时间
}
// ================================================================================================
// 网络地址信息
// ================================================================================================
message NetworkAddress {
string host = 1; // 主机名或IP地址
int32 port = 2; // 端口号
AddressType type = 3; // 地址类型
bool is_local = 4; // 是否为本地地址
}
enum AddressType {
ADDRESS_UNKNOWN = 0;
ADDRESS_IPV4 = 1; // IPv4地址
ADDRESS_IPV6 = 2; // IPv6地址
ADDRESS_HOSTNAME = 3; // 主机名
ADDRESS_UNIX_SOCKET = 4; // Unix套接字
}

View File

@@ -0,0 +1,196 @@
// ================================================================================================
// Audio Backend - 控制消息协议定义
// ================================================================================================
// 描述: 定义系统控制消息的类型和结构
// 用途: 进程间控制命令、配置更新、系统管理
// ================================================================================================
syntax = "proto3";
package audio_backend.communication.proto;
import "common.proto";
option cc_enable_arenas = true;
option optimize_for = SPEED;
// ================================================================================================
// 控制消息封装
// ================================================================================================
message ControlMessage {
string message_id = 1; // 消息唯一标识符
Endpoint source = 2; // 消息来源
Endpoint destination = 3; // 消息目的地
MessagePriority priority = 4; // 消息优先级
Timestamp timestamp = 5; // 消息时间戳
oneof payload {
CommandRequest command_request = 10;
CommandResponse command_response = 11;
ConfigUpdate config_update = 12;
ParameterChange parameter_change = 13;
SystemCommand system_command = 14;
}
}
// ================================================================================================
// 命令请求
// ================================================================================================
message CommandRequest {
string request_id = 1; // 请求ID
CommandType command_type = 2; // 命令类型
bytes payload = 3; // 命令载荷
map<string, string> parameters = 4; // 命令参数
int32 timeout_ms = 5; // 超时时间(毫秒)
}
enum CommandType {
CMD_UNKNOWN = 0;
CMD_START = 1; // 启动命令
CMD_STOP = 2; // 停止命令
CMD_PAUSE = 3; // 暂停命令
CMD_RESUME = 4; // 恢复命令
CMD_RESET = 5; // 重置命令
CMD_CONFIGURE = 6; // 配置命令
CMD_QUERY = 7; // 查询命令
CMD_CUSTOM = 100; // 自定义命令
}
// ================================================================================================
// 命令响应
// ================================================================================================
message CommandResponse {
string request_id = 1; // 对应的请求ID
ResponseStatus status = 2; // 响应状态
bytes result = 3; // 响应结果
ErrorInfo error = 4; // 错误信息(如果有)
int32 execution_time_ms = 5; // 执行时间(毫秒)
}
enum ResponseStatus {
STATUS_UNKNOWN = 0;
STATUS_SUCCESS = 1; // 成功
STATUS_PENDING = 2; // 处理中
STATUS_FAILED = 3; // 失败
STATUS_TIMEOUT = 4; // 超时
STATUS_REJECTED = 5; // 被拒绝
}
// ================================================================================================
// 配置更新
// ================================================================================================
message ConfigUpdate {
string config_id = 1; // 配置标识符
ConfigScope scope = 2; // 配置作用域
map<string, string> settings = 3; // 配置设置
bool require_restart = 4; // 是否需要重启
Timestamp effective_time = 5; // 生效时间
}
enum ConfigScope {
SCOPE_GLOBAL = 0; // 全局配置
SCOPE_ENGINE = 1; // 引擎配置
SCOPE_PLUGIN = 2; // 插件配置
SCOPE_DEVICE = 3; // 设备配置
SCOPE_NETWORK = 4; // 网络配置
}
// ================================================================================================
// 参数变更
// ================================================================================================
message ParameterChange {
string parameter_path = 1; // 参数路径(如"plugin.id.param.name"
ParameterValue value = 2; // 参数值
bool automated = 3; // 是否为自动化
string automation_id = 4; // 自动化ID如果有
}
message ParameterValue {
oneof value {
double float_value = 1;
int64 int_value = 2;
bool bool_value = 3;
string string_value = 4;
bytes binary_value = 5;
}
// 元数据
double min_value = 10; // 最小值
double max_value = 11; // 最大值
double default_value = 12; // 默认值
string unit = 13; // 单位
ParameterType type = 14; // 参数类型
}
enum ParameterType {
PARAM_UNKNOWN = 0;
PARAM_FLOAT = 1; // 浮点数参数
PARAM_INT = 2; // 整数参数
PARAM_BOOL = 3; // 布尔参数
PARAM_STRING = 4; // 字符串参数
PARAM_ENUM = 5; // 枚举参数
PARAM_BINARY = 6; // 二进制参数
}
// ================================================================================================
// 系统命令
// ================================================================================================
message SystemCommand {
SystemCommandType type = 1; // 系统命令类型
string target_id = 2; // 目标标识符
map<string, string> arguments = 3; // 命令参数
bool force = 4; // 是否强制执行
}
enum SystemCommandType {
SYS_CMD_UNKNOWN = 0;
SYS_CMD_SHUTDOWN = 1; // 关闭系统
SYS_CMD_RESTART = 2; // 重启系统
SYS_CMD_LOAD_PLUGIN = 3; // 加载插件
SYS_CMD_UNLOAD_PLUGIN = 4; // 卸载插件
SYS_CMD_ENABLE_DEVICE = 5; // 启用设备
SYS_CMD_DISABLE_DEVICE = 6; // 禁用设备
SYS_CMD_CLEAR_CACHE = 7; // 清除缓存
SYS_CMD_SAVE_STATE = 8; // 保存状态
SYS_CMD_LOAD_STATE = 9; // 加载状态
}
// ================================================================================================
// 心跳消息
// ================================================================================================
message HeartbeatMessage {
string sender_id = 1; // 发送者ID
Timestamp timestamp = 2; // 时间戳
ProcessState state = 3; // 进程状态
PerformanceMetrics metrics = 4; // 性能指标
int32 sequence_number = 5; // 序列号
}
// ================================================================================================
// 连接管理消息
// ================================================================================================
message ConnectionMessage {
ConnectionAction action = 1; // 连接操作
Endpoint endpoint = 2; // 端点信息
string session_id = 3; // 会话ID
ConnectionInfo info = 4; // 连接信息
}
enum ConnectionAction {
CONN_UNKNOWN = 0;
CONN_CONNECT = 1; // 连接请求
CONN_ACCEPT = 2; // 接受连接
CONN_REJECT = 3; // 拒绝连接
CONN_DISCONNECT = 4; // 断开连接
CONN_RECONNECT = 5; // 重新连接
CONN_PING = 6; // Ping
CONN_PONG = 7; // Pong
}
message ConnectionInfo {
TransportChannel channel = 1; // 传输通道
map<string, string> properties = 2; // 连接属性
Version protocol_version = 3; // 协议版本
bool encrypted = 4; // 是否加密
string encryption_method = 5; // 加密方法
}

View File

@@ -0,0 +1,299 @@
// ================================================================================================
// Audio Backend - 插件管理协议定义
// ================================================================================================
// 描述: 定义插件系统的管理消息和状态
// 用途: 插件加载、卸载、通信、状态管理
// ================================================================================================
syntax = "proto3";
package audio_backend.communication.proto;
import "common.proto";
import "audio_meta.proto";
option cc_enable_arenas = true;
option optimize_for = SPEED;
// ================================================================================================
// 插件管理消息
// ================================================================================================
message PluginManagementMessage {
string message_id = 1; // 消息ID
Endpoint source = 2; // 消息来源
Endpoint destination = 3; // 消息目的地
Timestamp timestamp = 4; // 时间戳
oneof payload {
PluginLoadRequest load_request = 10;
PluginLoadResponse load_response = 11;
PluginUnloadRequest unload_request = 12;
PluginUnloadResponse unload_response = 13;
PluginStateNotification state_notification = 14;
PluginProcessRequest process_request = 15;
PluginProcessResponse process_response = 16;
PluginParameterUpdate parameter_update = 17;
PluginPresetChange preset_change = 18;
}
}
// ================================================================================================
// 插件加载请求和响应
// ================================================================================================
message PluginLoadRequest {
string plugin_id = 1; // 插件唯一标识符
string plugin_path = 2; // 插件文件路径
PluginFormat format = 3; // 插件格式
map<string, string> init_params = 4; // 初始化参数
SandboxConfig sandbox_config = 5; // 沙盒配置
int32 timeout_ms = 6; // 加载超时时间
}
message PluginLoadResponse {
string plugin_id = 1; // 插件ID
PluginLoadStatus status = 2; // 加载状态
PluginInfo plugin_info = 3; // 插件信息
string sandbox_id = 4; // 沙盒ID
ErrorInfo error = 5; // 错误信息(如果有)
int32 load_time_ms = 6; // 加载时间
}
enum PluginFormat {
FORMAT_UNKNOWN = 0;
FORMAT_VST3 = 1; // VST3插件
FORMAT_AU = 2; // Audio Unit插件
FORMAT_LADSPA = 3; // LADSPA插件
FORMAT_LV2 = 4; // LV2插件
FORMAT_CLAP = 5; // CLAP插件
FORMAT_NATIVE = 6; // 原生插件
}
enum PluginLoadStatus {
LOAD_UNKNOWN = 0;
LOAD_SUCCESS = 1; // 加载成功
LOAD_FAILED = 2; // 加载失败
LOAD_PENDING = 3; // 加载中
LOAD_TIMEOUT = 4; // 加载超时
LOAD_INVALID_FORMAT = 5; // 格式无效
LOAD_MISSING_DEPENDENCIES = 6; // 缺少依赖
}
// ================================================================================================
// 插件卸载请求和响应
// ================================================================================================
message PluginUnloadRequest {
string plugin_id = 1; // 插件ID
bool force = 2; // 强制卸载
bool save_state = 3; // 保存状态
int32 timeout_ms = 4; // 卸载超时时间
}
message PluginUnloadResponse {
string plugin_id = 1; // 插件ID
PluginUnloadStatus status = 2; // 卸载状态
bytes saved_state = 3; // 保存的状态(如果有)
ErrorInfo error = 4; // 错误信息(如果有)
int32 unload_time_ms = 5; // 卸载时间
}
enum PluginUnloadStatus {
UNLOAD_UNKNOWN = 0;
UNLOAD_SUCCESS = 1; // 卸载成功
UNLOAD_FAILED = 2; // 卸载失败
UNLOAD_TIMEOUT = 3; // 卸载超时
UNLOAD_FORCED = 4; // 强制卸载
}
// ================================================================================================
// 插件信息定义
// ================================================================================================
message PluginInfo {
string plugin_id = 1; // 插件ID
string name = 2; // 插件名称
string vendor = 3; // 供应商
Version version = 4; // 版本
string description = 5; // 描述
PluginCategory category = 6; // 插件类别
PluginType type = 7; // 插件类型
repeated AudioFormat supported_formats = 8; // 支持的音频格式
PluginCapabilities capabilities = 9; // 插件能力
repeated PluginParameter parameters = 10; // 插件参数
repeated PluginPreset presets = 11; // 预设
}
enum PluginCategory {
CATEGORY_UNKNOWN = 0;
CATEGORY_EFFECT = 1; // 效果器
CATEGORY_INSTRUMENT = 2; // 乐器
CATEGORY_ANALYZER = 3; // 分析器
CATEGORY_GENERATOR = 4; // 生成器
CATEGORY_UTILITY = 5; // 工具
CATEGORY_MIXER = 6; // 混音器
}
enum PluginType {
TYPE_UNKNOWN = 0;
TYPE_AUDIO_EFFECT = 1; // 音频效果
TYPE_INSTRUMENT = 2; // 乐器
TYPE_MIDI_EFFECT = 3; // MIDI效果
TYPE_ANALYZER = 4; // 分析器
TYPE_GENERATOR = 5; // 生成器
}
message PluginCapabilities {
bool has_gui = 1; // 有GUI
bool supports_midi = 2; // 支持MIDI
bool supports_presets = 3; // 支持预设
bool supports_automation = 4; // 支持自动化
bool is_realtime_safe = 5; // 实时安全
bool supports_bypass = 6; // 支持旁路
int32 max_input_channels = 7; // 最大输入声道数
int32 max_output_channels = 8; // 最大输出声道数
double latency_samples = 9; // 延迟(样本)
}
// ================================================================================================
// 插件参数定义
// ================================================================================================
message PluginParameter {
string parameter_id = 1; // 参数ID
string name = 2; // 参数名称
string label = 3; // 参数标签
ParameterType type = 4; // 参数类型
ParameterValue default_value = 5; // 默认值
ParameterValue min_value = 6; // 最小值
ParameterValue max_value = 7; // 最大值
string unit = 8; // 单位
bool is_automatable = 9; // 可自动化
bool is_read_only = 10; // 只读
repeated string enum_values = 11; // 枚举值(如果适用)
}
// ================================================================================================
// 插件预设定义
// ================================================================================================
message PluginPreset {
string preset_id = 1; // 预设ID
string name = 2; // 预设名称
string description = 3; // 描述
string author = 4; // 作者
Version version = 5; // 版本
map<string, ParameterValue> parameters = 6; // 参数值
bytes binary_data = 7; // 二进制数据(如果有)
map<string, string> metadata = 8; // 元数据
}
// ================================================================================================
// 插件沙盒配置
// ================================================================================================
message SandboxConfig {
bool enabled = 1; // 启用沙盒
SandboxType type = 2; // 沙盒类型
ResourceLimits limits = 3; // 资源限制
SecuritySettings security = 4; // 安全设置
bool crash_recovery = 5; // 崩溃恢复
int32 watchdog_timeout_ms = 6; // 看门狗超时
}
enum SandboxType {
SANDBOX_NONE = 0; // 无沙盒
SANDBOX_PROCESS = 1; // 进程沙盒
SANDBOX_CONTAINER = 2; // 容器沙盒
SANDBOX_VM = 3; // 虚拟机沙盒
}
message ResourceLimits {
uint64 max_memory_bytes = 1; // 最大内存
double max_cpu_percent = 2; // 最大CPU使用率
uint32 max_threads = 3; // 最大线程数
uint32 max_file_handles = 4; // 最大文件句柄数
uint64 max_disk_usage_bytes = 5; // 最大磁盘使用量
}
message SecuritySettings {
bool allow_network_access = 1; // 允许网络访问
bool allow_file_system_access = 2; // 允许文件系统访问
repeated string allowed_paths = 3; // 允许的路径
repeated string blocked_apis = 4; // 阻止的API
bool enable_aslr = 5; // 启用ASLR
bool enable_dep = 6; // 启用DEP
}
// ================================================================================================
// 插件状态通知
// ================================================================================================
message PluginStateNotification {
string plugin_id = 1; // 插件ID
PluginState state = 2; // 插件状态
string message = 3; // 状态消息
PerformanceMetrics metrics = 4; // 性能指标
Timestamp timestamp = 5; // 时间戳
}
enum PluginState {
STATE_UNKNOWN = 0;
STATE_LOADING = 1; // 加载中
STATE_LOADED = 2; // 已加载
STATE_ACTIVE = 3; // 活跃
STATE_INACTIVE = 4; // 非活跃
STATE_PROCESSING = 5; // 处理中
STATE_BYPASSED = 6; // 已旁路
STATE_ERROR = 7; // 错误状态
STATE_CRASHED = 8; // 已崩溃
STATE_UNLOADING = 9; // 卸载中
}
// ================================================================================================
// 插件处理请求和响应
// ================================================================================================
message PluginProcessRequest {
string plugin_id = 1; // 插件ID
string buffer_id = 2; // 缓冲区ID
AudioBufferMetadata metadata = 3; // 音频元数据
repeated MidiMessage midi_events = 4; // MIDI事件
bool bypass = 5; // 旁路处理
}
message PluginProcessResponse {
string plugin_id = 1; // 插件ID
string buffer_id = 2; // 缓冲区ID
ProcessingResult result = 3; // 处理结果
repeated MidiMessage output_midi = 4; // 输出MIDI事件
PerformanceMetrics metrics = 5; // 性能指标
ErrorInfo error = 6; // 错误信息(如果有)
}
enum ProcessingResult {
RESULT_SUCCESS = 0; // 处理成功
RESULT_FAILED = 1; // 处理失败
RESULT_BYPASS = 2; // 旁路处理
RESULT_SILENCE = 3; // 输出静音
RESULT_TIMEOUT = 4; // 处理超时
}
// ================================================================================================
// 插件参数更新
// ================================================================================================
message PluginParameterUpdate {
string plugin_id = 1; // 插件ID
repeated ParameterChange changes = 2; // 参数变更
bool immediate = 3; // 立即生效
string automation_id = 4; // 自动化ID如果有
}
// ================================================================================================
// 插件预设变更
// ================================================================================================
message PluginPresetChange {
string plugin_id = 1; // 插件ID
PresetAction action = 2; // 预设操作
PluginPreset preset = 3; // 预设数据
bool immediate = 4; // 立即生效
}
enum PresetAction {
PRESET_LOAD = 0; // 加载预设
PRESET_SAVE = 1; // 保存预设
PRESET_DELETE = 2; // 删除预设
PRESET_RENAME = 3; // 重命名预设
}

View File

@@ -0,0 +1,348 @@
// ================================================================================================
// Audio Backend - 状态同步协议定义
// ================================================================================================
// 描述: 定义系统状态同步相关的消息和数据结构
// 用途: 进程状态同步、系统监控、诊断和健康检查
// ================================================================================================
syntax = "proto3";
package audio_backend.communication.proto;
import "common.proto";
import "audio_meta.proto";
option cc_enable_arenas = true;
option optimize_for = SPEED;
// ================================================================================================
// 状态同步消息
// ================================================================================================
message StatusMessage {
string message_id = 1; // 消息ID
Endpoint source = 2; // 消息来源
Timestamp timestamp = 3; // 时间戳
oneof payload {
SystemStatus system_status = 10;
ProcessStatus process_status = 11;
EngineStatus engine_status = 12;
PluginHostStatus plugin_host_status = 13;
DeviceStatus device_status = 14;
NetworkStatus network_status = 15;
HealthCheckRequest health_check_request = 16;
HealthCheckResponse health_check_response = 17;
DiagnosticRequest diagnostic_request = 18;
DiagnosticResponse diagnostic_response = 19;
}
}
// ================================================================================================
// 系统状态
// ================================================================================================
message SystemStatus {
string system_id = 1; // 系统ID
SystemState state = 2; // 系统状态
Version system_version = 3; // 系统版本
SystemResources resources = 4; // 系统资源
repeated ProcessStatus processes = 5; // 进程状态列表
repeated ErrorInfo recent_errors = 6; // 最近错误
Timestamp startup_time = 7; // 启动时间
double uptime_seconds = 8; // 运行时间
}
enum SystemState {
SYS_STATE_UNKNOWN = 0;
SYS_STATE_STARTING = 1; // 启动中
SYS_STATE_RUNNING = 2; // 运行中
SYS_STATE_DEGRADED = 3; // 功能降级
SYS_STATE_STOPPING = 4; // 停止中
SYS_STATE_ERROR = 5; // 错误状态
SYS_STATE_MAINTENANCE = 6; // 维护模式
}
message SystemResources {
double system_cpu_usage = 1; // 系统CPU使用率
double process_cpu_usage = 2; // 进程CPU使用率
uint64 physical_memory_bytes = 3; // 物理内存总量
uint64 memory_usage_bytes = 4; // 内存使用量
uint64 swap_usage_bytes = 5; // 交换空间使用量
uint64 disk_total_bytes = 6; // 磁盘总量
uint64 disk_used_bytes = 7; // 磁盘使用量
uint64 network_rx_bytes = 8; // 网络接收字节数
uint64 network_tx_bytes = 9; // 网络发送字节数
}
// ================================================================================================
// 进程状态
// ================================================================================================
message ProcessStatus {
string process_id = 1; // 进程ID
string process_name = 2; // 进程名称
ProcessType type = 3; // 进程类型
ProcessState state = 4; // 进程状态
PerformanceMetrics metrics = 5; // 性能指标
int32 pid = 6; // 系统进程ID
int32 restart_count = 7; // 重启计数
ErrorInfo last_error = 8; // 最近一次错误
Timestamp start_time = 9; // 启动时间
}
enum ProcessType {
PROCESS_TYPE_UNKNOWN = 0;
PROCESS_TYPE_ENGINE = 1; // 音频引擎进程
PROCESS_TYPE_PLUGIN_HOST = 2; // 插件沙盒进程
PROCESS_TYPE_FRONTEND = 3; // 前端进程
PROCESS_TYPE_NETWORK = 4; // 网络服务进程
PROCESS_TYPE_UTILITY = 5; // 工具进程
}
// ================================================================================================
// 音频引擎状态
// ================================================================================================
message EngineStatus {
string engine_id = 1; // 引擎ID
EngineState state = 2; // 引擎状态
AudioFormat current_format = 3; // 当前音频格式
repeated StreamStatus streams = 4; // 音频流状态
PerformanceMetrics metrics = 5; // 性能指标
repeated ProcessingNodeStatus nodes = 6; // 处理节点状态
double dsp_load = 7; // DSP负载
double latency_ms = 8; // 延迟(毫秒)
double xrun_count = 9; // 缓冲区溢出/欠载数
}
enum EngineState {
ENGINE_UNKNOWN = 0;
ENGINE_STOPPED = 1; // 停止
ENGINE_STARTING = 2; // 启动中
ENGINE_RUNNING = 3; // 运行中
ENGINE_STOPPING = 4; // 停止中
ENGINE_ERROR = 5; // 错误状态
}
message StreamStatus {
string stream_id = 1; // 流ID
StreamState state = 2; // 流状态
AudioBufferMetadata buffer_info = 3; // 缓冲区信息
double current_position_seconds = 4; // 当前位置(秒)
double peak_level = 5; // 峰值电平
double rms_level = 6; // RMS电平
bool is_clipping = 7; // 是否削波
}
message ProcessingNodeStatus {
string node_id = 1; // 节点ID
string node_type = 2; // 节点类型
bool enabled = 3; // 是否启用
bool bypassed = 4; // 是否旁路
double processing_load = 5; // 处理负载
double processing_time_ms = 6; // 处理时间(毫秒)
ErrorInfo error = 7; // 错误信息(如果有)
}
// ================================================================================================
// 插件宿主状态
// ================================================================================================
message PluginHostStatus {
string host_id = 1; // 宿主ID
ProcessState state = 2; // 进程状态
repeated PluginInstanceStatus plugins = 3; // 插件实例状态
SandboxStatus sandbox = 4; // 沙盒状态
PerformanceMetrics metrics = 5; // 性能指标
}
message PluginInstanceStatus {
string plugin_id = 1; // 插件ID
string plugin_name = 2; // 插件名称
PluginState state = 3; // 插件状态
double cpu_usage = 4; // CPU使用率
uint64 memory_usage = 5; // 内存使用量
double processing_time_ms = 6; // 处理时间(毫秒)
int32 input_count = 7; // 输入数量
int32 output_count = 8; // 输出数量
double latency_samples = 9; // 延迟(样本)
ErrorInfo last_error = 10; // 最近一次错误
}
message SandboxStatus {
bool enabled = 1; // 是否启用
SandboxType type = 2; // 沙盒类型
SandboxState state = 3; // 沙盒状态
ResourceUsage resource_usage = 4; // 资源使用情况
repeated string violations = 5; // 违规操作
ErrorInfo last_error = 6; // 最近一次错误
}
enum SandboxState {
SANDBOX_UNKNOWN = 0;
SANDBOX_ACTIVE = 1; // 活跃
SANDBOX_INACTIVE = 2; // 非活跃
SANDBOX_ERROR = 3; // 错误状态
SANDBOX_COMPROMISED = 4; // 已被破坏
}
message ResourceUsage {
double cpu_percent = 1; // CPU使用率百分比
uint64 memory_bytes = 2; // 内存使用量(字节)
uint32 thread_count = 3; // 线程数
uint32 file_handle_count = 4; // 文件句柄数
uint64 disk_usage_bytes = 5; // 磁盘使用量(字节)
}
// ================================================================================================
// 设备状态
// ================================================================================================
message DeviceStatus {
string device_id = 1; // 设备ID
string device_name = 2; // 设备名称
DeviceType type = 3; // 设备类型
DeviceState state = 4; // 设备状态
AudioFormat current_format = 5; // 当前格式
double buffer_health = 6; // 缓冲区健康度0-1
int32 xrun_count = 7; // 溢出/欠载计数
double latency_ms = 8; // 延迟(毫秒)
ErrorInfo last_error = 9; // 最近一次错误
}
// ================================================================================================
// 网络状态
// ================================================================================================
message NetworkStatus {
string network_id = 1; // 网络ID
NetworkState state = 2; // 网络状态
repeated ConnectionStatus connections = 3; // 连接状态
int32 active_peers = 4; // 活跃对等点数量
NetworkMetrics metrics = 5; // 网络指标
}
enum NetworkState {
NET_STATE_UNKNOWN = 0;
NET_STATE_DISCONNECTED = 1; // 断开连接
NET_STATE_CONNECTING = 2; // 连接中
NET_STATE_CONNECTED = 3; // 已连接
NET_STATE_ERROR = 4; // 错误状态
}
message ConnectionStatus {
string connection_id = 1; // 连接ID
Endpoint remote_endpoint = 2; // 远程端点
ConnectionState state = 3; // 连接状态
double latency_ms = 4; // 延迟(毫秒)
double packet_loss = 5; // 丢包率0-1
uint64 bytes_sent = 6; // 已发送字节数
uint64 bytes_received = 7; // 已接收字节数
int32 reconnect_count = 8; // 重连次数
}
enum ConnectionState {
CONN_STATE_UNKNOWN = 0;
CONN_STATE_DISCONNECTED = 1; // 断开连接
CONN_STATE_CONNECTING = 2; // 连接中
CONN_STATE_CONNECTED = 3; // 已连接
CONN_STATE_RECONNECTING = 4; // 重连中
CONN_STATE_ERROR = 5; // 错误状态
}
message NetworkMetrics {
double download_bandwidth_bps = 1; // 下载带宽bps
double upload_bandwidth_bps = 2; // 上传带宽bps
double packet_loss = 3; // 丢包率0-1
double average_latency_ms = 4; // 平均延迟(毫秒)
double jitter_ms = 5; // 抖动(毫秒)
uint64 total_bytes_sent = 6; // 总发送字节数
uint64 total_bytes_received = 7; // 总接收字节数
uint32 packet_errors = 8; // 包错误数
}
// ================================================================================================
// 健康检查
// ================================================================================================
message HealthCheckRequest {
string check_id = 1; // 检查ID
HealthCheckType type = 2; // 检查类型
string target_id = 3; // 目标ID
int32 timeout_ms = 4; // 超时时间(毫秒)
}
enum HealthCheckType {
CHECK_UNKNOWN = 0;
CHECK_PING = 1; // Ping检查
CHECK_DEEP = 2; // 深度检查
CHECK_RESOURCE = 3; // 资源检查
CHECK_CONNECTIVITY = 4; // 连接性检查
}
message HealthCheckResponse {
string check_id = 1; // 检查ID
HealthStatus status = 2; // 健康状态
string message = 3; // 状态消息
map<string, string> details = 4; // 详细信息
int32 response_time_ms = 5; // 响应时间(毫秒)
}
enum HealthStatus {
HEALTH_UNKNOWN = 0;
HEALTH_OK = 1; // 正常
HEALTH_WARNING = 2; // 警告
HEALTH_ERROR = 3; // 错误
HEALTH_CRITICAL = 4; // 严重错误
HEALTH_TIMEOUT = 5; // 超时
}
// ================================================================================================
// 诊断请求和响应
// ================================================================================================
message DiagnosticRequest {
string request_id = 1; // 请求ID
DiagnosticType type = 2; // 诊断类型
string target = 3; // 目标
map<string, string> parameters = 4; // 诊断参数
int32 timeout_ms = 5; // 超时时间(毫秒)
}
enum DiagnosticType {
DIAG_UNKNOWN = 0;
DIAG_SYSTEM = 1; // 系统诊断
DIAG_PROCESS = 2; // 进程诊断
DIAG_AUDIO = 3; // 音频诊断
DIAG_PLUGIN = 4; // 插件诊断
DIAG_NETWORK = 5; // 网络诊断
DIAG_DEVICE = 6; // 设备诊断
}
message DiagnosticResponse {
string request_id = 1; // 请求ID
DiagnosticResult result = 2; // 诊断结果
repeated DiagnosticFinding findings = 3; // 发现
string summary = 4; // 摘要
bytes raw_data = 5; // 原始数据
int32 execution_time_ms = 6; // 执行时间(毫秒)
}
enum DiagnosticResult {
RESULT_UNKNOWN = 0;
RESULT_OK = 1; // 正常
RESULT_WARNING = 2; // 警告
RESULT_ERROR = 3; // 错误
RESULT_CRITICAL = 4; // 严重错误
RESULT_TIMEOUT = 5; // 超时
}
message DiagnosticFinding {
string id = 1; // 发现ID
SeverityLevel severity = 2; // 严重程度
string title = 3; // 标题
string description = 4; // 描述
string location = 5; // 位置
string recommendation = 6; // 建议
map<string, string> details = 7; // 详细信息
}
enum SeverityLevel {
SEVERITY_INFO = 0; // 信息
SEVERITY_LOW = 1; // 低
SEVERITY_MEDIUM = 2; // 中
SEVERITY_HIGH = 3; // 高
SEVERITY_CRITICAL = 4; // 严重
}

117
src/engine/CMakeLists.txt Normal file
View File

@@ -0,0 +1,117 @@
# ================================================================================================
# Audio Backend - 音频引擎核心模块
# ================================================================================================
# 描述: 音频处理引擎核心组件,包括音频流管理、混音、处理链
# 功能: 音频缓冲区管理、处理图调度、混音引擎
# 依赖: Common, Communication, SIMD
# ================================================================================================
# ================================================================================================
# 自动收集源文件和头文件
# ================================================================================================
set(MODULE_SOURCES "")
retrieve_files(${CMAKE_CURRENT_SOURCE_DIR} MODULE_SOURCES)
# 如果当前没有源文件,创建一个空目标占位
if(NOT MODULE_SOURCES)
message(STATUS "Engine模块: 当前无源文件,创建接口库占位")
add_library(audio_backend_engine INTERFACE)
add_library(AudioBackend::Engine ALIAS audio_backend_engine)
# 设置接口包含路径
target_include_directories(audio_backend_engine INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}
)
# 设置接口依赖
target_link_libraries(audio_backend_engine INTERFACE
AudioBackend::Common
AudioBackend::Communication
AudioBackend::SIMD
)
return()
endif()
# ================================================================================================
# 库目标定义
# ================================================================================================
add_library(audio_backend_engine STATIC ${MODULE_SOURCES})
# 设置别名
add_library(AudioBackend::Engine ALIAS audio_backend_engine)
# ================================================================================================
# 目标属性配置
# ================================================================================================
target_include_directories(audio_backend_engine
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)
# ================================================================================================
# 依赖关系配置
# ================================================================================================
target_link_libraries(audio_backend_engine
PUBLIC
${audio_backend_project_options}
AudioBackend::Common
AudioBackend::Communication
PRIVATE
AudioBackend::SIMD
# 音频I/O库
portaudio::portaudio
sndfile::sndfile
${PLATFORM_LIBS}
)
# 条件性依赖
if(TARGET rtmidi::rtmidi)
target_link_libraries(audio_backend_engine PRIVATE rtmidi::rtmidi)
endif()
if(TARGET libsamplerate::libsamplerate)
target_link_libraries(audio_backend_engine PRIVATE libsamplerate::libsamplerate)
endif()
# ================================================================================================
# 音频引擎特定编译选项
# ================================================================================================
# 高优先级线程设置
if(WIN32)
target_compile_definitions(audio_backend_engine PRIVATE WIN32_LEAN_AND_MEAN)
elseif(UNIX)
# UNIX平台需要链接实时线程支持
find_library(REALTIME_LIB rt)
if(REALTIME_LIB)
target_link_libraries(audio_backend_engine PRIVATE ${REALTIME_LIB})
endif()
endif()
# ================================================================================================
# 目标编译定义
# ================================================================================================
target_compile_definitions(audio_backend_engine
PRIVATE
AUDIO_BACKEND_ENGINE_EXPORTS
PUBLIC
# 公共宏定义
)
# ================================================================================================
# 操作系统平台定义
# ================================================================================================
add_os_definitions(audio_backend_engine)
# ================================================================================================
# 安装规则
# ================================================================================================
install(TARGETS audio_backend_engine
EXPORT AudioBackendTargets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
message(STATUS "Engine模块: 已配置 ${MODULE_SOURCES}个文件")

290
src/engine/audio_buffer.cpp Normal file
View File

@@ -0,0 +1,290 @@
// ================================================================================================
// Audio Backend - 音频缓冲区管理实现
// ================================================================================================
#include "audio_buffer.h"
#include "audio_processing.h"
#include <cstring>
#include <algorithm>
#include <stdexcept>
namespace audio_backend::engine {
// ================================================================================================
// 音频格式名称
// ================================================================================================
const char* get_format_name(AudioFormat format) {
switch (format) {
case AudioFormat::INT16: return "INT16";
case AudioFormat::INT24: return "INT24";
case AudioFormat::INT32: return "INT32";
case AudioFormat::FLOAT32: return "FLOAT32";
case AudioFormat::FLOAT64: return "FLOAT64";
default: return "UNKNOWN";
}
}
// ================================================================================================
// AudioBuffer实现
// ================================================================================================
AudioBuffer::AudioBuffer(const AudioConfig& config, bool interleaved)
: config_(config), interleaved_(interleaved) {
validate_config();
allocate(config, interleaved);
}
AudioBuffer::AudioBuffer(uint32_t frames,
uint16_t channels,
AudioFormat format,
bool interleaved)
: interleaved_(interleaved) {
config_.frames_per_buffer = frames;
config_.channels = channels;
config_.format = format;
validate_config();
allocate(config_, interleaved);
}
AudioBuffer::AudioBuffer(AudioBuffer&& other) noexcept
: config_(other.config_),
interleaved_(other.interleaved_),
channel_stride_(other.channel_stride_),
data_(std::move(other.data_)) {
other.config_ = AudioConfig{};
other.channel_stride_ = 0;
}
AudioBuffer& AudioBuffer::operator=(AudioBuffer&& other) noexcept {
if (this != &other) {
config_ = other.config_;
interleaved_ = other.interleaved_;
channel_stride_ = other.channel_stride_;
data_ = std::move(other.data_);
other.config_ = AudioConfig{};
other.channel_stride_ = 0;
}
return *this;
}
AudioBuffer AudioBuffer::clone() const {
AudioBuffer copy;
copy.config_ = config_;
copy.interleaved_ = interleaved_;
copy.channel_stride_ = channel_stride_;
copy.data_.allocate(data_.size());
std::memcpy(copy.data_.data(), data_.data(), data_.size());
return copy;
}
void AudioBuffer::allocate(const AudioConfig& config, bool interleaved) {
config_ = config;
interleaved_ = interleaved;
validate_config();
size_t buffer_size = calculate_buffer_size();
data_.allocate(buffer_size);
if (!interleaved_) {
channel_stride_ = calculate_channel_stride();
}
clear();
}
void AudioBuffer::allocate(uint32_t frames,
uint16_t channels,
AudioFormat format,
bool interleaved) {
AudioConfig config;
config.frames_per_buffer = frames;
config.channels = channels;
config.format = format;
allocate(config, interleaved);
}
void AudioBuffer::release() {
data_.deallocate();
config_ = AudioConfig{};
channel_stride_ = 0;
}
void AudioBuffer::clear() {
if (!data_.empty()) {
std::memset(data_.data(), 0, data_.size());
}
}
void AudioBuffer::copy_to(AudioBuffer& dest) const {
if (dest.config_ != config_ || dest.interleaved_ != interleaved_) {
dest.allocate(config_, interleaved_);
}
std::memcpy(dest.data_.data(), data_.data(), data_.size());
}
void AudioBuffer::copy_from(const AudioBuffer& src) {
src.copy_to(*this);
}
void AudioBuffer::apply_gain(float gain) {
if (format() != AudioFormat::FLOAT32) {
throw common::AudioException(
common::ErrorCode::AUDIO_FORMAT_ERROR,
"apply_gain only supports FLOAT32 format");
}
float* data_ptr = reinterpret_cast<float*>(data_.data());
size_t sample_count = config_.frames_per_buffer * config_.channels;
// 使用SIMD优化的增益应用
simd::apply_gain_f32(data_ptr, gain, data_ptr, sample_count);
}
bool AudioBuffer::is_aligned() const {
return data_.is_properly_aligned();
}
void AudioBuffer::validate_config() const {
if (!config_.is_valid()) {
throw common::AudioException(
common::ErrorCode::INVALID_ARGUMENT,
"Invalid audio configuration");
}
}
size_t AudioBuffer::calculate_buffer_size() const {
return config_.get_buffer_size_bytes();
}
size_t AudioBuffer::calculate_channel_stride() const {
return config_.frames_per_buffer * get_format_byte_size(config_.format);
}
AudioBuffer AudioBuffer::to_interleaved() const {
if (interleaved_) {
return clone();
}
AudioBuffer result(config_, true);
// 转换非交错到交错格式
size_t format_size = get_format_byte_size(config_.format);
for (uint32_t frame = 0; frame < config_.frames_per_buffer; ++frame) {
for (uint16_t channel = 0; channel < config_.channels; ++channel) {
const uint8_t* src = data_.data() + channel * channel_stride_ + frame * format_size;
uint8_t* dest = result.data_.data() + (frame * config_.channels + channel) * format_size;
std::memcpy(dest, src, format_size);
}
}
return result;
}
AudioBuffer AudioBuffer::to_non_interleaved() const {
if (!interleaved_) {
return clone();
}
AudioBuffer result(config_, false);
// 转换交错到非交错格式
size_t format_size = get_format_byte_size(config_.format);
for (uint32_t frame = 0; frame < config_.frames_per_buffer; ++frame) {
for (uint16_t channel = 0; channel < config_.channels; ++channel) {
const uint8_t* src = data_.data() + (frame * config_.channels + channel) * format_size;
uint8_t* dest = result.data_.data() + channel * result.channel_stride_ + frame * format_size;
std::memcpy(dest, src, format_size);
}
}
return result;
}
AudioBuffer AudioBuffer::convert_format(AudioFormat new_format) const {
if (new_format == config_.format) {
return clone();
}
// 目前只实现INT16 <-> FLOAT32的转换
if ((config_.format == AudioFormat::INT16 && new_format == AudioFormat::FLOAT32) ||
(config_.format == AudioFormat::FLOAT32 && new_format == AudioFormat::INT16)) {
AudioConfig new_config = config_;
new_config.format = new_format;
AudioBuffer result(new_config, interleaved_);
size_t sample_count = config_.frames_per_buffer * config_.channels;
if (config_.format == AudioFormat::INT16 && new_format == AudioFormat::FLOAT32) {
const int16_t* src = reinterpret_cast<const int16_t*>(data_.data());
float* dest = reinterpret_cast<float*>(result.data_.data());
simd::convert_i16_to_f32(src, dest, sample_count);
} else {
const float* src = reinterpret_cast<const float*>(data_.data());
int16_t* dest = reinterpret_cast<int16_t*>(result.data_.data());
simd::convert_f32_to_i16(src, dest, sample_count);
}
return result;
}
throw common::AudioException(
common::ErrorCode::NOT_IMPLEMENTED,
"Format conversion not implemented for this format pair");
}
AudioBuffer AudioBuffer::resample(uint32_t new_sample_rate) const {
if (new_sample_rate == config_.sample_rate) {
return clone();
}
// 简单的线性插值重采样(实际应用中应使用更高质量的算法)
double ratio = static_cast<double>(new_sample_rate) / config_.sample_rate;
uint32_t new_frames = static_cast<uint32_t>(config_.frames_per_buffer * ratio);
AudioConfig new_config = config_;
new_config.sample_rate = new_sample_rate;
new_config.frames_per_buffer = new_frames;
AudioBuffer result(new_config, interleaved_);
// TODO: 实现高质量的重采样算法
// 这里仅作为占位符
return result;
}
void AudioBuffer::mix_from(const AudioBuffer& src, float gain) {
if (src.config_ != config_ || src.interleaved_ != interleaved_) {
throw common::AudioException(
common::ErrorCode::INVALID_ARGUMENT,
"Buffer configurations must match for mixing");
}
if (format() != AudioFormat::FLOAT32 || src.format() != AudioFormat::FLOAT32) {
throw common::AudioException(
common::ErrorCode::AUDIO_FORMAT_ERROR,
"mix_from only supports FLOAT32 format");
}
float* dest_data = reinterpret_cast<float*>(data_.data());
const float* src_data = reinterpret_cast<const float*>(src.data_.data());
size_t sample_count = config_.frames_per_buffer * config_.channels;
// 使用SIMD优化的混音
if (gain == 1.0f) {
simd::mix_audio_f32(dest_data, src_data, dest_data, sample_count);
} else {
// 先应用增益再混音
simd::AlignedBuffer<float, simd::ALIGNMENT_AVX> temp;
temp.allocate(sample_count);
simd::apply_gain_f32(src_data, gain, temp.data(), sample_count);
simd::mix_audio_f32(dest_data, temp.data(), dest_data, sample_count);
}
}
} // namespace audio_backend::engine

346
src/engine/audio_buffer.h Normal file
View File

@@ -0,0 +1,346 @@
// ================================================================================================
// Audio Backend - 音频缓冲区管理
// ================================================================================================
// 描述: 高性能音频缓冲区管理,支持多种格式和声道配置
// 功能: SIMD对齐、零拷贝、线程安全
// ================================================================================================
#pragma once
#include "aligned_allocator.h"
#include "error.h"
#include <cstdint>
#include <memory>
#include <vector>
#include <atomic>
#include <mutex>
namespace audio_backend::engine {
// ================================================================================================
// 音频格式定义
// ================================================================================================
enum class AudioFormat {
UNKNOWN = 0,
INT16, // 16位有符号整数 [-32768, 32767]
INT24, // 24位有符号整数包在int32中[-8388608, 8388607]
INT32, // 32位有符号整数
FLOAT32, // 32位浮点数 [-1.0, 1.0]
FLOAT64 // 64位浮点数 [-1.0, 1.0]
};
// 获取音频格式的字节大小
inline size_t get_format_byte_size(AudioFormat format) {
switch (format) {
case AudioFormat::INT16: return 2;
case AudioFormat::INT24: return 3;
case AudioFormat::INT32: return 4;
case AudioFormat::FLOAT32: return 4;
case AudioFormat::FLOAT64: return 8;
default: return 0;
}
}
// 获取音频格式名称
const char* get_format_name(AudioFormat format);
// ================================================================================================
// 音频配置结构
// ================================================================================================
struct AudioConfig {
uint32_t sample_rate = 48000; // 采样率Hz
uint16_t channels = 2; // 声道数
AudioFormat format = AudioFormat::FLOAT32; // 音频格式
uint32_t frames_per_buffer = 512; // 每个缓冲区的帧数
// 验证配置有效性
bool is_valid() const {
return sample_rate > 0 &&
sample_rate <= 192000 &&
channels > 0 &&
channels <= 32 &&
format != AudioFormat::UNKNOWN &&
frames_per_buffer > 0 &&
frames_per_buffer <= 8192;
}
// 计算缓冲区大小(字节)
size_t get_buffer_size_bytes() const {
return frames_per_buffer * channels * get_format_byte_size(format);
}
// 计算缓冲区大小(样本数)
size_t get_buffer_size_samples() const {
return frames_per_buffer * channels;
}
// 计算延迟(毫秒)
double get_latency_ms() const {
return (static_cast<double>(frames_per_buffer) / sample_rate) * 1000.0;
}
// 比较操作符
bool operator==(const AudioConfig& other) const {
return sample_rate == other.sample_rate &&
channels == other.channels &&
format == other.format &&
frames_per_buffer == other.frames_per_buffer;
}
bool operator!=(const AudioConfig& other) const {
return !(*this == other);
}
};
// ================================================================================================
// 音频缓冲区类(支持交错和非交错格式)
// ================================================================================================
class AudioBuffer {
public:
// 构造函数
AudioBuffer() = default;
explicit AudioBuffer(const AudioConfig& config, bool interleaved = false);
AudioBuffer(uint32_t frames,
uint16_t channels,
AudioFormat format,
bool interleaved = false);
// 移动构造和赋值
AudioBuffer(AudioBuffer&& other) noexcept;
AudioBuffer& operator=(AudioBuffer&& other) noexcept;
// 禁止拷贝使用clone方法显式拷贝
AudioBuffer(const AudioBuffer&) = delete;
AudioBuffer& operator=(const AudioBuffer&) = delete;
~AudioBuffer() = default;
// 显式拷贝
AudioBuffer clone() const;
// 重新分配缓冲区
void allocate(const AudioConfig& config, bool interleaved = false);
void allocate(uint32_t frames,
uint16_t channels,
AudioFormat format,
bool interleaved = false);
// 释放缓冲区
void release();
// 清空缓冲区(填充零)
void clear();
// 获取配置
const AudioConfig& config() const { return config_; }
// 访问器
uint32_t frames() const { return config_.frames_per_buffer; }
uint16_t channels() const { return config_.channels; }
AudioFormat format() const { return config_.format; }
uint32_t sample_rate() const { return config_.sample_rate; }
bool is_interleaved() const { return interleaved_; }
// 数据访问(非交错格式)
template<typename T>
T* channel_data(uint16_t channel) {
if (interleaved_) {
throw common::AudioException(
common::ErrorCode::INVALID_OPERATION,
"Cannot access channel data in interleaved buffer");
}
if (channel >= config_.channels) {
throw common::AudioException(
common::ErrorCode::INVALID_ARGUMENT,
"Channel index out of range");
}
return reinterpret_cast<T*>(data_.data() + channel * channel_stride_);
}
template<typename T>
const T* channel_data(uint16_t channel) const {
return const_cast<AudioBuffer*>(this)->channel_data<T>(channel);
}
// 数据访问(交错格式)
template<typename T>
T* interleaved_data() {
if (!interleaved_) {
throw common::AudioException(
common::ErrorCode::INVALID_OPERATION,
"Cannot access interleaved data in non-interleaved buffer");
}
return reinterpret_cast<T*>(data_.data());
}
template<typename T>
const T* interleaved_data() const {
return const_cast<AudioBuffer*>(this)->interleaved_data<T>();
}
// 原始数据访问
uint8_t* data() { return data_.data(); }
const uint8_t* data() const { return data_.data(); }
size_t size_bytes() const { return data_.size(); }
bool empty() const { return data_.empty(); }
// 转换为交错/非交错格式
AudioBuffer to_interleaved() const;
AudioBuffer to_non_interleaved() const;
// 格式转换
AudioBuffer convert_format(AudioFormat new_format) const;
// 重采样(简单的线性插值,用于格式转换)
AudioBuffer resample(uint32_t new_sample_rate) const;
// 复制数据到另一个缓冲区
void copy_to(AudioBuffer& dest) const;
// 从另一个缓冲区复制数据
void copy_from(const AudioBuffer& src);
// 混音(加法混合)
void mix_from(const AudioBuffer& src, float gain = 1.0f);
// 应用增益
void apply_gain(float gain);
// 检查缓冲区是否正确对齐
bool is_aligned() const;
private:
AudioConfig config_;
bool interleaved_ = false;
size_t channel_stride_ = 0; // 非交错格式中每个声道的字节偏移
simd::AlignedBuffer<uint8_t, simd::ALIGNMENT_AVX> data_;
// 辅助函数
void validate_config() const;
size_t calculate_buffer_size() const;
size_t calculate_channel_stride() const;
};
// ================================================================================================
// 环形缓冲区(用于实时音频流)
// ================================================================================================
template<typename T>
class RingBuffer {
public:
explicit RingBuffer(size_t capacity = 0)
: capacity_(capacity),
read_pos_(0),
write_pos_(0),
available_(0) {
if (capacity > 0) {
buffer_.allocate(capacity);
}
}
// 重新分配容量
void resize(size_t new_capacity) {
std::lock_guard<std::mutex> lock(mutex_);
capacity_ = new_capacity;
buffer_.allocate(new_capacity);
read_pos_ = 0;
write_pos_ = 0;
available_ = 0;
}
// 写入数据
size_t write(const T* data, size_t count) {
std::lock_guard<std::mutex> lock(mutex_);
size_t space = capacity_ - available_.load(std::memory_order_acquire);
size_t to_write = std::min(count, space);
if (to_write == 0) return 0;
size_t write_pos = write_pos_.load(std::memory_order_relaxed);
// 分两部分写入(如果需要环绕)
size_t first_part = std::min(to_write, capacity_ - write_pos);
std::memcpy(buffer_.data() + write_pos, data, first_part * sizeof(T));
if (to_write > first_part) {
size_t second_part = to_write - first_part;
std::memcpy(buffer_.data(), data + first_part, second_part * sizeof(T));
}
write_pos_.store((write_pos + to_write) % capacity_, std::memory_order_release);
available_.fetch_add(to_write, std::memory_order_acq_rel);
return to_write;
}
// 读取数据
size_t read(T* data, size_t count) {
std::lock_guard<std::mutex> lock(mutex_);
size_t avail = available_.load(std::memory_order_acquire);
size_t to_read = std::min(count, avail);
if (to_read == 0) return 0;
size_t read_pos = read_pos_.load(std::memory_order_relaxed);
// 分两部分读取(如果需要环绕)
size_t first_part = std::min(to_read, capacity_ - read_pos);
std::memcpy(data, buffer_.data() + read_pos, first_part * sizeof(T));
if (to_read > first_part) {
size_t second_part = to_read - first_part;
std::memcpy(data + first_part, buffer_.data(), second_part * sizeof(T));
}
read_pos_.store((read_pos + to_read) % capacity_, std::memory_order_release);
available_.fetch_sub(to_read, std::memory_order_acq_rel);
return to_read;
}
// 清空缓冲区
void clear() {
std::lock_guard<std::mutex> lock(mutex_);
read_pos_.store(0, std::memory_order_relaxed);
write_pos_.store(0, std::memory_order_relaxed);
available_.store(0, std::memory_order_relaxed);
}
// 获取可用数据量
size_t available() const {
return available_.load(std::memory_order_acquire);
}
// 获取可写空间
size_t space() const {
return capacity_ - available_.load(std::memory_order_acquire);
}
// 获取容量
size_t capacity() const { return capacity_; }
// 检查是否为空
bool empty() const {
return available_.load(std::memory_order_acquire) == 0;
}
// 检查是否已满
bool full() const {
return available_.load(std::memory_order_acquire) == capacity_;
}
private:
size_t capacity_;
std::atomic<size_t> read_pos_;
std::atomic<size_t> write_pos_;
std::atomic<size_t> available_;
simd::AlignedBuffer<T, simd::ALIGNMENT_AVX> buffer_;
mutable std::mutex mutex_;
};
} // namespace audio_backend::engine

106
src/frontend/CMakeLists.txt Normal file
View File

@@ -0,0 +1,106 @@
# ================================================================================================
# Audio Backend - 前端进程模块
# ================================================================================================
# 描述: 用户界面和控制进程,负责与音频引擎核心的交互
# 功能: 硬件抽象层、用户界面集成、控制命令
# 依赖: Common, Communication
# ================================================================================================
# ================================================================================================
# 自动收集源文件和头文件
# ================================================================================================
set(MODULE_SOURCES "")
retrieve_files(${CMAKE_CURRENT_SOURCE_DIR} MODULE_SOURCES)
# 如果当前没有源文件,创建一个空目标占位
if(NOT MODULE_SOURCES)
message(STATUS "Frontend模块: 当前无源文件,创建接口库占位")
add_library(audio_backend_frontend INTERFACE)
add_library(AudioBackend::Frontend ALIAS audio_backend_frontend)
# 设置接口包含路径
target_include_directories(audio_backend_frontend INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}
)
# 设置接口依赖
target_link_libraries(audio_backend_frontend INTERFACE
AudioBackend::Common
AudioBackend::Communication
nlohmann_json::nlohmann_json
)
return()
endif()
# ================================================================================================
# 库目标定义
# ================================================================================================
add_library(audio_backend_frontend STATIC ${MODULE_SOURCES})
# 设置别名
add_library(AudioBackend::Frontend ALIAS audio_backend_frontend)
# ================================================================================================
# 目标属性配置
# ================================================================================================
target_include_directories(audio_backend_frontend
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)
# ================================================================================================
# 依赖关系配置
# ================================================================================================
target_link_libraries(audio_backend_frontend
PUBLIC
${audio_backend_project_options}
AudioBackend::Common
AudioBackend::Communication
PRIVATE
nlohmann_json::nlohmann_json
yaml-cpp::yaml-cpp
${PLATFORM_LIBS}
)
# ================================================================================================
# 平台特定前端配置
# ================================================================================================
if(WIN32)
# Windows前端特定功能
target_compile_definitions(audio_backend_frontend PRIVATE WIN32_LEAN_AND_MEAN)
elseif(APPLE)
# macOS前端特定功能
find_library(COREFOUNDATION_FRAMEWORK CoreFoundation)
if(COREFOUNDATION_FRAMEWORK)
target_link_libraries(audio_backend_frontend PRIVATE ${COREFOUNDATION_FRAMEWORK})
endif()
endif()
# ================================================================================================
# 目标编译定义
# ================================================================================================
target_compile_definitions(audio_backend_frontend
PRIVATE
AUDIO_BACKEND_FRONTEND_EXPORTS
PUBLIC
$<$<BOOL:${DAW_ENABLE_NETWORK}>:DAW_NETWORK_ENABLED>
)
# ================================================================================================
# 操作系统平台定义
# ================================================================================================
add_os_definitions(audio_backend_frontend)
# ================================================================================================
# 安装规则
# ================================================================================================
install(TARGETS audio_backend_frontend
EXPORT AudioBackendTargets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
message(STATUS "Frontend模块: 已配置 ${MODULE_SOURCES}个文件")

View File

@@ -0,0 +1,147 @@
# ================================================================================================
# Audio Backend - 插件沙盒宿主模块
# ================================================================================================
# 描述: 插件沙盒隔离执行环境,管理第三方插件的生命周期
# 功能: 插件加载、沙盒隔离、进程管理、资源限制
# 依赖: Common, Communication, Engine, Boost::process
# ================================================================================================
# ================================================================================================
# 自动收集源文件和头文件
# ================================================================================================
set(MODULE_SOURCES "")
retrieve_files(${CMAKE_CURRENT_SOURCE_DIR} MODULE_SOURCES)
# 如果当前没有源文件,创建一个空目标占位
if(NOT MODULE_SOURCES)
message(STATUS "Plugin Host模块: 当前无源文件,创建接口库占位")
add_library(audio_backend_plugin_host INTERFACE)
add_library(AudioBackend::PluginHost ALIAS audio_backend_plugin_host)
# 设置接口包含路径
target_include_directories(audio_backend_plugin_host INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}
)
# 设置接口依赖
target_link_libraries(audio_backend_plugin_host INTERFACE
AudioBackend::Common
AudioBackend::Communication
AudioBackend::Engine
Boost::process
Boost::system
Boost::filesystem
)
return()
endif()
# ================================================================================================
# 库目标定义
# ================================================================================================
add_library(audio_backend_plugin_host STATIC ${MODULE_SOURCES})
# 设置别名
add_library(AudioBackend::PluginHost ALIAS audio_backend_plugin_host)
# ================================================================================================
# 目标属性配置
# ================================================================================================
target_include_directories(audio_backend_plugin_host
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)
# ================================================================================================
# 依赖关系配置
# ================================================================================================
target_link_libraries(audio_backend_plugin_host
PUBLIC
${audio_backend_project_options}
AudioBackend::Common
AudioBackend::Communication
AudioBackend::Engine
PRIVATE
Boost::process
Boost::system
Boost::filesystem
${PLATFORM_LIBS}
)
# ================================================================================================
# 插件格式支持配置
# ================================================================================================
# VST支持相关的编译定义
if(DAW_ENABLE_VST2)
target_compile_definitions(audio_backend_plugin_host PUBLIC DAW_VST2_SUPPORT)
endif()
if(DAW_ENABLE_VST3)
target_compile_definitions(audio_backend_plugin_host PUBLIC DAW_VST3_SUPPORT)
endif()
if(DAW_ENABLE_CLAP)
target_compile_definitions(audio_backend_plugin_host PUBLIC DAW_CLAP_SUPPORT)
endif()
# ================================================================================================
# 平台特定沙盒配置
# ================================================================================================
if(WIN32)
# Windows沙盒支持
target_compile_definitions(audio_backend_plugin_host PRIVATE
SANDBOX_WINDOWS_SUPPORT
)
target_link_libraries(audio_backend_plugin_host PRIVATE
advapi32 # 用于安全和进程管理
userenv # 用户环境API
)
elseif(APPLE)
# macOS沙盒支持
target_compile_definitions(audio_backend_plugin_host PRIVATE
SANDBOX_MACOS_SUPPORT
)
find_library(FOUNDATION_FRAMEWORK Foundation)
if(FOUNDATION_FRAMEWORK)
target_link_libraries(audio_backend_plugin_host PRIVATE ${FOUNDATION_FRAMEWORK})
endif()
elseif(UNIX)
# Linux沙盒支持 (seccomp, namespaces, cgroups)
target_compile_definitions(audio_backend_plugin_host PRIVATE
SANDBOX_LINUX_SUPPORT
)
# 检查libseccomp可用性
find_library(SECCOMP_LIB seccomp)
if(SECCOMP_LIB)
target_link_libraries(audio_backend_plugin_host PRIVATE ${SECCOMP_LIB})
target_compile_definitions(audio_backend_plugin_host PRIVATE HAVE_SECCOMP)
endif()
endif()
# ================================================================================================
# 目标编译定义
# ================================================================================================
target_compile_definitions(audio_backend_plugin_host
PRIVATE
AUDIO_BACKEND_PLUGIN_HOST_EXPORTS
PUBLIC
$<$<BOOL:${DAW_ENABLE_SANDBOX}>:DAW_SANDBOX_ENABLED>
)
# ================================================================================================
# 操作系统平台定义
# ================================================================================================
add_os_definitions(audio_backend_plugin_host)
# ================================================================================================
# 安装规则
# ================================================================================================
install(TARGETS audio_backend_plugin_host
EXPORT AudioBackendTargets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
message(STATUS "Plugin Host模块: 已配置 ${MODULE_SOURCES}个文件")

131
src/simd/CMakeLists.txt Normal file
View File

@@ -0,0 +1,131 @@
# ================================================================================================
# Audio Backend - SIMD优化模块
# ================================================================================================
# 描述: 提供SIMD单指令多数据优化的音频处理函数
# 功能: 自动运行时检测CPU指令集并选择最优实现
# 依赖: Eigen、FFTW、TBB
# ================================================================================================
# ================================================================================================
# 自动收集源文件和头文件
# ================================================================================================
set(MODULE_SOURCES "")
retrieve_files(${CMAKE_CURRENT_SOURCE_DIR} MODULE_SOURCES)
# 如果当前没有源文件,创建一个空目标占位
if(NOT MODULE_SOURCES)
message(STATUS "SIMD模块: 当前无源文件,创建接口库占位")
add_library(audio_backend_simd INTERFACE)
add_library(AudioBackend::SIMD ALIAS audio_backend_simd)
# 设置接口包含路径
target_include_directories(audio_backend_simd INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}
)
# 设置接口依赖
target_link_libraries(audio_backend_simd INTERFACE
AudioBackend::Common
Eigen3::Eigen
TBB::tbb
)
if(TARGET fftw::fftw)
target_link_libraries(audio_backend_simd INTERFACE fftw::fftw)
endif()
return()
endif()
# ================================================================================================
# 库目标定义
# ================================================================================================
add_library(audio_backend_simd STATIC ${MODULE_SOURCES})
# 设置别名
add_library(AudioBackend::SIMD ALIAS audio_backend_simd)
# ================================================================================================
# 目标属性配置
# ================================================================================================
target_include_directories(audio_backend_simd
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)
# ================================================================================================
# 依赖关系配置
# ================================================================================================
target_link_libraries(audio_backend_simd
PUBLIC
${audio_backend_project_options}
AudioBackend::Common
Eigen3::Eigen
TBB::tbb
PRIVATE
# 私有依赖
)
# 条件性依赖FFTW
if(TARGET fftw::fftw)
target_link_libraries(audio_backend_simd PUBLIC fftw::fftw)
endif()
# ================================================================================================
# SIMD特定编译选项
# ================================================================================================
# 1. 对于x86/x64平台启用特定的SIMD指令集
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64|i686")
if(MSVC)
if(DAW_ENABLE_AVX512)
target_compile_options(audio_backend_simd PRIVATE /arch:AVX512)
elseif(DAW_ENABLE_SIMD)
target_compile_options(audio_backend_simd PRIVATE /arch:AVX2)
endif()
else() # GCC/Clang
if(DAW_ENABLE_AVX512)
target_compile_options(audio_backend_simd PRIVATE
-mavx512f -mavx512vl -mavx512bw -mfma)
elseif(DAW_ENABLE_SIMD)
target_compile_options(audio_backend_simd PRIVATE -mavx2 -mfma)
endif()
endif()
# 2. 对于ARM平台启用NEON
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "arm|aarch64|ARM64")
if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|ARM64")
# ARM64自动支持NEON不需要额外标志
else()
if(NOT APPLE) # ARM32非Apple平台
target_compile_options(audio_backend_simd PRIVATE -mfpu=neon)
endif()
endif()
endif()
# ================================================================================================
# 目标编译定义
# ================================================================================================
target_compile_definitions(audio_backend_simd
PRIVATE
AUDIO_BACKEND_SIMD_EXPORTS
PUBLIC
$<$<BOOL:${DAW_ENABLE_SIMD}>:DAW_SIMD_ENABLED>
$<$<BOOL:${DAW_ENABLE_AVX512}>:DAW_AVX512_ENABLED>
)
# ================================================================================================
# 操作系统平台定义
# ================================================================================================
add_os_definitions(audio_backend_simd)
# ================================================================================================
# 安装规则
# ================================================================================================
install(TARGETS audio_backend_simd
EXPORT AudioBackendTargets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
message(STATUS "SIMD模块: 已配置 ${MODULE_SOURCES}个文件")

View File

@@ -0,0 +1,305 @@
// ================================================================================================
// Audio Backend - SIMD内存对齐分配器
// ================================================================================================
// 描述: 为SIMD操作提供正确对齐的内存分配
// 功能: 支持16/32/64字节对齐确保SIMD指令高效执行
// ================================================================================================
#pragma once
#include <cstddef>
#include <cstdlib>
#include <memory>
#include <new>
#include <type_traits>
namespace audio_backend::simd {
// ================================================================================================
// 对齐常量
// ================================================================================================
constexpr size_t ALIGNMENT_SSE = 16; // SSE需要16字节对齐
constexpr size_t ALIGNMENT_AVX = 32; // AVX需要32字节对齐
constexpr size_t ALIGNMENT_AVX512 = 64; // AVX-512需要64字节对齐
constexpr size_t ALIGNMENT_CACHE = 64; // CPU缓存行大小通常64字节
// ================================================================================================
// 对齐内存分配/释放函数
// ================================================================================================
// 分配对齐内存
inline void* aligned_malloc(size_t size, size_t alignment) {
if (alignment == 0 || (alignment & (alignment - 1)) != 0) {
// 对齐值必须是2的幂
return nullptr;
}
#if ALICHO_PLATFORM_WINDOWS
return _aligned_malloc(size, alignment);
#elif ALICHO_PLATFORM_POSIX || ALICHO_PLATFORM_UNIX
void* ptr = nullptr;
if (posix_memalign(&ptr, alignment, size) != 0) {
return nullptr;
}
return ptr;
#else
// 回退实现:手动对齐
// 分配额外空间来存储原始指针和进行对齐
size_t total_size = size + alignment + sizeof(void*);
void* raw_ptr = std::malloc(total_size);
if (!raw_ptr) {
return nullptr;
}
// 计算对齐后的地址
uintptr_t raw_addr = reinterpret_cast<uintptr_t>(raw_ptr);
uintptr_t aligned_addr = (raw_addr + sizeof(void*) + alignment - 1) & ~(alignment - 1);
void* aligned_ptr = reinterpret_cast<void*>(aligned_addr);
// 在对齐地址前存储原始指针
(reinterpret_cast<void**>(aligned_ptr))[-1] = raw_ptr;
return aligned_ptr;
#endif
}
// 释放对齐内存
inline void aligned_free(void* ptr) {
if (!ptr) return;
#if ALICHO_PLATFORM_WINDOWS
_aligned_free(ptr);
#elif ALICHO_PLATFORM_POSIX || ALICHO_PLATFORM_UNIX
std::free(ptr);
#else
// 回退实现:获取原始指针并释放
void* raw_ptr = (reinterpret_cast<void**>(ptr))[-1];
std::free(raw_ptr);
#endif
}
// ================================================================================================
// 对齐分配器用于STL容器
// ================================================================================================
template<typename T, size_t Alignment = ALIGNMENT_AVX>
class AlignedAllocator {
public:
using value_type = T;
using pointer = T*;
using const_pointer = const T*;
using reference = T&;
using const_reference = const T&;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
template<typename U>
struct rebind {
using other = AlignedAllocator<U, Alignment>;
};
AlignedAllocator() noexcept = default;
template<typename U>
AlignedAllocator(const AlignedAllocator<U, Alignment>&) noexcept {}
pointer allocate(size_type n) {
if (n == 0) return nullptr;
size_type size = n * sizeof(T);
void* ptr = aligned_malloc(size, Alignment);
if (!ptr) {
throw std::bad_alloc();
}
return static_cast<pointer>(ptr);
}
void deallocate(pointer p, size_type) noexcept {
aligned_free(p);
}
template<typename U, typename... Args>
void construct(U* p, Args&&... args) {
::new(static_cast<void*>(p)) U(std::forward<Args>(args)...);
}
template<typename U>
void destroy(U* p) {
p->~U();
}
size_type max_size() const noexcept {
return std::numeric_limits<size_type>::max() / sizeof(T);
}
};
template<typename T1, size_t A1, typename T2, size_t A2>
bool operator==(const AlignedAllocator<T1, A1>&, const AlignedAllocator<T2, A2>&) noexcept {
return A1 == A2;
}
template<typename T1, size_t A1, typename T2, size_t A2>
bool operator!=(const AlignedAllocator<T1, A1>&, const AlignedAllocator<T2, A2>&) noexcept {
return A1 != A2;
}
// ================================================================================================
// 便捷类型定义
// ================================================================================================
template<typename T>
using AlignedVector16 = std::vector<T, AlignedAllocator<T, ALIGNMENT_SSE>>;
template<typename T>
using AlignedVector32 = std::vector<T, AlignedAllocator<T, ALIGNMENT_AVX>>;
template<typename T>
using AlignedVector64 = std::vector<T, AlignedAllocator<T, ALIGNMENT_AVX512>>;
// 根据当前CPU支持的最高SIMD级别选择对齐方式
template<typename T>
using AlignedVectorAuto = std::vector<T, AlignedAllocator<T, ALIGNMENT_AVX>>;
// ================================================================================================
// 对齐检查工具
// ================================================================================================
// 检查指针是否对齐
template<size_t Alignment>
inline bool is_aligned(const void* ptr) {
return (reinterpret_cast<uintptr_t>(ptr) % Alignment) == 0;
}
// 检查指针是否按特定字节数对齐
inline bool is_aligned(const void* ptr, size_t alignment) {
return (reinterpret_cast<uintptr_t>(ptr) % alignment) == 0;
}
// 计算对齐后的大小
inline size_t align_size(size_t size, size_t alignment) {
return (size + alignment - 1) & ~(alignment - 1);
}
// 计算对齐后的指针
template<size_t Alignment>
inline void* align_pointer(void* ptr) {
uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);
uintptr_t aligned = (addr + Alignment - 1) & ~(Alignment - 1);
return reinterpret_cast<void*>(aligned);
}
// ================================================================================================
// RAII对齐内存管理器
// ================================================================================================
template<typename T, size_t Alignment = ALIGNMENT_AVX>
class AlignedBuffer {
public:
AlignedBuffer() : data_(nullptr), size_(0) {}
explicit AlignedBuffer(size_t count) : data_(nullptr), size_(0) {
allocate(count);
}
~AlignedBuffer() {
deallocate();
}
// 禁止拷贝
AlignedBuffer(const AlignedBuffer&) = delete;
AlignedBuffer& operator=(const AlignedBuffer&) = delete;
// 允许移动
AlignedBuffer(AlignedBuffer&& other) noexcept
: data_(other.data_), size_(other.size_) {
other.data_ = nullptr;
other.size_ = 0;
}
AlignedBuffer& operator=(AlignedBuffer&& other) noexcept {
if (this != &other) {
deallocate();
data_ = other.data_;
size_ = other.size_;
other.data_ = nullptr;
other.size_ = 0;
}
return *this;
}
void allocate(size_t count) {
deallocate();
if (count > 0) {
data_ = static_cast<T*>(aligned_malloc(count * sizeof(T), Alignment));
if (!data_) {
throw std::bad_alloc();
}
size_ = count;
// 对于非POD类型需要构造对象
if constexpr (!std::is_trivially_constructible_v<T>) {
for (size_t i = 0; i < size_; ++i) {
new(data_ + i) T();
}
}
}
}
void deallocate() {
if (data_) {
// 对于非POD类型需要析构对象
if constexpr (!std::is_trivially_destructible_v<T>) {
for (size_t i = 0; i < size_; ++i) {
data_[i].~T();
}
}
aligned_free(data_);
data_ = nullptr;
size_ = 0;
}
}
void resize(size_t new_count) {
if (new_count != size_) {
allocate(new_count);
}
}
T* data() noexcept { return data_; }
const T* data() const noexcept { return data_; }
size_t size() const noexcept { return size_; }
bool empty() const noexcept { return size_ == 0; }
T& operator[](size_t index) noexcept { return data_[index]; }
const T& operator[](size_t index) const noexcept { return data_[index]; }
T* begin() noexcept { return data_; }
T* end() noexcept { return data_ + size_; }
const T* begin() const noexcept { return data_; }
const T* end() const noexcept { return data_ + size_; }
// 检查对齐
bool is_properly_aligned() const noexcept {
return is_aligned<Alignment>(data_);
}
private:
T* data_;
size_t size_;
};
// ================================================================================================
// 对齐断言宏
// ================================================================================================
#ifdef AUDIO_BACKEND_DEBUG
#define ASSERT_ALIGNED(ptr, alignment) \
do { \
if (!audio_backend::simd::is_aligned(ptr, alignment)) { \
throw std::runtime_error("Pointer not properly aligned"); \
} \
} while(0)
#else
#define ASSERT_ALIGNED(ptr, alignment) ((void)0)
#endif
} // namespace audio_backend::simd

View File

@@ -0,0 +1,249 @@
// ================================================================================================
// Audio Backend - SIMD音频处理函数实现
// ================================================================================================
#include "audio_processing.h"
#include <cmath>
#include <algorithm>
#include <limits>
#include <iostream>
// SSE相关头文件
#if ALICHO_PLATFORM_X86
#include <immintrin.h>
#endif
// NEON相关头文件
#if ALICHO_PLATFORM_ARM && defined(__ARM_NEON)
#include <arm_neon.h>
#endif
namespace audio_backend::simd {
// ================================================================================================
// 混合函数 - 标量实现(所有平台通用)
// ================================================================================================
void mix_audio_f32_scalar(const float* input1, const float* input2, float* output, size_t samples) {
for (size_t i = 0; i < samples; ++i) {
output[i] = input1[i] + input2[i];
}
}
// ================================================================================================
// 混合函数 - SSE实现
// ================================================================================================
#if ALICHO_PLATFORM_X86
void mix_audio_f32_sse(const float* input1, const float* input2, float* output, size_t samples) {
ASSERT_ALIGNED(input1, ALIGNMENT_SSE);
ASSERT_ALIGNED(input2, ALIGNMENT_SSE);
ASSERT_ALIGNED(output, ALIGNMENT_SSE);
const size_t vector_size = 4; // 每个SSE向量处理4个浮点数
size_t i = 0;
// 向量化处理
for (; i + vector_size <= samples; i += vector_size) {
__m128 vec1 = _mm_load_ps(input1 + i);
__m128 vec2 = _mm_load_ps(input2 + i);
__m128 result = _mm_add_ps(vec1, vec2);
_mm_store_ps(output + i, result);
}
// 处理剩余元素
for (; i < samples; ++i) {
output[i] = input1[i] + input2[i];
}
}
// ================================================================================================
// 混合函数 - AVX实现
// ================================================================================================
void mix_audio_f32_avx(const float* input1, const float* input2, float* output, size_t samples) {
ASSERT_ALIGNED(input1, ALIGNMENT_AVX);
ASSERT_ALIGNED(input2, ALIGNMENT_AVX);
ASSERT_ALIGNED(output, ALIGNMENT_AVX);
const size_t vector_size = 8; // 每个AVX向量处理8个浮点数
size_t i = 0;
// 向量化处理
for (; i + vector_size <= samples; i += vector_size) {
__m256 vec1 = _mm256_load_ps(input1 + i);
__m256 vec2 = _mm256_load_ps(input2 + i);
__m256 result = _mm256_add_ps(vec1, vec2);
_mm256_store_ps(output + i, result);
}
// 处理剩余元素
for (; i < samples; ++i) {
output[i] = input1[i] + input2[i];
}
}
#endif
// ================================================================================================
// 混合函数 - ARM NEON实现
// ================================================================================================
#if ALICHO_PLATFORM_ARM && defined(__ARM_NEON)
void mix_audio_f32_neon(const float* input1, const float* input2, float* output, size_t samples) {
const size_t vector_size = 4; // 每个NEON向量处理4个浮点数
size_t i = 0;
// 向量化处理
for (; i + vector_size <= samples; i += vector_size) {
float32x4_t vec1 = vld1q_f32(input1 + i);
float32x4_t vec2 = vld1q_f32(input2 + i);
float32x4_t result = vaddq_f32(vec1, vec2);
vst1q_f32(output + i, result);
}
// 处理剩余元素
for (; i < samples; ++i) {
output[i] = input1[i] + input2[i];
}
}
#endif
// ================================================================================================
// 音量控制函数 - 标量实现
// ================================================================================================
void apply_gain_f32_scalar(const float* input, float gain, float* output, size_t samples) {
for (size_t i = 0; i < samples; ++i) {
output[i] = input[i] * gain;
}
}
// ================================================================================================
// 音量控制函数 - SSE实现
// ================================================================================================
#if ALICHO_PLATFORM_X86
void apply_gain_f32_sse(const float* input, float gain, float* output, size_t samples) {
ASSERT_ALIGNED(input, ALIGNMENT_SSE);
ASSERT_ALIGNED(output, ALIGNMENT_SSE);
const size_t vector_size = 4;
size_t i = 0;
// 创建填充了增益值的向量
__m128 gain_vec = _mm_set1_ps(gain);
// 向量化处理
for (; i + vector_size <= samples; i += vector_size) {
__m128 in_vec = _mm_load_ps(input + i);
__m128 result = _mm_mul_ps(in_vec, gain_vec);
_mm_store_ps(output + i, result);
}
// 处理剩余元素
for (; i < samples; ++i) {
output[i] = input[i] * gain;
}
}
#endif
// ================================================================================================
// 格式转换 - 16位整数转32位浮点标量实现
// ================================================================================================
void convert_i16_to_f32_scalar(const int16_t* input, float* output, size_t samples) {
const float scale = 1.0f / 32768.0f; // 将[-32768, 32767]缩放到[-1.0, 1.0]
for (size_t i = 0; i < samples; ++i) {
output[i] = input[i] * scale;
}
}
// ================================================================================================
// 格式转换 - 16位整数转32位浮点SSE实现
// ================================================================================================
#if ALICHO_PLATFORM_X86
void convert_i16_to_f32_sse(const int16_t* input, float* output, size_t samples) {
ASSERT_ALIGNED(output, ALIGNMENT_SSE);
const size_t vector_size = 4;
size_t i = 0;
const __m128 scale_vec = _mm_set1_ps(1.0f / 32768.0f);
// 向量化处理
for (; i + vector_size <= samples; i += vector_size) {
// 加载4个16位整数并转换为32位整数
__m128i in_i16 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(input + i));
// 将前4个16位整数转换为32位整数
__m128i in_i32 = _mm_cvtepi16_epi32(in_i16);
// 转换为浮点数
__m128 in_f32 = _mm_cvtepi32_ps(in_i32);
// 缩放到[-1.0, 1.0]
__m128 result = _mm_mul_ps(in_f32, scale_vec);
// 存储结果
_mm_store_ps(output + i, result);
}
// 处理剩余元素
for (; i < samples; ++i) {
output[i] = input[i] * (1.0f / 32768.0f);
}
}
#endif
// ================================================================================================
// 音频处理函数注册
// ================================================================================================
void AudioProcessingRegistry::register_all_functions() {
// 注册混音函数
REGISTER_SIMD_FUNCTION("mix_audio_f32", FunctionVersion::SCALAR, mix_audio_f32_scalar);
#if ALICHO_PLATFORM_X86
REGISTER_SIMD_FUNCTION("mix_audio_f32", FunctionVersion::SSE, mix_audio_f32_sse);
REGISTER_SIMD_FUNCTION("mix_audio_f32", FunctionVersion::AVX, mix_audio_f32_avx);
#endif
#if ALICHO_PLATFORM_ARM && defined(__ARM_NEON)
REGISTER_SIMD_FUNCTION("mix_audio_f32", FunctionVersion::NEON, mix_audio_f32_neon);
#endif
// 注册音量控制函数
REGISTER_SIMD_FUNCTION("apply_gain_f32", FunctionVersion::SCALAR, apply_gain_f32_scalar);
#if ALICHO_PLATFORM_X86
REGISTER_SIMD_FUNCTION("apply_gain_f32", FunctionVersion::SSE, apply_gain_f32_sse);
#endif
// 注册格式转换函数
REGISTER_SIMD_FUNCTION("convert_i16_to_f32", FunctionVersion::SCALAR, convert_i16_to_f32_scalar);
#if ALICHO_PLATFORM_X86
REGISTER_SIMD_FUNCTION("convert_i16_to_f32", FunctionVersion::SSE, convert_i16_to_f32_sse);
#endif
// 可以在这里添加更多函数注册
}
void AudioProcessingRegistry::print_available_functions() {
FunctionDispatcher::instance().print_registry_status();
}
// ================================================================================================
// 对外API实现调用注册的最优函数
// ================================================================================================
void mix_audio_f32(const float* input1, const float* input2, float* output, size_t samples) {
CALL_SIMD_FUNCTION(void(const float*, const float*, float*, size_t), "mix_audio_f32",
input1, input2, output, samples);
}
void apply_gain_f32(const float* input, float gain, float* output, size_t samples) {
CALL_SIMD_FUNCTION(void(const float*, float, float*, size_t), "apply_gain_f32",
input, gain, output, samples);
}
void convert_i16_to_f32(const int16_t* input, float* output, size_t samples) {
CALL_SIMD_FUNCTION(void(const int16_t*, float*, size_t), "convert_i16_to_f32",
input, output, samples);
}
// 其它函数可以按需添加
} // namespace audio_backend::simd

227
src/simd/audio_processing.h Normal file
View File

@@ -0,0 +1,227 @@
// ================================================================================================
// Audio Backend - SIMD音频处理函数
// ================================================================================================
// 描述: 使用SIMD优化的音频处理函数集合
// 功能: 音频混合、音量控制、格式转换、基础数学运算
// ================================================================================================
#pragma once
#include "function_dispatcher.h"
#include "aligned_allocator.h"
#include <cstddef>
#include <cstdint>
namespace audio_backend::simd {
// ================================================================================================
// 音频格式定义
// ================================================================================================
enum class AudioFormat {
INT16, // 16位有符号整数
INT24, // 24位有符号整数通常打包在int32中
INT32, // 32位有符号整数
FLOAT32, // 32位浮点数
FLOAT64 // 64位浮点数
};
// ================================================================================================
// 音频混合函数
// ================================================================================================
// 混合两个浮点音频缓冲区
void mix_audio_f32(const float* input1, const float* input2, float* output, size_t samples);
// 混合多个浮点音频缓冲区
void mix_audio_multi_f32(const float* const* inputs, size_t num_inputs, float* output, size_t samples);
// 带权重的音频混合
void mix_audio_weighted_f32(const float* input1, float weight1,
const float* input2, float weight2,
float* output, size_t samples);
// ================================================================================================
// 音量控制函数
// ================================================================================================
// 应用恒定音量倍数
void apply_gain_f32(const float* input, float gain, float* output, size_t samples);
// 应用渐变音量(线性插值)
void apply_gain_ramp_f32(const float* input, float start_gain, float end_gain,
float* output, size_t samples);
// 应用每个样本不同的音量
void apply_gain_per_sample_f32(const float* input, const float* gains,
float* output, size_t samples);
// ================================================================================================
// 音频格式转换函数
// ================================================================================================
// 16位整数转32位浮点数
void convert_i16_to_f32(const int16_t* input, float* output, size_t samples);
// 32位浮点数转16位整数
void convert_f32_to_i16(const float* input, int16_t* output, size_t samples);
// 32位整数转32位浮点数
void convert_i32_to_f32(const int32_t* input, float* output, size_t samples);
// 32位浮点数转32位整数
void convert_f32_to_i32(const float* input, int32_t* output, size_t samples);
// 单声道转立体声(复制)
void mono_to_stereo_f32(const float* input, float* output, size_t samples);
// 立体声转单声道(平均)
void stereo_to_mono_f32(const float* input, float* output, size_t samples);
// ================================================================================================
// 数学运算函数
// ================================================================================================
// 向量加法
void vector_add_f32(const float* a, const float* b, float* result, size_t samples);
// 向量减法
void vector_subtract_f32(const float* a, const float* b, float* result, size_t samples);
// 向量乘法
void vector_multiply_f32(const float* a, const float* b, float* result, size_t samples);
// 标量乘法
void vector_scale_f32(const float* input, float scale, float* output, size_t samples);
// 计算RMS均方根
float calculate_rms_f32(const float* input, size_t samples);
// 计算峰值
float calculate_peak_f32(const float* input, size_t samples);
// ================================================================================================
// 滤波器和效果函数
// ================================================================================================
// 简单低通滤波器(一阶)
void lowpass_filter_f32(const float* input, float* output, size_t samples,
float cutoff_freq, float sample_rate, float* state);
// 简单高通滤波器(一阶)
void highpass_filter_f32(const float* input, float* output, size_t samples,
float cutoff_freq, float sample_rate, float* state);
// 延迟效果
void delay_effect_f32(const float* input, float* output, size_t samples,
float* delay_buffer, size_t delay_buffer_size,
size_t delay_samples, float feedback, float* delay_index);
// ================================================================================================
// 音频分析函数
// ================================================================================================
// 检测静音
bool detect_silence_f32(const float* input, size_t samples, float threshold = -60.0f);
// 检测削波
bool detect_clipping_f32(const float* input, size_t samples, float threshold = 0.99f);
// 计算频谱能量需要配合FFT使用
void calculate_spectral_energy_f32(const float* fft_output, float* energy_bands,
size_t fft_size, size_t num_bands);
// ================================================================================================
// SIMD优化的音频缓冲区类
// ================================================================================================
template<typename T, size_t Alignment = ALIGNMENT_AVX>
class AudioBuffer {
public:
AudioBuffer() = default;
AudioBuffer(size_t channels, size_t samples)
: channels_(channels), samples_(samples) {
allocate(channels, samples);
}
void allocate(size_t channels, size_t samples) {
channels_ = channels;
samples_ = samples;
size_t total_samples = channels * samples;
buffer_.resize(total_samples);
}
void clear() {
std::fill(buffer_.begin(), buffer_.end(), T{});
}
T* channel_data(size_t channel) {
return buffer_.data() + channel * samples_;
}
const T* channel_data(size_t channel) const {
return buffer_.data() + channel * samples_;
}
T* data() { return buffer_.data(); }
const T* data() const { return buffer_.data(); }
size_t channels() const { return channels_; }
size_t samples() const { return samples_; }
size_t size() const { return buffer_.size(); }
bool empty() const { return buffer_.empty(); }
// 获取交错格式的数据LRLRLR...
void to_interleaved(T* output) const {
for (size_t sample = 0; sample < samples_; ++sample) {
for (size_t channel = 0; channel < channels_; ++channel) {
output[sample * channels_ + channel] =
buffer_[channel * samples_ + sample];
}
}
}
// 从交错格式填充数据
void from_interleaved(const T* input) {
for (size_t sample = 0; sample < samples_; ++sample) {
for (size_t channel = 0; channel < channels_; ++channel) {
buffer_[channel * samples_ + sample] =
input[sample * channels_ + channel];
}
}
}
// 检查对齐
bool is_properly_aligned() const {
return is_aligned<Alignment>(buffer_.data());
}
private:
size_t channels_ = 0;
size_t samples_ = 0;
AlignedBuffer<T, Alignment> buffer_;
};
// 便捷类型定义
using AudioBufferF32 = AudioBuffer<float>;
using AudioBufferI16 = AudioBuffer<int16_t>;
using AudioBufferI32 = AudioBuffer<int32_t>;
// ================================================================================================
// 函数注册器用于在启动时注册所有SIMD版本
// ================================================================================================
class AudioProcessingRegistry {
public:
static void register_all_functions();
static void print_available_functions();
};
// ================================================================================================
// 便捷宏定义
// ================================================================================================
// 调用最优SIMD版本的宏
#define CALL_SIMD_AUDIO_FUNCTION(name, ...) \
CALL_SIMD_FUNCTION(decltype(name), #name, __VA_ARGS__)
} // namespace audio_backend::simd

513
src/simd/cpu_features.cpp Normal file
View File

@@ -0,0 +1,513 @@
// ================================================================================================
// Audio Backend - SIMD CPU特性检测器实现
// ================================================================================================
#include "cpu_features.h"
#include <cstring>
#include <iostream>
#include <thread>
// 平台特定的头文件
#if ALICHO_PLATFORM_WINDOWS
#include <windows.h>
#include <intrin.h>
#elif ALICHO_PLATFORM_UNIX || ALICHO_PLATFORM_POSIX
#if ALICHO_PLATFORM_X86
#include <cpuid.h>
#endif
#include <pthread.h>
#include <unistd.h>
#if ALICHO_PLATFORM_APPLE
#include <sys/sysctl.h>
#endif
#endif
// ARM NEON支持
#if ALICHO_PLATFORM_ARM && defined(__ARM_NEON)
#include <arm_neon.h>
#endif
namespace audio_backend::simd {
// ================================================================================================
// CPUInfo的features_string方法实现
// ================================================================================================
std::string CPUInfo::features_string() const {
std::string result;
struct FeatureNamePair {
CPUFeature feature;
const char* name;
};
static const FeatureNamePair feature_names[] = {
{ CPUFeature::SSE, "SSE" },
{ CPUFeature::SSE2, "SSE2" },
{ CPUFeature::SSE3, "SSE3" },
{ CPUFeature::SSSE3, "SSSE3" },
{ CPUFeature::SSE41, "SSE4.1" },
{ CPUFeature::SSE42, "SSE4.2" },
{ CPUFeature::AVX, "AVX" },
{ CPUFeature::AVX2, "AVX2" },
{ CPUFeature::FMA, "FMA" },
{ CPUFeature::AVX512F, "AVX512F" },
{ CPUFeature::AVX512VL, "AVX512VL" },
{ CPUFeature::AVX512BW, "AVX512BW" },
{ CPUFeature::AVX512DQ, "AVX512DQ" },
{ CPUFeature::NEON, "NEON" },
{ CPUFeature::NEON_FP16, "NEON_FP16" },
{ CPUFeature::POPCNT, "POPCNT" },
{ CPUFeature::BMI1, "BMI1" }
};
for (const auto& pair : feature_names) {
if (supports(pair.feature)) {
if (!result.empty()) {
result += ", ";
}
result += pair.name;
}
}
return result;
}
// ================================================================================================
// x86/x64平台CPUID实现
// ================================================================================================
#if ALICHO_PLATFORM_X86
struct CPUIDResult {
uint32_t eax, ebx, ecx, edx;
};
#if ALICHO_PLATFORM_WINDOWS
// Windows平台CPUID实现
static CPUIDResult cpuid(uint32_t function_id, uint32_t subfunction_id = 0) {
CPUIDResult result;
int regs[4];
__cpuidex(regs, function_id, subfunction_id);
result.eax = static_cast<uint32_t>(regs[0]);
result.ebx = static_cast<uint32_t>(regs[1]);
result.ecx = static_cast<uint32_t>(regs[2]);
result.edx = static_cast<uint32_t>(regs[3]);
return result;
}
#else
// Unix/Linux/macOS平台CPUID实现
static CPUIDResult cpuid(uint32_t function_id, uint32_t subfunction_id = 0) {
CPUIDResult result;
uint32_t regs[4];
__cpuid_count(function_id, subfunction_id, regs[0], regs[1], regs[2], regs[3]);
result.eax = regs[0];
result.ebx = regs[1];
result.ecx = regs[2];
result.edx = regs[3];
return result;
}
#endif
static void get_vendor_string(char* vendor_string) {
CPUIDResult result = cpuid(0, 0);
// 制造商ID字符串由EBX, EDX, ECX组成
reinterpret_cast<int*>(vendor_string)[0] = result.ebx;
reinterpret_cast<int*>(vendor_string)[1] = result.edx;
reinterpret_cast<int*>(vendor_string)[2] = result.ecx;
vendor_string[12] = '\0';
}
static void get_brand_string(char* brand_string) {
CPUIDResult result;
// 检查是否支持品牌字符串
result = cpuid(0x80000000, 0);
if (result.eax < 0x80000004) {
strcpy(brand_string, "Unknown");
return;
}
// 获取品牌字符串的三部分
for (uint32_t i = 0; i < 3; ++i) {
result = cpuid(0x80000002 + i, 0);
reinterpret_cast<int*>(brand_string + i * 16)[0] = result.eax;
reinterpret_cast<int*>(brand_string + i * 16)[1] = result.ebx;
reinterpret_cast<int*>(brand_string + i * 16)[2] = result.ecx;
reinterpret_cast<int*>(brand_string + i * 16)[3] = result.edx;
}
brand_string[48] = '\0';
}
#endif // ALICHO_PLATFORM_X86
// ================================================================================================
// 构造函数和初始化
// ================================================================================================
CPUFeatureDetector::CPUFeatureDetector() : info_{} {
// 初始化CPU信息
info_.vendor = "Unknown";
info_.brand = "Unknown";
info_.features = 0;
info_.max_simd_level = SIMDLevel::NONE;
// 检测逻辑核心数
#if ALICHO_PLATFORM_WINDOWS
SYSTEM_INFO sysInfo;
GetSystemInfo(&sysInfo);
info_.logical_cores = sysInfo.dwNumberOfProcessors;
#else
// Unix/Linux/macOS平台
info_.logical_cores = static_cast<int>(std::thread::hardware_concurrency());
#endif
info_.physical_cores = info_.logical_cores; // 默认,后续可能会修正
// 检测CPU特性
detect_features();
}
void CPUFeatureDetector::detect_features() {
#if ALICHO_PLATFORM_X86
detect_x86_features();
#elif ALICHO_PLATFORM_ARM
detect_arm_features();
#else
// 不支持的架构
info_.max_simd_level = SIMDLevel::NONE;
#endif
}
#if ALICHO_PLATFORM_X86
void CPUFeatureDetector::detect_x86_features() {
char vendor[13] = {0};
char brand[49] = {0};
// 获取制造商和品牌字符串
get_vendor_string(vendor);
get_brand_string(brand);
info_.vendor = vendor;
info_.brand = brand;
// 获取标准特性
CPUIDResult cpuid_1 = cpuid(1, 0);
// 检测SSE特性
if ((cpuid_1.edx & (1 << 25)) != 0) {
info_.features |= static_cast<uint32_t>(CPUFeature::SSE);
}
if ((cpuid_1.edx & (1 << 26)) != 0) {
info_.features |= static_cast<uint32_t>(CPUFeature::SSE2);
}
if ((cpuid_1.ecx & (1 << 0)) != 0) {
info_.features |= static_cast<uint32_t>(CPUFeature::SSE3);
}
if ((cpuid_1.ecx & (1 << 9)) != 0) {
info_.features |= static_cast<uint32_t>(CPUFeature::SSSE3);
}
if ((cpuid_1.ecx & (1 << 19)) != 0) {
info_.features |= static_cast<uint32_t>(CPUFeature::SSE41);
}
if ((cpuid_1.ecx & (1 << 20)) != 0) {
info_.features |= static_cast<uint32_t>(CPUFeature::SSE42);
}
if ((cpuid_1.ecx & (1 << 28)) != 0) {
info_.features |= static_cast<uint32_t>(CPUFeature::AVX);
}
if ((cpuid_1.ecx & (1 << 12)) != 0) {
info_.features |= static_cast<uint32_t>(CPUFeature::FMA);
}
if ((cpuid_1.ecx & (1 << 23)) != 0) {
info_.features |= static_cast<uint32_t>(CPUFeature::POPCNT);
}
// 获取扩展特性
CPUIDResult cpuid_7 = cpuid(7, 0);
if ((cpuid_7.ebx & (1 << 5)) != 0) {
info_.features |= static_cast<uint32_t>(CPUFeature::AVX2);
}
if ((cpuid_7.ebx & (1 << 3)) != 0) {
info_.features |= static_cast<uint32_t>(CPUFeature::BMI1);
}
// AVX-512检测
if ((cpuid_7.ebx & (1 << 16)) != 0) {
info_.features |= static_cast<uint32_t>(CPUFeature::AVX512F);
}
if ((cpuid_7.ebx & (1 << 31)) != 0) {
info_.features |= static_cast<uint32_t>(CPUFeature::AVX512VL);
}
if ((cpuid_7.ebx & (1 << 30)) != 0) {
info_.features |= static_cast<uint32_t>(CPUFeature::AVX512BW);
}
if ((cpuid_7.ebx & (1 << 17)) != 0) {
info_.features |= static_cast<uint32_t>(CPUFeature::AVX512DQ);
}
// 确定最高SIMD级别
if (info_.supports(CPUFeature::AVX512F) &&
info_.supports(CPUFeature::AVX512VL) &&
info_.supports(CPUFeature::AVX512BW)) {
info_.max_simd_level = SIMDLevel::AVX512;
}
else if (info_.supports(CPUFeature::AVX2) &&
info_.supports(CPUFeature::FMA)) {
info_.max_simd_level = SIMDLevel::AVX2;
}
else if (info_.supports(CPUFeature::AVX)) {
info_.max_simd_level = SIMDLevel::AVX;
}
else if (info_.supports(CPUFeature::SSE42)) {
info_.max_simd_level = SIMDLevel::SSE4;
}
else if (info_.supports(CPUFeature::SSSE3) ||
info_.supports(CPUFeature::SSE3)) {
info_.max_simd_level = SIMDLevel::SSE3;
}
else if (info_.supports(CPUFeature::SSE2)) {
info_.max_simd_level = SIMDLevel::SSE;
}
else {
info_.max_simd_level = SIMDLevel::NONE;
}
// 获取物理核心数 - 平台特定实现
#if ALICHO_PLATFORM_WINDOWS
// Windows特定的物理心数检测
DWORD length = 0;
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = nullptr;
// 获取所需缓冲区大小
GetLogicalProcessorInformation(buffer, &length);
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(length);
if (buffer) {
if (GetLogicalProcessorInformation(buffer, &length)) {
DWORD processorCoreCount = 0;
DWORD byteOffset = 0;
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = buffer;
while (byteOffset < length) {
if (ptr->Relationship == RelationProcessorCore) {
processorCoreCount++;
}
byteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
ptr++;
}
if (processorCoreCount > 0) {
info_.physical_cores = processorCoreCount;
}
}
free(buffer);
}
}
#elif ALICHO_PLATFORM_MACOS
// macOS特定的物理核数检测
int nm[2];
size_t len = 4;
uint32_t count;
nm[0] = CTL_HW;
nm[1] = HW_AVAILCPU;
sysctlbyname("hw.physicalcpu", &count, &len, NULL, 0);
if (count > 0) {
info_.physical_cores = static_cast<int>(count);
} else {
// 回退到逻辑核心数
info_.physical_cores = info_.logical_cores;
}
#elif ALICHO_PLATFORM_LINUX
// Linux特定的物理核数检测
// 尝试读取/proc/cpuinfo
FILE* fp = fopen("/proc/cpuinfo", "r");
if (fp) {
char buffer[1024];
std::unordered_set<std::string> physical_ids;
while (fgets(buffer, sizeof(buffer), fp)) {
if (strncmp(buffer, "physical id", 11) == 0) {
char* id_pos = strchr(buffer, ':');
if (id_pos) {
physical_ids.insert(std::string(id_pos + 1));
}
}
}
fclose(fp);
if (!physical_ids.empty()) {
info_.physical_cores = static_cast<int>(physical_ids.size());
}
}
#endif
}
#endif // ALICHO_PLATFORM_X86
#if ALICHO_PLATFORM_ARM
void CPUFeatureDetector::detect_arm_features() {
// ARM架构下的特性检测
#if defined(__ARM_NEON) || defined(__aarch64__)
info_.features |= static_cast<uint32_t>(CPUFeature::NEON);
info_.max_simd_level = SIMDLevel::NEON;
#ifdef __ARM_FEATURE_FP16
info_.features |= static_cast<uint32_t>(CPUFeature::NEON_FP16);
info_.max_simd_level = SIMDLevel::NEON_FP16;
#endif
#endif
// 在ARM上获取更多CPU信息
#if ALICHO_PLATFORM_ANDROID
// Android特定代码
info_.vendor = "ARM";
// 尝试从/proc/cpuinfo取更多信息
FILE* fp = fopen("/proc/cpuinfo", "r");
if (fp) {
char buffer[1024];
while (fgets(buffer, sizeof(buffer), fp)) {
if (strncmp(buffer, "Hardware", 8) == 0 ||
strncmp(buffer, "model name", 10) == 0) {
char* sep = strchr(buffer, ':');
if (sep) {
// 去除前导空格
char* value = sep + 1;
while (*value && isspace(*value)) value++;
// 去除末尾换行符
char* end = value;
while (*end && *end != '\n') end++;
*end = '\0';
info_.brand = value;
break;
}
}
}
fclose(fp);
}
#elif ALICHO_PLATFORM_APPLE
// iOS/macOS ARM (Apple Silicon)
info_.vendor = "Apple";
info_.brand = "Apple Silicon";
// 获取物理核心数通过sysctl
int nm[2];
size_t len = 4;
uint32_t count;
sysctlbyname("hw.physicalcpu", &count, &len, NULL, 0);
if (count > 0) {
info_.physical_cores = static_cast<int>(count);
}
#else
// 其他ARM平台
info_.vendor = "ARM";
info_.brand = "Unknown ARM Processor";
#endif
// 获取物理核心数Linux/Unix
#if ALICHO_PLATFORM_LINUX && !ALICHO_PLATFORM_ANDROID
// 尝试使用sysconf
info_.physical_cores = static_cast<int>(sysconf(_SC_NPROCESSORS_CONF));
#endif
}
#endif // ALICHO_PLATFORM_ARM
SIMDLevel CPUFeatureDetector::recommended_simd_level() const noexcept {
// 根据检测到的SIMD别返回推荐使用的级别
// 这可能会考虑性能、兼容性和微架构因素
// 基本策略使用最高可用级别但对于AVX-512要考虑热降频问题
switch (info_.max_simd_level) {
case SIMDLevel::AVX512:
// 某些CPU在使用AVX-512时会降频
// 在实际应用中可能需要更复杂的检测和决策
// 例如根据CPU型号或运行时测试决定是否使用AVX-512
#if ALICHO_PLATFORM_WINDOWS
// Windows平台上特别慎使用AVX-512
if (info_.vendor.find("Intel") != std::string::npos &&
(info_.brand.find("Xeon") != std::string::npos ||
info_.brand.find("i9") != std::string::npos)) {
return SIMDLevel::AVX512; // 高端Intel CPU上使用AVX-512
}
#endif
if (info_.vendor.find("AMD") != std::string::npos) {
return SIMDLevel::AVX512; // 所有AMD CPU上使用AVX-512
}
return SIMDLevel::AVX2; // 默认情况下返回AVX2
case SIMDLevel::AVX2:
case SIMDLevel::AVX:
case SIMDLevel::SSE4:
case SIMDLevel::SSE3:
case SIMDLevel::SSE:
case SIMDLevel::NEON:
case SIMDLevel::NEON_FP16:
return info_.max_simd_level; // 直接使用最高支持级别
default:
case SIMDLevel::NONE:
return SIMDLevel::NONE;
}
}
void CPUFeatureDetector::print_info() const {
std::cout << "CPU信息:" << std::endl;
#if ALICHO_PLATFORM_WINDOWS
std::cout << " 平台: Windows" << std::endl;
#elif ALICHO_PLATFORM_MACOS
std::cout << " 平台: macOS" << std::endl;
#elif ALICHO_PLATFORM_LINUX
std::cout << " 平台: Linux" << std::endl;
#elif ALICHO_PLATFORM_ANDROID
std::cout << " 平台: Android" << std::endl;
#elif ALICHO_PLATFORM_IOS
std::cout << " 平台: iOS" << std::endl;
#else
std::cout << " 平台: 未知" << std::endl;
#endif
std::cout << " 厂商: " << info_.vendor << std::endl;
std::cout << " 型号: " << info_.brand << std::endl;
std::cout << " 逻辑核心数: " << info_.logical_cores << std::endl;
std::cout << " 物理核心数: " << info_.physical_cores << std::endl;
std::cout << " 最高SIMD级别: ";
switch (info_.max_simd_level) {
case SIMDLevel::NONE: std::cout << "None (标量)"; break;
case SIMDLevel::SSE: std::cout << "SSE/SSE2"; break;
case SIMDLevel::SSE3: std::cout << "SSE3/SSSE3"; break;
case SIMDLevel::SSE4: std::cout << "SSE4.1/SSE4.2"; break;
case SIMDLevel::AVX: std::cout << "AVX"; break;
case SIMDLevel::AVX2: std::cout << "AVX2"; break;
case SIMDLevel::AVX512: std::cout << "AVX-512"; break;
case SIMDLevel::NEON: std::cout << "NEON"; break;
case SIMDLevel::NEON_FP16: std::cout << "NEON (FP16)"; break;
}
std::cout << std::endl;
std::cout << " 推荐SIMD级别: ";
switch (recommended_simd_level()) {
case SIMDLevel::NONE: std::cout << "None (标量)"; break;
case SIMDLevel::SSE: std::cout << "SSE/SSE2"; break;
case SIMDLevel::SSE3: std::cout << "SSE3/SSSE3"; break;
case SIMDLevel::SSE4: std::cout << "SSE4.1/SSE4.2"; break;
case SIMDLevel::AVX: std::cout << "AVX"; break;
case SIMDLevel::AVX2: std::cout << "AVX2"; break;
case SIMDLevel::AVX512: std::cout << "AVX-512"; break;
case SIMDLevel::NEON: std::cout << "NEON"; break;
case SIMDLevel::NEON_FP16: std::cout << "NEON (FP16)"; break;
}
std::cout << std::endl;
std::cout << " 支持的特性: " << info_.features_string() << std::endl;
}
} // namespace audio_backend::simd

178
src/simd/cpu_features.h Normal file
View File

@@ -0,0 +1,178 @@
// ================================================================================================
// Audio Backend - SIMD CPU特性检测器
// ================================================================================================
// 描述: 运行时检测CPU支持的SIMD指令集
// 支持: SSE/AVX/AVX2/AVX-512/NEON
// ================================================================================================
#pragma once
#include <cstdint>
#include <string>
#include <array>
namespace audio_backend::simd {
// ================================================================================================
// CPU特性标志
// ================================================================================================
enum class CPUFeature : uint32_t {
// x86/x64 SIMD特性
SSE = 1 << 0,
SSE2 = 1 << 1,
SSE3 = 1 << 2,
SSSE3 = 1 << 3,
SSE41 = 1 << 4,
SSE42 = 1 << 5,
AVX = 1 << 6,
AVX2 = 1 << 7,
FMA = 1 << 8,
AVX512F = 1 << 9,
AVX512VL = 1 << 10,
AVX512BW = 1 << 11,
AVX512DQ = 1 << 12,
// ARM NEON特性
NEON = 1 << 20,
NEON_FP16 = 1 << 21,
// 其他特性
POPCNT = 1 << 30,
BMI1 = 1 << 31
};
// 位运算支持
inline CPUFeature operator|(CPUFeature lhs, CPUFeature rhs) {
return static_cast<CPUFeature>(
static_cast<uint32_t>(lhs) | static_cast<uint32_t>(rhs)
);
}
inline CPUFeature operator&(CPUFeature lhs, CPUFeature rhs) {
return static_cast<CPUFeature>(
static_cast<uint32_t>(lhs) & static_cast<uint32_t>(rhs)
);
}
inline bool has_feature(CPUFeature features, CPUFeature test) {
return (static_cast<uint32_t>(features) & static_cast<uint32_t>(test)) != 0;
}
// ================================================================================================
// SIMD指令集级别
// ================================================================================================
enum class SIMDLevel {
NONE, // 无SIMD支持纯标量
SSE, // SSE/SSE2
SSE3, // SSE3/SSSE3
SSE4, // SSE4.1/SSE4.2
AVX, // AVX
AVX2, // AVX2 + FMA
AVX512, // AVX-512
NEON, // ARM NEON
NEON_FP16 // ARM NEON with FP16
};
// ================================================================================================
// CPU信息结构
// ================================================================================================
struct CPUInfo {
std::string vendor; // CPU厂商
std::string brand; // CPU品牌字符串
uint32_t features; // 支持的特性位掩码
SIMDLevel max_simd_level; // 支持的最高SIMD级别
int logical_cores; // 逻辑核心数
int physical_cores; // 物理核心数
// 检查是否支持特定特性
[[nodiscard]] bool supports(CPUFeature feature) const noexcept {
return (features & static_cast<uint32_t>(feature)) != 0;
}
// 获取人类可读的特性字符串
[[nodiscard]] std::string features_string() const;
};
// ================================================================================================
// CPU特性检测器单例模式
// ================================================================================================
class CPUFeatureDetector {
public:
// 获取单例实例
static CPUFeatureDetector& instance() {
static CPUFeatureDetector detector;
return detector;
}
// 禁止拷贝和移动
CPUFeatureDetector(const CPUFeatureDetector&) = delete;
CPUFeatureDetector& operator=(const CPUFeatureDetector&) = delete;
CPUFeatureDetector(CPUFeatureDetector&&) = delete;
CPUFeatureDetector& operator=(CPUFeatureDetector&&) = delete;
// 获取CPU信息
[[nodiscard]] const CPUInfo& cpu_info() const noexcept { return info_; }
// 便捷方法
[[nodiscard]] bool supports(CPUFeature feature) const noexcept {
return info_.supports(feature);
}
[[nodiscard]] SIMDLevel max_simd_level() const noexcept {
return info_.max_simd_level;
}
// 检查是否至少支持某个SIMD级别
[[nodiscard]] bool supports_at_least(SIMDLevel level) const noexcept {
return info_.max_simd_level >= level;
}
// 获取推荐的SIMD级别考虑性能和兼容性
[[nodiscard]] SIMDLevel recommended_simd_level() const noexcept;
// 打印CPU信息
void print_info() const;
private:
CPUFeatureDetector();
~CPUFeatureDetector() = default;
// 检测函数
void detect_features();
void detect_x86_features();
void detect_arm_features();
// x86 CPUID支持
#if defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || defined(_M_IX86)
struct CPUIDResult {
uint32_t eax, ebx, ecx, edx;
};
static CPUIDResult cpuid(uint32_t function_id, uint32_t subfunction_id = 0);
static void get_vendor_string(char* vendor_string);
static void get_brand_string(char* brand_string);
#endif
CPUInfo info_;
};
// ================================================================================================
// 全局便捷函数
// ================================================================================================
inline const CPUInfo& get_cpu_info() {
return CPUFeatureDetector::instance().cpu_info();
}
inline bool cpu_supports(CPUFeature feature) {
return CPUFeatureDetector::instance().supports(feature);
}
inline SIMDLevel get_max_simd_level() {
return CPUFeatureDetector::instance().max_simd_level();
}
inline SIMDLevel get_recommended_simd_level() {
return CPUFeatureDetector::instance().recommended_simd_level();
}
} // namespace audio_backend::simd

View File

@@ -0,0 +1,120 @@
// ================================================================================================
// Audio Backend - SIMD函数分发器实现
// ================================================================================================
#include "function_dispatcher.h"
#include <iostream>
namespace audio_backend::simd {
// ================================================================================================
// 函数版本字符串转换实现
// ================================================================================================
const char* function_version_to_string(FunctionVersion version) {
switch (version) {
case FunctionVersion::SCALAR: return "SCALAR";
case FunctionVersion::SSE: return "SSE";
case FunctionVersion::SSE3: return "SSE3";
case FunctionVersion::SSE4: return "SSE4";
case FunctionVersion::AVX: return "AVX";
case FunctionVersion::AVX2: return "AVX2";
case FunctionVersion::AVX512: return "AVX512";
case FunctionVersion::NEON: return "NEON";
case FunctionVersion::NEON_FP16: return "NEON_FP16";
default: return "UNKNOWN";
}
}
FunctionVersion string_to_function_version(const std::string& str) {
if (str == "SCALAR") return FunctionVersion::SCALAR;
if (str == "SSE") return FunctionVersion::SSE;
if (str == "SSE3") return FunctionVersion::SSE3;
if (str == "SSE4") return FunctionVersion::SSE4;
if (str == "AVX") return FunctionVersion::AVX;
if (str == "AVX2") return FunctionVersion::AVX2;
if (str == "AVX512") return FunctionVersion::AVX512;
if (str == "NEON") return FunctionVersion::NEON;
if (str == "NEON_FP16") return FunctionVersion::NEON_FP16;
return FunctionVersion::SCALAR; // 默认回退到标量版本
}
// ================================================================================================
// FunctionDispatcher实现
// ================================================================================================
void FunctionDispatcher::print_registry_status() const {
std::cout << "\n=== SIMD函数注册状态 ===" << std::endl;
std::cout << "已注册函数数量: " << function_registry_.size() << std::endl;
// 获取当前CPU支持的最高SIMD级别
SIMDLevel max_level = get_max_simd_level();
SIMDLevel recommended_level = get_recommended_simd_level();
std::cout << "CPU最高SIMD级别: ";
switch (max_level) {
case SIMDLevel::NONE: std::cout << "None"; break;
case SIMDLevel::SSE: std::cout << "SSE"; break;
case SIMDLevel::SSE3: std::cout << "SSE3"; break;
case SIMDLevel::SSE4: std::cout << "SSE4"; break;
case SIMDLevel::AVX: std::cout << "AVX"; break;
case SIMDLevel::AVX2: std::cout << "AVX2"; break;
case SIMDLevel::AVX512: std::cout << "AVX-512"; break;
case SIMDLevel::NEON: std::cout << "NEON"; break;
case SIMDLevel::NEON_FP16: std::cout << "NEON_FP16"; break;
}
std::cout << std::endl;
std::cout << "推荐SIMD级别: ";
switch (recommended_level) {
case SIMDLevel::NONE: std::cout << "None"; break;
case SIMDLevel::SSE: std::cout << "SSE"; break;
case SIMDLevel::SSE3: std::cout << "SSE3"; break;
case SIMDLevel::SSE4: std::cout << "SSE4"; break;
case SIMDLevel::AVX: std::cout << "AVX"; break;
case SIMDLevel::AVX2: std::cout << "AVX2"; break;
case SIMDLevel::AVX512: std::cout << "AVX-512"; break;
case SIMDLevel::NEON: std::cout << "NEON"; break;
case SIMDLevel::NEON_FP16: std::cout << "NEON_FP16"; break;
}
std::cout << std::endl;
std::cout << "\n函数详情:" << std::endl;
for (const auto& pair : function_registry_) {
const std::string& name = pair.first;
const auto& holder = pair.second;
std::cout << " " << name << ":" << std::endl;
// 获取可用版本
auto available_versions = holder->get_available_versions();
if (available_versions.empty()) {
std::cout << " ❌ 无可用实现" << std::endl;
} else {
std::cout << " ✅ 可用版本: ";
for (size_t i = 0; i < available_versions.size(); ++i) {
if (i > 0) std::cout << ", ";
std::cout << function_version_to_string(available_versions[i]);
}
std::cout << std::endl;
// 显示将使用的版本
FunctionVersion preferred_version = simd_level_to_version(recommended_level);
FunctionVersion selected_version = FunctionVersion::SCALAR;
// 查找最佳匹配版本
for (int i = static_cast<int>(preferred_version); i >= 0; --i) {
FunctionVersion version = static_cast<FunctionVersion>(i);
auto it = std::find(available_versions.begin(), available_versions.end(), version);
if (it != available_versions.end()) {
selected_version = version;
break;
}
}
std::cout << " 🎯 将使用版本: " << function_version_to_string(selected_version) << std::endl;
}
}
std::cout << "=========================" << std::endl;
}
} // namespace audio_backend::simd

View File

@@ -0,0 +1,264 @@
// ================================================================================================
// Audio Backend - SIMD函数分发器
// ================================================================================================
// 描述: 运行时自动选择最优SIMD实现的函数分发器
// 功能: 根据CPU特性动态选择最佳的函数实现版本
// ================================================================================================
#pragma once
#include "cpu_features.h"
#include <functional>
#include <array>
#include <unordered_map>
#include <memory>
namespace audio_backend::simd {
// ================================================================================================
// 函数实现版本枚举
// ================================================================================================
enum class FunctionVersion {
SCALAR = 0, // 标量实现(默认回退)
SSE, // SSE实现
SSE3, // SSE3实现
SSE4, // SSE4实现
AVX, // AVX实现
AVX2, // AVX2实现
AVX512, // AVX-512实现
NEON, // ARM NEON实现
NEON_FP16, // ARM NEON FP16实现
VERSION_COUNT // 版本数量(用于数组大小)
};
// 将SIMD级别转换为函数版本
constexpr FunctionVersion simd_level_to_version(SIMDLevel level) {
switch (level) {
case SIMDLevel::NONE: return FunctionVersion::SCALAR;
case SIMDLevel::SSE: return FunctionVersion::SSE;
case SIMDLevel::SSE3: return FunctionVersion::SSE3;
case SIMDLevel::SSE4: return FunctionVersion::SSE4;
case SIMDLevel::AVX: return FunctionVersion::AVX;
case SIMDLevel::AVX2: return FunctionVersion::AVX2;
case SIMDLevel::AVX512: return FunctionVersion::AVX512;
case SIMDLevel::NEON: return FunctionVersion::NEON;
case SIMDLevel::NEON_FP16: return FunctionVersion::NEON_FP16;
default: return FunctionVersion::SCALAR;
}
}
// ================================================================================================
// 多版本函数持有者模板
// ================================================================================================
template<typename FuncSignature>
class MultiVersionFunction;
template<typename ReturnType, typename... Args>
class MultiVersionFunction<ReturnType(Args...)> {
public:
using FunctionType = std::function<ReturnType(Args...)>;
using FunctionArray = std::array<FunctionType, static_cast<size_t>(FunctionVersion::VERSION_COUNT)>;
MultiVersionFunction() = default;
// 注册函数版本
void register_version(FunctionVersion version, FunctionType function) {
functions_[static_cast<size_t>(version)] = std::move(function);
}
// 获取最佳函数版本
const FunctionType& get_best_function() const {
// 获取推荐的SIMD级别
SIMDLevel recommended_level = get_recommended_simd_level();
FunctionVersion preferred_version = simd_level_to_version(recommended_level);
// 从首选版本开始,向下查找可用实现
for (int i = static_cast<int>(preferred_version); i >= 0; --i) {
FunctionVersion version = static_cast<FunctionVersion>(i);
const auto& func = functions_[static_cast<size_t>(version)];
if (func) {
return func;
}
}
// 如果没有找到任何实现,返回空函数
static const FunctionType empty_func;
return empty_func;
}
// 调用最佳函数版本
ReturnType operator()(Args... args) const {
const auto& func = get_best_function();
if (func) {
return func(args...);
} else {
// 没有可用实现时的错误处理
throw std::runtime_error("No suitable function implementation available");
}
}
// 检查是否有任何版本的实现
bool has_implementation() const {
for (const auto& func : functions_) {
if (func) return true;
}
return false;
}
// 获取可用版本列表
std::vector<FunctionVersion> get_available_versions() const {
std::vector<FunctionVersion> versions;
for (size_t i = 0; i < functions_.size(); ++i) {
if (functions_[i]) {
versions.push_back(static_cast<FunctionVersion>(i));
}
}
return versions;
}
private:
FunctionArray functions_{};
};
// ================================================================================================
// 函数分发器注册器(单例模式)
// ================================================================================================
class FunctionDispatcher {
public:
// 获取单例实例
static FunctionDispatcher& instance() {
static FunctionDispatcher dispatcher;
return dispatcher;
}
// 禁止拷贝和移动
FunctionDispatcher(const FunctionDispatcher&) = delete;
FunctionDispatcher& operator=(const FunctionDispatcher&) = delete;
FunctionDispatcher(FunctionDispatcher&&) = delete;
FunctionDispatcher& operator=(FunctionDispatcher&&) = delete;
// 注册函数(通过函数名)
template<typename FuncSignature>
void register_function(const std::string& name,
FunctionVersion version,
std::function<FuncSignature> function) {
auto& func_holder = get_or_create_function<FuncSignature>(name);
func_holder.register_version(version, std::move(function));
}
// 获取函数
template<typename FuncSignature>
const MultiVersionFunction<FuncSignature>& get_function(const std::string& name) {
auto& func_holder = get_or_create_function<FuncSignature>(name);
return func_holder;
}
// 调用函数(便捷方法)
template<typename FuncSignature, typename... Args>
auto call_function(const std::string& name, Args&&... args)
-> decltype(std::declval<std::function<FuncSignature>>()(args...)) {
const auto& func = get_function<FuncSignature>(name);
return func(std::forward<Args>(args)...);
}
// 列出所有已注册的函数
std::vector<std::string> list_functions() const {
std::vector<std::string> names;
for (const auto& pair : function_registry_) {
names.push_back(pair.first);
}
return names;
}
// 打印函数注册状态
void print_registry_status() const;
private:
FunctionDispatcher() = default;
~FunctionDispatcher() = default;
// 类型擦除的基类
struct FunctionHolderBase {
virtual ~FunctionHolderBase() = default;
virtual std::vector<FunctionVersion> get_available_versions() const = 0;
virtual bool has_implementation() const = 0;
};
// 具体的函数持有者
template<typename FuncSignature>
struct FunctionHolder : public FunctionHolderBase {
MultiVersionFunction<FuncSignature> function;
std::vector<FunctionVersion> get_available_versions() const override {
return function.get_available_versions();
}
bool has_implementation() const override {
return function.has_implementation();
}
};
// 获取或创建函数持有者
template<typename FuncSignature>
MultiVersionFunction<FuncSignature>& get_or_create_function(const std::string& name) {
auto it = function_registry_.find(name);
if (it == function_registry_.end()) {
auto holder = std::make_unique<FunctionHolder<FuncSignature>>();
auto* raw_holder = holder.get();
function_registry_[name] = std::move(holder);
return raw_holder->function;
} else {
auto* holder = dynamic_cast<FunctionHolder<FuncSignature>*>(it->second.get());
if (!holder) {
throw std::runtime_error("Function signature mismatch for: " + name);
}
return holder->function;
}
}
std::unordered_map<std::string, std::unique_ptr<FunctionHolderBase>> function_registry_;
};
// ================================================================================================
// 便捷宏定义
// ================================================================================================
// 注册函数版本的宏
#define REGISTER_SIMD_FUNCTION(name, version, function) \
audio_backend::simd::FunctionDispatcher::instance().register_function<decltype(function)>(name, version, function)
// 获取函数的宏
#define GET_SIMD_FUNCTION(signature, name) \
audio_backend::simd::FunctionDispatcher::instance().get_function<signature>(name)
// 调用函数的宏
#define CALL_SIMD_FUNCTION(signature, name, ...) \
audio_backend::simd::FunctionDispatcher::instance().call_function<signature>(name, __VA_ARGS__)
// ================================================================================================
// 自动注册辅助类
// ================================================================================================
template<typename FuncSignature>
class AutoRegister {
public:
AutoRegister(const std::string& name,
FunctionVersion version,
std::function<FuncSignature> function) {
FunctionDispatcher::instance().register_function<FuncSignature>(
name, version, std::move(function));
}
};
// 自动注册宏
#define AUTO_REGISTER_SIMD_FUNCTION(name, version, function) \
static auto _auto_reg_##name##_##version = \
audio_backend::simd::AutoRegister<decltype(function)>(#name, version, function)
// ================================================================================================
// 函数版本字符串转换
// ================================================================================================
const char* function_version_to_string(FunctionVersion version);
FunctionVersion string_to_function_version(const std::string& str);
} // namespace audio_backend::simd

181
tests/CMakeLists.txt Normal file
View File

@@ -0,0 +1,181 @@
# ================================================================================================
# Audio Backend Framework - 测试配置
# ================================================================================================
# 描述: 配置单元测试和集成测试
# 框架: Google Test (GTest)
# 类型: 单元测试、集成测试、性能测试
# ================================================================================================
message(STATUS "")
message(STATUS "=== 配置测试模块 ===")
# ================================================================================================
# 测试相关的全局配置
# ================================================================================================
# 启用测试框架
enable_testing()
# 设置测试输出目录
set(TEST_OUTPUT_DIR ${CMAKE_BINARY_DIR}/tests)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${TEST_OUTPUT_DIR})
# ================================================================================================
# 查找测试依赖
# ================================================================================================
find_package(GTest REQUIRED)
# 检查benchmark库是否可用
set(BENCHMARK_AVAILABLE FALSE)
if(TARGET benchmark::benchmark AND DAW_ENABLE_BENCHMARKS)
set(BENCHMARK_AVAILABLE TRUE)
endif()
# ================================================================================================
# 公共测试配置接口库
# ================================================================================================
add_library(audio_backend_test_common INTERFACE)
# 设置测试公共包含路径
target_include_directories(audio_backend_test_common INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_SOURCE_DIR}/src
)
# 链接测试依赖
target_link_libraries(audio_backend_test_common INTERFACE
${audio_backend_project_options}
AudioBackend::Common
AudioBackend::Communication
AudioBackend::Engine
GTest::gtest
GTest::gtest_main
${THREADS_LIB}
)
# 测试特定编译定义
target_compile_definitions(audio_backend_test_common INTERFACE
GTEST_HAS_PTHREAD=1
$<$<CONFIG:Debug>:AUDIO_BACKEND_TEST_DEBUG>
)
# 设置操作系统定义
add_os_definitions(audio_backend_test_common)
# ================================================================================================
# 单元测试配置
# ================================================================================================
message(STATUS "配置单元测试...")
# 自动收集单元测试源文件
set(UNIT_TEST_SOURCES "")
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/unit)
retrieve_files(${CMAKE_CURRENT_SOURCE_DIR}/unit UNIT_TEST_SOURCES)
endif()
if(UNIT_TEST_SOURCES)
# 创建单元测试可执行文件
add_executable(audio_backend_unit_tests ${UNIT_TEST_SOURCES})
# 链接依赖
target_link_libraries(audio_backend_unit_tests PRIVATE
audio_backend_test_common
AudioBackend::SIMD
AudioBackend::PluginHost
AudioBackend::Frontend
)
# 添加测试到CTest
add_test(NAME UnitTests COMMAND audio_backend_unit_tests)
# 设置测试属性
set_tests_properties(UnitTests PROPERTIES
TIMEOUT 300 # 5分钟超时
LABELS "unit"
)
message(STATUS "✓ 单元测试配置完成: ${UNIT_TEST_SOURCES}个件")
else()
message(STATUS "○ 单元测试: 无测试文件")
endif()
# ================================================================================================
# 集成测试配置
# ================================================================================================
message(STATUS "配置集成测试...")
# 自动收集集成测试源文件
set(INTEGRATION_TEST_SOURCES "")
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/integration)
retrieve_files(${CMAKE_CURRENT_SOURCE_DIR}/integration INTEGRATION_TEST_SOURCES)
endif()
if(INTEGRATION_TEST_SOURCES)
# 创建集成测试可执行文件
add_executable(audio_backend_integration_tests ${INTEGRATION_TEST_SOURCES})
# 链接依赖
target_link_libraries(audio_backend_integration_tests PRIVATE
audio_backend_test_common
AudioBackend::SIMD
AudioBackend::PluginHost
AudioBackend::Frontend
)
# 添加测试到CTest
add_test(NAME IntegrationTests COMMAND audio_backend_integration_tests)
# 设置测试属性
set_tests_properties(IntegrationTests PROPERTIES
TIMEOUT 600 # 10分钟超时
LABELS "integration"
)
message(STATUS "✓ 集成测试配置完成: ${INTEGRATION_TEST_SOURCES}个文件")
else()
message(STATUS "○ 集成测试: 无测试文件")
endif()
# ================================================================================================
# 性能基准测试配置
# ================================================================================================
if(BENCHMARK_AVAILABLE)
message(STATUS "配置性能基准测试...")
# 自动收集基准测试源文件
set(BENCHMARK_SOURCES "")
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/benchmarks)
retrieve_files(${CMAKE_CURRENT_SOURCE_DIR}/benchmarks BENCHMARK_SOURCES)
endif()
if(BENCHMARK_SOURCES)
# 创建基准测试可执行文件
add_executable(audio_backend_benchmarks ${BENCHMARK_SOURCES})
# 链接依赖
target_link_libraries(audio_backend_benchmarks PRIVATE
audio_backend_test_common
AudioBackend::SIMD
AudioBackend::Engine
benchmark::benchmark
)
# 添加基准测试不加入CTest手动运行
message(STATUS "✓ 性能基准测试配置完成: ${BENCHMARK_SOURCES}个文件")
else()
message(STATUS "○ 性能基准测试: 无测试文件")
endif()
else()
message(STATUS "○ 性能基准测试: benchmark库不可用或被禁用")
endif()
# ================================================================================================
# 测试配置摘要
# ================================================================================================
message(STATUS "")
message(STATUS "=== 测试配置摘要 ===")
message(STATUS "测试框架: Google Test")
message(STATUS "单元测试: ${UNIT_TEST_SOURCES}个文件")
message(STATUS "集成测试: ${INTEGRATION_TEST_SOURCES}个文件")
message(STATUS "性能测试: ${BENCHMARK_AVAILABLE}")
message(STATUS "测试输出: ${TEST_OUTPUT_DIR}")
message(STATUS "")