# ttplayer-cpp **Repository Path**: hpc2h2/ttplayer-cpp ## Basic Information - **Project Name**: ttplayer-cpp - **Description**: 将 @jthhpcqy 用PyQt5写的千千静听 ttplayer 移植到C++ Qt6.8.2 中。初步加了频谱显示功能。 - **Primary Language**: C - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-09-20 - **Last Updated**: 2026-09-12 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # TTPlayer (C++ / Qt 6) [English](#english) | [中文](#中文) ![TTPlayer Screenshot](screenshot.png) ## English ### Introduction TTPlayer is a lightweight music player developed with Qt 6 and C++. This project is a port of the original [TTPlayer](https://github.com/jthhpcqy/ttplayer) which was developed using PyQt5. The goal is to improve performance and provide a native application experience while maintaining the classic **千千静听** UI. ### Screenshots #### Default Skin (Purple) ![Default Purple Skin](t3.png) #### Skin Switching (Drag & Drop `.skn` file) Supports loading original 千千静听 skin packages at runtime — simply drag any `.skn` file onto the player window: | XP Style | HiFi 31 Digital | Classic Gray | Retro Radio | |:---:|:---:|:---:|:---:| | ![XP Skin](t4.png) | ![HiFi Skin](t5.png) | ![Gray Skin](t6.png) | ![Radio Skin](t7.png) | > **Note**: The original 千千静听 UI for comparison: > > ![Original 千千静听](t2.png) ### Features - Clean and modern UI (supports custom `.skn` skins via drag-and-drop) - Playlist management with auto-loop - Drag and drop support for adding music files (.mp3, .wav, .flac, .ogg, .m4a, .aac) - Lyrics display (.lrc format) with fade animation - **Real-time audio spectrum visualization** — 41-bar log-frequency spectrum with A-weighting, spatial smoothing, EMA temporal smoothing, and peak indicators - Volume control - Keyboard shortcuts for playback control - Progress bar seeking with synchronized spectrum position - Window opacity animation effects ### Known Issues / TODO - **Text overflow on some skins**: When using certain skins (e.g., the Radio skin in screenshot `t7.png`), status text such as *"已切换皮肤:..."* can exceed the visible area and get clipped or garbled. This is because label geometry is currently hardcoded for the default Purple skin layout; dynamic skin-aware label sizing has not yet been implemented. - Further UI adaptation work needed: button alignment, font scaling, and element positioning vary across different skin packages. ### Requirements - Qt 6.x (macOS verified with Qt 6.11.2; the Windows helper script targets Qt 6.10.3) - CMake 3.16 or higher - MinGW or MSVC compiler with C++17 support - zlib (required by the `.skn` skin parser) - Qt Multimedia is required on macOS and other non-Windows platforms - Qt Multimedia is optional on Windows; when unavailable, the player uses the native `waveOut` backend > **Build status**: The macOS arm64 build has been verified locally. The Windows build path is included, but still needs to be validated on a Windows machine. ### Building from Source ```bash # Clone the repository git clone https://github.com/HPC2H2/ttplayer-cpp.git cd ttplayer-cpp # On Windows, first update the Qt/tool paths in _rebuild.bat if necessary, # then run it from a Qt/MinGW command prompt. _rebuild.bat ``` Or manually: ```powershell # Windows (Qt 6 + MinGW/Ninja; adjust the Qt path for your installation) cmake -S . -B build -G Ninja -DCMAKE_PREFIX_PATH=C:/Qt/6.10.3/mingw_64 cmake --build build --parallel build\TTPlayer.exe ``` ```bash # macOS (Homebrew Qt) cmake -S . -B build -G Ninja -DCMAKE_PREFIX_PATH=/opt/homebrew -DCMAKE_BUILD_TYPE=Release cmake --build build --parallel ./build/TTPlayer ``` For a generic CMake/Ninja setup: ```bash cmake -S . -B build -G Ninja cmake --build build --parallel ``` ### Usage After building, run `build/TTPlayer.exe` on Windows or `./build/TTPlayer` on macOS. Drag MP3 files onto the player window to start playing, or drag `.skn` skin files to change the appearance. #### Keyboard Shortcuts | Key | Action | |-----|--------| | Space | Play / Pause | | Up Arrow | Increase volume (+15%) | | Down Arrow | Decrease volume (-15%) | ### Architecture ``` ┌────────────┐ ┌──────────────────┐ │ MP3 file │────▶│ Audio backend │ │ │────▶│ QMediaPlayer / │ └─────┬──────┘ │ Windows waveOut │ │ └──────────────────┘ ▼ ┌───────────────┐ ┌────────────────┐ │ MP3Decoder │────▶│ SpectrumBars │ │ (minimp3) │ │ (FFT + Render)│ └──────┬────────┘ └────────────────┘ ▼ ┌───────────────┐ │ Custom FFT │ │ (fft.h,1024pt)│ └───────────────┘ ``` - **Audio backend**: Uses Qt Multimedia where available; Windows can fall back to native `waveOut` output. - **MP3Decoder**: Background thread decoding MP3 via [minimp3](https://github.com/lieff/minimp3), downmixes multi-channel PCM for analysis, and computes FFT spectrum in real time. - **SpectrumBars**: Receives FFT data through a callback and applies: 1. Sample-rate-aware log-frequency band mapping (up to 41 bars) 2. FFT normalization with partial A-weighting compensation 3. Dynamic 85th-percentile auto-scaling with EMA stabilization 4. Square-root dynamic-range compression 5. Spatial smoothing with kernel `[1,2,3,2,1]` 6. Faster EMA temporal smoothing and peak decay indicators - **SkinEngine**: Parses `.skn` skin packages (BMP images + XML config), supports dynamic skin switching at runtime via drag-and-drop. Falls back to built-in Purple default skin when no external skin is loaded. - **PlayList**: Manages playback queue, handles auto-loop (next song on EndOfMedia) ### Project Structure ``` ttplayer-cpp/ ├── src/ # Source code │ ├── mainwindow.cpp/h # Main window (UI construction, skin switching, drag & drop) │ ├── spectrumbars.cpp/h # Spectrum visualization (FFT + rendering) │ ├── mp3decoder.cpp/h # MP3 decode thread (minimp3) │ ├── fft.h # Self-implemented FFT (1024 points) │ ├── playlist.cpp/h # Playlist management │ ├── skinengine.cpp/h # Skin engine (.skn parsing and loading) │ ├── skinparser.cpp/h # Skin XML config parser │ ├── imageslider.cpp/h # Custom image slider │ └── fadinglabel.cpp/h # Fade-in/out lyric label ├── skin/ # Built-in default Purple skin resources ├── Designer_ui/ # Qt Designer UI files ├── tools/ # Helper scripts ├── 【千千静听 Skin】皮肤 ★/ # Original 千千静听 skin package collection ├── CMakeLists.txt # CMake build configuration └── _rebuild.bat # One-click build script ``` ### About This Project This project is a learning exercise that recreates the interface and functionality of the classic Chinese music player "千千静听" (TTPlayer) using modern technologies. The original TTPlayer was developed by Zheng Nanling. This C++ version is a port of the Python implementation by [jthhpcqy](https://github.com/jthhpcqy/ttplayer). ### Changelog - **2026-09-12**: - Improved spectrum rendering with stereo downmixing, RMS frequency bands, dynamic auto-scaling, and updated bar layout. - Added compatibility with original SKN `Visual.xml` attributes, including `SpectrumWide`. - Made audio backends platform-specific: Qt Multimedia on macOS, with a native `waveOut` fallback on Windows. - Updated build documentation for Windows and macOS. - Verified on **MacBook Air (Apple M4, 10-core CPU, 16 GB)** running **macOS 26.6.2 arm64**: Release build, application startup, and local MP3 decoding passed. - Windows build path is included but has not yet been verified on a Windows machine. - **2026-06-27**: - Full rewrite of the spectrum visualization (AudioSpectrum-style algorithm: log-frequency mapping, A-weighting, spatial/temporal smoothing). - Fixed spectrum stutter during looped playback (stop the old decode thread on `sourceChanged`). - Replaced kissFFT with a self-implemented FFT (`fft.h`, 1024 points). - Added SkinEngine: drag-and-drop `.skn` skins, including support for original 千千静听 skin packages. - Fixed UI glitches and crashes caused by duplicate button creation (nullptr initialization + idempotent guards in the constructor). - Aligned the UI with the original 千千静听 (removed the redundant always-on-top button, shifted the top-right three buttons). - Added screenshots, project structure, and known issues to the README. - **2025-08-13**: Added the spectrum display, based on minimp3 + kissFFT for MP3 decoding and FFT analysis. - **2025-08-xx**: Ported from the PyQt5 version to Qt 6.8.2 / C++17. ### Disclaimer All copyrights belong to the original authors. This project is for educational purposes only. ### Acknowledgements - Original TTPlayer (千千静听) by Zheng Nanling - Python implementation [TTPlayer](https://github.com/jthhpcqy/ttplayer) by jthhpcqy - Qt framework - [MiniMP3](https://github.com/lieff/minimp3) - Lightweight MP3 decoder - [AudioSpectrum](https://github.com/potato04/AudioSpectrum) - Spectrum visualization algorithm reference - [Spectralizer](https://github.com/univrsal/spectralizer) - Spectrum processing reference --- ## 中文 ### 简介 TTPlayer 是一款使用 Qt 6 和 C++ 开发的轻量级音乐播放器。本项目是原始 [TTPlayer](https://github.com/jthhpcqy/ttplayer)(使用 PyQt5 开发)的 C++ 移植版本,在保持经典千千静听界面风格的同时提供原生性能体验。 ### 截图展示 #### 默认皮肤(Purple) ![默认 Purple 皮肤](t3.png) #### 换肤功能(拖放 `.skn` 文件即可切换) 支持在运行时加载原版千千静听皮肤包 —— 将任意 `.skn` 文件拖放到播放器窗口即可: | XP 风格 | HiFi 31 数字风 | 经典灰 | 复古收音机 | |:---:|:---:|:---:|:---:| | ![XP 皮肤](t4.png) | ![HiFi 皮肤](t5.png) | ![灰色皮肤](t6.png) | ![收音机皮肤](t7.png) | > **附:原版千千静听界面对照** > > ![原版千千静听](t2.png) ### 功能特点 - 简洁现代的 UI(支持拖放 `.skn` 皮肤文件动态换肤) - 播放列表管理,支持自动循环播放 - 拖放添加音乐文件(.mp3、.wav、.flac、.ogg、.m4a、.aac) - 歌词显示(.lrc 格式),带淡入淡出动画 - **实时频谱可视化** — 41 柱对数频率分布,A 计权感知加权,空间卷积平滑,EMA 帧间平滑,峰值指示器 - 音量控制滑块 - 键盘快捷键控制播放 - 进度条拖拽定位,频谱位置同步跟随 - 窗口透明度动画效果 ### 已知问题 / 待改进 - **部分皮肤存在文字溢出**:在使用某些皮肤时(如截图 `t7.png` 的收音机皮肤),状态文字(如 *"已切换皮肤:..."*)可能超出可见区域,出现截断或乱码。这是因为当前标签几何尺寸为默认 Purple 皮肤硬编码,尚未实现根据不同皮肤包动态调整标签大小与位置的功能。 - 其他 UI 适配工作待完善:按钮对齐、字体缩放、元素布局在不同皮肤包间存在差异。 ### 系统要求 - Qt 6.x(macOS 已使用 Qt 6.11.2 验证;Windows 一键脚本当前以 Qt 6.10.3 为目标) - CMake 3.16 或更高版本 - 支持 C++17 的编译器(MinGW / MSVC) - zlib(`.skn` 皮肤解析器需要) - macOS 及其他非 Windows 平台必须安装 Qt Multimedia - Windows 平台可选 Qt Multimedia;未安装时使用 Windows 原生 `waveOut` 音频后端 > **构建状态**:macOS arm64 已在本机验证通过。Windows 构建路径已经保留,但仍需要在 Windows 机器上实际验证。 ### 从源代码构建 ```bash # 克隆仓库 git clone https://github.com/HPC2H2/ttplayer-cpp.git cd ttplayer-cpp # Windows 下请先根据本机环境修改 _rebuild.bat 中的 Qt、CMake、Ninja 路径, # 然后在 Qt/MinGW 命令提示符中运行 _rebuild.bat ``` 或手动构建: ```powershell # Windows(Qt 6 + MinGW/Ninja;请按实际安装位置修改 Qt 路径) cmake -S . -B build -G Ninja -DCMAKE_PREFIX_PATH=C:/Qt/6.10.3/mingw_64 cmake --build build --parallel build\TTPlayer.exe ``` ```bash # macOS(Homebrew Qt) cmake -S . -B build -G Ninja -DCMAKE_PREFIX_PATH=/opt/homebrew -DCMAKE_BUILD_TYPE=Release cmake --build build --parallel ./build/TTPlayer ``` 通用 CMake/Ninja 构建: ```bash cmake -S . -B build -G Ninja cmake --build build --parallel ``` ### 使用方法 构建完成后,Windows 运行 `build\TTPlayer.exe`,macOS 运行 `./build/TTPlayer`。将 MP3 文件拖放到窗口即可开始播放;将 `.skn` 皮肤文件拖放到窗口即可切换外观。 #### 键盘快捷键 | 按键 | 功能 | |------|------| | 空格键 | 播放 / 暂停 | | 上箭头 | 音量 +15% | | 下箭头 | 音量 -15% | ### 技术架构 ``` ┌────────────┐ ┌──────────────────┐ │ MP3 文件 │────▶│ 音频后端 │ │ │────▶│ QMediaPlayer / │ └─────┬──────┘ │ Windows waveOut │ │ └──────────────────┘ ▼ ┌───────────────┐ ┌────────────────┐ │ MP3Decoder │────▶│ SpectrumBars │ │ (minimp3解码)│ │ (FFT+渲染) │ └──────┬────────┘ └────────────────┘ ▼ ┌───────────────┐ │ 自定义 FFT │ │ (fft.h,1024点)│ └───────────────┘ ``` - **音频后端**:优先使用 Qt Multimedia;Windows 在没有该模块时回退到原生 `waveOut` 输出。 - **MP3Decoder**:后台线程通过 [minimp3](https://github.com/lieff/minimp3) 解码 MP3,多声道 PCM 混音后实时计算 FFT 频谱。 - **SpectrumBars**:通过回调接收 FFT 数据,处理流程包括: 1. 根据采样率计算对数频率映射(最多 41 根柱子) 2. FFT 归一化与部分 A 计权补偿 3. 基于 85% 分位数的动态自动缩放,并使用 EMA 稳定 4. 开平方动态范围压缩 5. 空间卷积平滑(核 `[1,2,3,2,1]`) 6. 更快的 EMA 帧间平滑与峰值衰减指示器 - **SkinEngine**:解析 `.skn` 皮肤包(BMP 图片 + XML 配置),运行时通过拖放动态换肤;无外部皮肤时回退内置 Purple 默认皮肤 - **PlayList**:管理播放队列,EndOfMedia 时自动切下一首 ### 项目结构 ``` ttplayer-cpp/ ├── src/ # 源代码 │ ├── mainwindow.cpp/h # 主窗口(UI构建、换肤、拖放) │ ├── spectrumbars.cpp/h # 频谱可视化(FFT + 渲染) │ ├── mp3decoder.cpp/h # MP3解码线程(minimp3) │ ├── fft.h # 自实现 FFT(1024点) │ ├── playlist.cpp/h # 播放列表管理 │ ├── skinengine.cpp/h # 皮肤引擎(.skn 解析与加载) │ ├── skinparser.cpp/h # 皮肤 XML 配置解析 │ ├── imageslider.cpp/h # 自定义图片滑块 │ └── fadinglabel.cpp/h # 淡入淡出歌词标签 ├── skin/ # 内置默认 Purple 皮肤资源 ├── Designer_ui/ # Qt Designer UI 文件 ├── tools/ # 辅助工具脚本 ├── 【千千静听 Skin】皮肤 ★/ # 原版千千静听皮肤包集合 ├── CMakeLists.txt # CMake 构建配置 └── _rebuild.bat # 一键构建脚本 ``` ### 关于本项目 本项目是一个学习性质的项目,使用现代技术重新实现经典中文音乐播放器"千千静听"(TTPlayer)的界面与功能。原始千千静听由郑南岭先生开发。 这个 C++ 版本是对 [jthhpcqy](https://github.com/jthhpcqy/ttplayer) 的 Python 实现的移植。 ### 更新日志 - **2026-09-12**: - 改进频谱显示:加入立体声混音、RMS 频带分析、动态自动缩放和新的柱状布局。 - 增强原版 SKN `Visual.xml` 属性兼容性,支持 `SpectrumWide` 等配置。 - 按平台选择音频后端:macOS 使用 Qt Multimedia,Windows 提供原生 `waveOut` 后备实现。 - 更新 Windows 与 macOS 构建说明。 - 已在 **MacBook Air(Apple M4,10 核 CPU,16 GB)**、**macOS 26.6.2 arm64** 环境通过 Release 构建、程序启动和本地 MP3 解码验证。 - Windows 构建路径已保留,但尚未在 Windows 设备上实机验证。 - **2026-06-27**: - 频谱可视化完整重写(AudioSpectrum 风格算法:对数频率映射、A计权、空间/时间平滑) - 修复循环播放时频谱卡顿(sourceChanged 时停旧解码线程) - 替换 kissFFT 为自研 FFT 实现(fft.h, 1024 点) - 新增 SkinEngine:拖放 `.skn` 文件动态换肤,支持原版千千静听皮肤包 - 修复按钮重复创建导致的 UI 异常与闪退(构造函数补全 nullptr 初始化 + 幂等保护) - UI 对齐原版千千静听(移除多余置顶按钮,右上角三按钮右移) - README 补充截图展示、项目结构、已知问题记录 - **2025-08-13**: 引入频谱显示功能,基于 minimp3 + kissFFT 实现 MP3 解码和 FFT 频谱分析 - **2025-08-xx**: 从 PyQt5 版本移植到 Qt 6.8.2 / C++17 ### 免责声明 所有版权归原作者所有。本项目仅供学习用途。 ### 致谢 - 原始千千静听由郑南岭先生开发 - Python 版本 [TTPlayer](https://github.com/jthhpcqy/ttplayer) 由 jthhpcqy 开发 - Qt 框架 - [MiniMP3](https://github.com/lieff/minimp3) - 轻量级 MP3 解码库 - [AudioSpectrum](https://github.com/potato04/AudioSpectrum) - 频谱可视化算法参考 - [Spectralizer](https://github.com/univrsal/spectralizer) - 频谱处理参考