# 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) | [中文](#中文)

## 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)

#### 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 |
|:---:|:---:|:---:|:---:|
|  |  |  |  |
> **Note**: The original 千千静听 UI for comparison:
>
> 
### 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)

#### 换肤功能(拖放 `.skn` 文件即可切换)
支持在运行时加载原版千千静听皮肤包 —— 将任意 `.skn` 文件拖放到播放器窗口即可:
| XP 风格 | HiFi 31 数字风 | 经典灰 | 复古收音机 |
|:---:|:---:|:---:|:---:|
|  |  |  |  |
> **附:原版千千静听界面对照**
>
> 
### 功能特点
- 简洁现代的 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) - 频谱处理参考