382 lines
14 KiB
Markdown
382 lines
14 KiB
Markdown
# Hướng Dẫn Kiểm Thử SonicForge Studio
|
|
|
|
## ✅ Trạng Thái Hoàn Thành
|
|
|
|
### Đã Hoàn Thành
|
|
- ✅ **Cấu trúc thư mục** - Toàn bộ kiến trúc app/
|
|
- ✅ **Docker Configuration** - Dockerfile + docker-compose.yml
|
|
- ✅ **FastAPI Gateway** - main.py, config.py, API endpoints
|
|
- ✅ **Core DSP Engine** - analyzer.py, dsp_utils.py, audio_editor.py
|
|
- ✅ **Celery Workers** - worker.py với task definitions
|
|
- ✅ **Frontend UI** - index.html với đầy đủ Web Audio API
|
|
- ✅ **Python Syntax** - Tất cả files đã validate
|
|
|
|
### Tính Năng Đã Triển Khai
|
|
|
|
#### Frontend (index.html)
|
|
- 🌊 Waveform visualization với HTML5 Canvas
|
|
- ⏯️ Audio playback controls (Play/Pause/Stop)
|
|
- 🔊 Real-time volume control với gain node
|
|
- 📍 Marker system với drag & drop
|
|
- 🎯 Client-side Zero-Crossing detection
|
|
- 💾 WAV Encoder (8/16/24-bit PCM)
|
|
- 📤 File upload với progress tracking
|
|
- 📊 Real-time status logging
|
|
|
|
#### Backend API
|
|
- `POST /api/v1/audio/upload` - Upload audio files
|
|
- `GET /api/v1/audio/tasks/{task_id}` - Check task status
|
|
- `POST /api/v1/audio/edit` - Apply server-side editing
|
|
- `GET /api/v1/audio/download/{file_id}` - Download processed files
|
|
|
|
#### Core DSP Modules
|
|
- **analyzer.py** - Librosa BPM/Beat tracking với Dynamic Programming
|
|
- **dsp_utils.py** - Zero-crossing detection, Micro-fading
|
|
- **audio_editor.py** - Cut, Loop, Fade, Volume operations
|
|
|
|
## 🚀 Cách Chạy Hệ Thống
|
|
|
|
### Option 1: Docker (Khuyến Nghị)
|
|
|
|
```bash
|
|
# Build và khởi động tất cả services
|
|
docker compose up --build
|
|
|
|
# Chạy ở background
|
|
docker compose up -d --build
|
|
|
|
# Xem logs
|
|
docker compose logs -f
|
|
|
|
# Dừng services
|
|
docker compose down
|
|
```
|
|
|
|
Truy cập: **http://localhost:8000**
|
|
|
|
### Option 2: Local Development
|
|
|
|
```bash
|
|
# 1. Cài đặt Python dependencies
|
|
pip install -r requirements.txt
|
|
|
|
# 2. Khởi động Redis (terminal riêng)
|
|
redis-server
|
|
|
|
# 3. Khởi động FastAPI (terminal riêng)
|
|
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
|
|
|
|
# 4. Khởi động Celery Worker (terminal riêng)
|
|
celery -A app.tasks.worker.celery_app worker --loglevel=info
|
|
```
|
|
|
|
## 🧪 Kịch Bản Kiểm Thử
|
|
|
|
### Test 1: Basic Audio Loading
|
|
1. Mở http://localhost:8000
|
|
2. Click "Choose File" và chọn file audio (MP3/WAV)
|
|
3. File sẽ load và hiển thị waveform
|
|
4. Kiểm tra thời gian hiển thị đúng
|
|
|
|
### Test 2: Playback Controls
|
|
1. Load audio file
|
|
2. Click Play - audio phát
|
|
3. Click Pause - audio tạm dừng
|
|
4. Click Play lại - tiếp tục từ vị trí pause
|
|
5. Click Stop - reset về đầu
|
|
|
|
### Test 3: Volume Control
|
|
1. Load và play audio
|
|
2. Kéo slider Volume từ -20dB đến +20dB
|
|
3. Kiểm tra âm lượng thay đổi real-time
|
|
|
|
### Test 4: Server Upload & Analysis
|
|
1. Load audio file
|
|
2. Click "Upload to Server"
|
|
3. Đợi upload hoàn tất (hiển thị file_id)
|
|
4. Click "Analyze Audio"
|
|
5. Kiểm tra kết quả BPM, beats, bars
|
|
|
|
### Test 5: Zero-Crossing Detection
|
|
1. Load audio file với waveform hiển thị
|
|
2. Click "Add Marker" (tạo marker tại vị trí current time)
|
|
3. Click "Snap to Zero-Crossing"
|
|
4. Marker sẽ di chuyển đến điểm zero-crossing gần nhất
|
|
5. Kiểm tra status log để xem thời gian chính xác
|
|
|
|
### Test 6: Server-side Editing
|
|
1. Upload file lên server
|
|
2. Add 2 markers (start/end cut points)
|
|
3. Snap markers to zero-crossing
|
|
4. Điều chỉnh:
|
|
- Loop Count: 2
|
|
- Fade In: 500ms
|
|
- Fade Out: 500ms
|
|
- Volume: +3dB
|
|
5. Click "Apply Edit (Server)"
|
|
6. Đợi processing complete
|
|
7. Download file đã edit
|
|
|
|
### Test 7: WAV Export (Client-side)
|
|
1. Load audio file
|
|
2. Chọn bit depth (8/16/24-bit)
|
|
3. Click "Export WAV (Client)"
|
|
4. File sẽ download tự động
|
|
5. Mở file bằng audio player để kiểm tra
|
|
|
|
## 🎹 FluidSynth WASM Migration — Manual Test Plan
|
|
|
|
### Môi trường
|
|
- Mở DevTools Console (F12) → Tab Console (bật `Verbose` để thấy `[SonicSF]` logs)
|
|
- Tab Network: filter `fluidsynth`, `sf3`, `.wasm`
|
|
|
|
### Test A: FluidSynth WASM Load & Init
|
|
|
|
| Step | Action | Expected Result |
|
|
|------|--------|----------------|
|
|
| A1 | Mở http://localhost:8000 | Console: `[FluidSynth] Loaded from: https://cdn.jsdelivr.net/...` |
|
|
| A2 | Kiểm tra Network tab | `.wasm` file tải thành công (status 200) |
|
|
| A3 | Check window.__FluidSynthModuleFactory | `typeof window.__FluidSynthModuleFactory === 'function'` |
|
|
| A4 | Tương tác với app (click vào DAW) | Console: `[SonicSF] FluidSynth WASM Engine initialized.` |
|
|
| A5 | Kiểm tra AudioWorklet | Console: `Worklet reg success` hoặc check `audioWorklet` trong Application tab |
|
|
|
|
### Test B: SoundFont Loading
|
|
|
|
| Step | Action | Expected Result |
|
|
|------|--------|----------------|
|
|
| B1 | Mở Plugin Manager → tab SoundFont | Danh sách SoundFont hiển thị |
|
|
| B2 | Chọn 1 SoundFont instrument (vd: Piano) | Console: `[SonicSF] SoundFont loaded: <sfId>` |
|
|
| B3 | Kiểm tra Network tab | Request `download/<sfId>` status 200 |
|
|
| B4 | Chuyển đổi instrument khác (vd: Violin) | Console: `Bank Select + Program Change` (nếu cùng SF, không tải lại) |
|
|
| B5 | Load SoundFont có loop samples (vd: Tremolo Strings, Pad, Synth) | loadSoundFont success, không lỗi |
|
|
|
|
### Test C: Piano Roll Playback
|
|
|
|
| Step | Action | Expected Result |
|
|
|------|--------|----------------|
|
|
| C1 | Mở Piano Roll tab | Grid hiển thị notes |
|
|
| C2 | Click vào 1 note trên grid | Note phát ra → âm thanh giống nhạc cụ thật (không phải oscillator beep) |
|
|
| C3 | Click và kéo thả chuột trên grid → draw note mới | Âm thanh phát ngay lập tức |
|
|
| C4 | Scroll wheel trên piano roll notes | Các note scroll qua phát âm thanh preview |
|
|
| C5 | Vẽ note dài (full measure) | Note kéo dài đúng độ dài, không bị tắt giữa chừng |
|
|
|
|
### Test D: MIDI Keyboard (Virtual & Hardware)
|
|
|
|
| Step | Action | Expected Result |
|
|
|------|--------|----------------|
|
|
| D1 | Click vào phím đàn virtual (piano keybed) | Note phát ra = âm thanh instrument đúng |
|
|
| D2 | Kéo chuột ngang trên keybed | Các note phát liên tục, glide không bị stuck |
|
|
| D3 | Kết nối MIDI keyboard qua WebMIDI | Console: `MIDI access granted` |
|
|
| D4 | Nhấn phím trên MIDI keyboard | Note phát ra ngay, không delay |
|
|
| D5 | Nhả phím MIDI | Note tắt ngay (không stuck, không sustain dài) |
|
|
| D6 | Sustain pedal (CC 64) | Nhấn pedal → notes sustain; nhả → notes release |
|
|
| D7 | Pitch bend wheel | Cao độ thay đổi real-time |
|
|
| D8 | Modulation wheel (CC 1) | Âm thanh thay đổi (nếu instrument hỗ trợ) |
|
|
|
|
### Test E: Timeline Playback (MIDI Tracks)
|
|
|
|
| Step | Action | Expected Result |
|
|
|------|--------|----------------|
|
|
| E1 | Tạo track MIDI mới | Track được tạo |
|
|
| E2 | Gán SoundFont instrument cho track | Console log bank/program change |
|
|
| E3 | Thêm MIDI notes vào track, click Play | Notes phát đúng pitch, đúng thời điểm, đúng instrument |
|
|
| E4 | Click Pause → Play | Nhạc tiếp tục từ vị trí pause |
|
|
| E5 | Click Stop | Tất cả notes tắt ngay lập tức |
|
|
| E6 | Seek playhead → Play | Play từ vị trí mới, notes cũ tắt |
|
|
| E7 | Set loop region → Play | Loop playback hoạt động |
|
|
| E8 | Chuyển track instrument khác → Play | Âm thanh thay đổi theo instrument mới |
|
|
|
|
### Test F: Tremolo/Sustain/Loop Instrument Stress Test
|
|
|
|
| Step | Action | Expected Result |
|
|
|------|--------|----------------|
|
|
| F1 | Chọn Tremolo Strings (GM#44) | Load SF thành công |
|
|
| F2 | Play note → nhanh chóng NoteOff | **QUAN TRỌNG**: Note tắt ngay, không bị stuck loop |
|
|
| F3 | Play nhiều note liên tiếp (staccato) | Mỗi note tắt hẳn trước khi note kế phát |
|
|
| F4 | Chọn Saxophone (GM#65-67) | Load SF thành công |
|
|
| F5 | Play note giữ 3s → NoteOff | Saxophone release envelope chạy đúng, không stuck |
|
|
| F6 | Chọn Pad/Synth (GM#88-95) | Các instrument loop dài không bị stuck |
|
|
| F7 | Play 10+ notes cùng lúc → Stop All | Tất cả notes tắt ngay |
|
|
| F8 | **So sánh**: Test F1-F7 cũ: SpessaSynth bị stuck notes cần CC120+noteOn+post. FluidSynth WASM: chỉ cần noteOff thường. | FluidSynth handle loop Gen 54 đúng spec |
|
|
|
|
### Test G: Multi-SoundFont Switching
|
|
|
|
| Step | Action | Expected Result |
|
|
|------|--------|----------------|
|
|
| G1 | Load SoundFont A (vd: GeneralUser) | Handle ID log |
|
|
| G2 | Chuyển track sang instrument từ SF A | SF A active |
|
|
| G3 | Tạo track 2, load SoundFont B (vd: SGM) | SF B load vào MEMFS |
|
|
| G4 | Play track 1 (SF A) + track 2 (SF B) | Cả 2 soundfont phát đồng thời, mỗi track instrument đúng |
|
|
| G5 | Unload SF A, load SF C | SF A đã unload, SF C active |
|
|
|
|
### Test H: Transport Controls
|
|
|
|
| Step | Action | Expected Result |
|
|
|------|--------|----------------|
|
|
| H1 | Đang play → click Stop | Console: `FluidSynth: All notes stopped.` |
|
|
| H2 | Play với nhiều notes đang vang → Stop | Âm thanh tắt ngay lập tức (CC 120 all sound off) |
|
|
| H3 | Play → Pause → Seek → Play | Seek không bị stuck notes |
|
|
| H4 | Play → Reload trang | Audio context mới, FluidSynth init lại |
|
|
|
|
### Test I: Fallback Behavior
|
|
|
|
| Step | Action | Expected Result |
|
|
|------|--------|----------------|
|
|
| I1 | Chặn CDN request (DevTools → Network → Offline) | `fluidsynthLoader.js` detect localhost → vẫn dùng CDN? Set `window.__FLUIDSYNTH_CDN` = null |
|
|
| I2 | Nếu FluidSynth init fail | Console: `FluidSynth init failed`. Fallback oscillator hoạt động (âm beep) |
|
|
| I3 | Nếu loadSoundFont fail (network down) | Console: `SoundFont not found`. Fallback oscillator cho note preview |
|
|
|
|
### Test J: Memory & Performance
|
|
|
|
| Step | Action | Expected Result |
|
|
|------|--------|----------------|
|
|
| J1 | Load SF lần đầu | Network download + MEMFS write + sfload |
|
|
| J2 | Load lại SF lần 2 (đã cache IndexedDB) | `_sfHandleMap.has(sfId)` → true, skip download |
|
|
| J3 | Check Performance tab (DevTools) | `_fluid_synth_write_float` không block main thread > 5ms |
|
|
| J4 | Play liên tục 5 phút | Không memory leak, không audio glitch |
|
|
| J5 | Load SF 3-4MB (SGM v2.01) | MEMFS write + sfload < 500ms |
|
|
|
|
### Test K: Audio Parity (Client vs Server)
|
|
|
|
| Step | Action | Expected Result |
|
|
|------|--------|----------------|
|
|
| K1 | Tạo project với MIDI notes + SoundFont | Client preview âm thanh |
|
|
| K2 | Export WAV server-side (Render) | Server dùng pyfluidsynth (C++ core) |
|
|
| K3 | **So sánh** WAV export vs Client preview | Giống nhau 100% (cùng FluidSynth engine) |
|
|
| K4 | Test với SF3 files | Cả client (FluidSynth WASM) và server (pyfluidsynth) đều xử lý SF3 |
|
|
|
|
### Test L: Regression — Tính năng không thay đổi
|
|
|
|
| Step | Action | Expected Result |
|
|
|------|--------|----------------|
|
|
| L1 | AI track generation | `applyAITrackInstrument` works → bank/program change |
|
|
| L2 | Audio file playback | Không ảnh hưởng (vẫn dùng AudioEngine cũ) |
|
|
| L3 | VST instrument tracks | Không ảnh hưởng (dùng VST engine riêng) |
|
|
| L4 | Upload/download file | Không thay đổi |
|
|
| L5 | Multi-track mix | Không thay đổi |
|
|
|
|
### Test Environment Setup
|
|
|
|
```bash
|
|
# 1. Start server
|
|
cd /home/locpham/SonicForgeStudio
|
|
docker compose up -d --build
|
|
|
|
# 2. Clear browser cache trước khi test lần đầu (cache-bust version đã update)
|
|
# Chrome: DevTools → Network → Disable cache (khi DevTools mở)
|
|
|
|
# 3. Kiểm tra console logs
|
|
# Mở DevTools Console, filter: [SonicSF] [FluidSynth]
|
|
|
|
# 4. Force re-download SF (xóa IndexedDB cache nếu cần)
|
|
# Application → IndexedDB → DAW_SoundFont_Cache → Clear
|
|
```
|
|
|
|
### Checklist
|
|
|
|
- [ ] A1-A5: FluidSynth WASM load + init
|
|
- [ ] B1-B5: SoundFont load + switch (nhiều SF)
|
|
- [ ] C1-C5: Piano roll note play
|
|
- [ ] D1-D8: MIDI keyboard (virtual + hardware)
|
|
- [ ] E1-E8: Timeline playback
|
|
- [ ] F1-F8: **Tremolo/Sustain loop stress** — key test
|
|
- [ ] G1-G5: Multi-SoundFont switching
|
|
- [ ] H1-H4: Transport controls (stop, seek)
|
|
- [ ] I1-I3: Fallback oscillator
|
|
- [ ] J1-J5: Memory & performance
|
|
- [ ] K1-K4: Audio parity client vs server
|
|
- [ ] L1-L5: Regression (features không thay đổi)
|
|
|
|
## 🐛 Known Issues
|
|
|
|
### Docker Environment
|
|
- Module `celery`, `redis`, `librosa`, `pydub`, `soundfile` chưa được cài trong môi trường hiện tại
|
|
- **Giải pháp**: Sử dụng Docker để chạy (tất cả dependencies đã có trong Dockerfile)
|
|
|
|
### Browser Compatibility
|
|
- Web Audio API yêu cầu user interaction trước khi play
|
|
- Safari có thể cần format audio khác
|
|
- **Giải pháp**: Test trên Chrome/Firefox
|
|
|
|
## 📋 Checklist Kiểm Thử Đầy Đủ
|
|
|
|
- [ ] Docker build thành công
|
|
- [ ] Redis container chạy
|
|
- [ ] FastAPI web container chạy
|
|
- [ ] Celery worker container chạy
|
|
- [ ] Truy cập http://localhost:8000 thành công
|
|
- [ ] Load audio file và hiển thị waveform
|
|
- [ ] Play/Pause/Stop hoạt động
|
|
- [ ] Volume control real-time
|
|
- [ ] Upload file lên server
|
|
- [ ] Server analysis trả về BPM/beats
|
|
- [ ] Zero-crossing detection hoạt động
|
|
- [ ] Server editing hoàn tất
|
|
- [ ] Download file processed
|
|
- [ ] Export WAV client-side
|
|
- [ ] Kiểm tra không có audio glitch/pop
|
|
|
|
## 🔍 Debugging
|
|
|
|
### Kiểm tra logs
|
|
```bash
|
|
# Web server logs
|
|
docker compose logs web
|
|
|
|
# Celery worker logs
|
|
docker compose logs worker
|
|
|
|
# Redis logs
|
|
docker compose logs redis
|
|
|
|
# All services
|
|
docker compose logs -f
|
|
```
|
|
|
|
### Kiểm tra containers
|
|
```bash
|
|
# List containers
|
|
docker compose ps
|
|
|
|
# Enter container shell
|
|
docker compose exec web bash
|
|
docker compose exec worker bash
|
|
```
|
|
|
|
### Kiểm tra storage
|
|
```bash
|
|
# Uploaded files
|
|
ls -la app/storage/uploads/
|
|
|
|
# Processed files
|
|
ls -la app/storage/processed/
|
|
```
|
|
|
|
## 📊 Performance Metrics
|
|
|
|
### Mục Tiêu
|
|
- Upload file 10MB: < 5s
|
|
- BPM Analysis: < 10s
|
|
- Zero-crossing detection: < 100ms
|
|
- Waveform rendering: < 500ms
|
|
- Audio playback latency: < 50ms
|
|
|
|
## 🎯 Next Steps
|
|
|
|
Sau khi test cơ bản hoạt động:
|
|
1. Stress test với file > 100MB
|
|
2. Concurrent user testing
|
|
3. Memory leak detection
|
|
4. Audio quality testing (THD, SNR)
|
|
5. Cross-browser compatibility
|
|
6. Mobile responsive testing
|
|
|
|
## 📞 Support
|
|
|
|
Nếu gặp vấn đề, kiểm tra:
|
|
1. Docker daemon đang chạy
|
|
2. Port 8000, 6379 không bị chiếm
|
|
3. Đủ RAM (tối thiểu 4GB)
|
|
4. FFmpeg installed trong container
|
|
5. Browser console không có errors
|