Dưới đây là toàn bộ nội dung tài liệu đặc tả kỹ thuật đã được chuyển đổi sang định dạng Markdown chuẩn, tối ưu hóa các khối mã nguồn (`python`, `text`), căn chỉnh bảng biểu, sơ đồ luồng ASCII và các công thức toán học dạng LaTeX:

# Đặc Tả Kỹ Thuật: Biên Tập Cục Bộ, Cơ Chế Tab Tạm Thời & Hoàn Tác (Undo/Redo)

Tài liệu này phân tích chi tiết cơ chế tương tác đồ họa và xử lý tín hiệu âm thanh dựa trên giao diện DAW chuẩn hóa trong hình `image_e076cb.png`. Mục tiêu là cung cấp tài liệu thiết kế hệ thống và giải thuật để port trực tiếp sang ứng dụng Python chạy trên Docker.

---

## 1. Phân Tích Trạng Thái Track Hoạt Động (Active Track State) & Khung Vùng Chọn Cục Bộ

Dựa trên hình `image_e076cb.png`, hệ thống sử dụng cơ chế *Local Waveform Selection* (Chọn vùng cục bộ trên từng kênh) thay vì phủ bóng toàn bộ các kênh trên dòng thời gian.

### 1.1. Trạng thái Track Active

* **Hành động:** Khi người dùng click chuột vào vùng hiển thị của một Track (ví dụ: Track 1), hệ thống sẽ gán trạng thái `ACTIVE` cho track đó.
* **Hiển thị hình ảnh:**
* Nền của Track active sẽ chuyển sang màu xám sáng (`#2a2a2a` hoặc `#333333`), trong khi các track không active ở trạng thái chờ với màu tối hơn (`#181818`).
* Toàn bộ đường viền quanh track được highlight nhẹ bằng một viền sáng mờ.



### 1.2. Khung Chọn Cục Bộ (Local Selection Highlight)

* **Quy luật hiển thị:** Khung màu sáng (Overlay màu xám bạc trong hình `image_e076cb.png`) chỉ được vẽ đè lên dạng sóng (Waveform) của riêng track đang active, giới hạn trục ngang từ $T_{\text{start}}$ đến $T_{\text{end}}$.
* **Ràng buộc đồ họa:** Các track nằm dưới (ví dụ: Track 2) sẽ hoàn toàn không bị phủ bóng xám, dù nằm cùng khoảng thời gian $T_{\text{start}} \rightarrow T_{\text{end}}$.

> **Khai báo an toàn khi Port sang Python (Tránh Crash):**
> * Luôn kiểm tra tính hợp lệ của mốc thời gian: $0 \le T_{\text{start}} < T_{\text{end}} \le T_{\text{max}}$.
> * Chặn lỗi vượt quá giới hạn mảng mẫu (*Index Out of Bounds*) khi ánh xạ từ Pixel sang mẫu âm thanh số:
> 
> 
> $$\text{Sample}_{\text{start}} = \text{clamp}(0, \lfloor T_{\text{start}} \times \text{Sample Rate} \rfloor, \text{Total Samples})$$
> 
> 

---

## 2. Quy Trình Biên Tập Trong Tab Tạm Thời (Temporary Edit Tab Workflow)

Đây là tính năng biên tập không phá hủy (*Non-destructive*) nâng cao, cho phép cô lập phân đoạn âm thanh để xử lý chuyên sâu trước khi gộp lại vào bản phối chính.

```text
[Bản Phối Chính] ──► Chọn đoạn (T_start -> T_end) ──► Nhấn "Edit in Temp Tab"
                                                               │
  ┌────────────────────────────────────────────────────────────┘
  ▼
[Khởi tạo Tab Tạm Thời] 
  ├── Trích xuất mảng mẫu phụ (Audio Sub-segment Buffer)
  ├── Hiển thị dạng sóng cô lập (Thời gian chạy từ 0 đến T_duration)
  ├── Người dùng thực hiện các hiệu ứng: Reverse, Gain, Pitch Shift, Fade...
  └── Nhấn "Áp dụng (Apply)"
        │
        ▼
[Hòa nhập lại Bản Phối]
  ├── Tính toán khớp Zero-crossing tại hai đầu biên ghép nối.
  ├── Áp dụng hiệu ứng mờ biên (Micro-crossfades) để chống tiếng Click/Pop.
  └── Thay thế mảng mẫu mới vào vị trí cũ và dọn dẹp Tab tạm.

```

### 2.1. Trích xuất sang Tab Tạm Thời (Export to Temporary Tab)

Khi người dùng chọn vùng trên Track Active và nhấn "Edit in Temp Tab", hệ thống sẽ tách đoạn âm thanh này thành một thực thể đệm độc lập (`Sub-segment AudioBuffer`).

* Một tab mới (Ví dụ: `Tab: sẤit tiá...n` trong hình `image_e076cb.png`) xuất hiện ngay phía trên dòng thời gian.
* Trong tab này, trục thời gian của Ruler sẽ được đặt lại (*Reset*) bắt đầu từ `00:00:00.000` cho đến độ dài của đoạn được cắt:

$$T_{\text{duration}} = T_{\text{end}} - T_{\text{start}}$$

### 2.2. Hòa nhập lại Track Chính (Apply & Merge Back)

Khi người dùng hoàn tất chỉnh sửa trên Tab tạm và nhấn *Apply*, hệ thống Python/Docker Backend thực hiện quy trình DSP ghép nối sau để tránh hiện tượng vấp âm (*Click/Pop*):

1. **Tìm điểm Zero-Crossing lân cận:** Hệ thống tự động dịch nhẹ mốc nối $T_{\text{start}}$ và $T_{\text{end}}$ một vài mẫu ($5 \rightarrow 10$ samples) để đảm bảo biên độ tại điểm ghép nối bằng $0$.
2. **Áp dụng Micro-Crossfade:** Tạo một cửa sổ chuyển tiếp cực ngắn ($w = 10\text{ ms}$) giữa file gốc và file sửa đổi tại điểm ráp nối để triệt tiêu hoàn toàn sự thay đổi đột ngột của pha:

$$\text{Final}_{\text{audio}}(t) = (1 - \alpha(t)) \cdot \text{Original}(t) + \alpha(t) \cdot \text{Edited}(t - T_{\text{start}})$$

*Trong đó:* $\alpha(t) = \frac{t - T_{\text{start}}}{w}$ với $T_{\text{start}} \le t \le T_{\text{start}} + w$.

---

## 3. Cơ Chế Đồng Bộ Hóa Con Trỏ Phát Nhạc (Playhead Tracking)

* **Hành vi tương tác:** Khi phát nhạc (*Play*), kim phát nhạc (*Playhead line* màu đỏ) phải di chuyển liên tục, mượt mà dọc theo trục ngang của dạng sóng.
* **Thuật toán đồng bộ hóa (Client-Server):**
* Tốc độ di chuyển của Playhead dựa trên thời gian thực tế của luồng phát âm thanh (`AudioContext.currentTime` ở Client hoặc đồng hồ xung của card âm thanh phía Server).
* Vị trí hoành độ $X$ (Pixel) của con trỏ tại thời điểm $t$ được tính bằng công thức:


$$X(t) = t \times \text{Zoom Level}$$


* **Khi Loop hoạt động:** Khi $t \ge T_{\text{end}}$, luồng âm thanh lập tức chuyển hướng phát về $T_{\text{start}}$, đồng thời biến thời gian hiển thị con trỏ được đặt lại ngay lập tức: $t = T_{\text{start}}$ mà không dừng luồng phần cứng.



---

## 4. Kiến Trúc Hoàn Tác & Làm Lại (Undo / Redo Engine: Ctrl-Z & Ctrl-Y)

Để đảm bảo hiệu năng tối ưu trên Docker Server (tránh việc lưu đi lưu lại các tệp tin WAV nặng hàng trăm Megabytes vào bộ nhớ), hệ thống sử dụng Kiến trúc Hoàn tác dựa trên Delta (*State Delta-based Undo/Redo*).

### 4.1. Cấu trúc lưu trữ lịch sử (History Stack Node)

Mỗi hành động của người dùng (Cắt, ghép, thay đổi volume, fade, chỉnh sửa trong tab tạm) được đóng gói thành một đối tượng `ActionNode`:

```python
import time

class ActionNode:
    def __init__(self, action_type: str, track_id: str):
        self.action_type = action_type  # 'SPLIT', 'VOLUME_CHANGE', 'TEMP_TAB_EDIT', etc.
        self.track_id = track_id
        self.timestamp = time.time()
        
        # Lưu thông tin delta để khôi phục thay vì lưu cả file nhạc
        self.before_state = {}  # Trạng thái trước khi sửa
        self.after_state = {}   # Trạng thái sau khi sửa

```

### 4.2. Logic Hoàn tác (Undo - `Ctrl + Z`)

Khi người dùng nhấn tổ hợp phím `Ctrl + Z`:

1. Lấy hành động mới nhất từ *Undo Stack*.
2. Thực thi hàm nghịch đảo của hành động đó để đưa track về trạng thái `before_state`.
3. Đẩy hành động này sang *Redo Stack* để có thể làm lại.
4. Vẽ lại dạng sóng trên Canvas tương ứng.

### 4.3. Logic Làm lại (Redo - `Ctrl + Y`)

Khi người dùng nhấn tổ hợp phím `Ctrl + Y`:

1. Lấy hành động mới nhất từ *Redo Stack*.
2. Áp dụng trạng thái `after_state` lên track đích.
3. Đẩy ngược hành động này về lại *Undo Stack*.
4. Cập nhật đồ họa hiển thị.

### 4.4. Quản lý bộ nhớ tối ưu (Garbage Collection)

* Giới hạn kích thước tối đa của Stack hoàn tác (Ví dụ: tối đa 30 hành động) để tránh tràn bộ nhớ RAM của Docker Container.
* Các đoạn âm thanh bị thay thế bởi thao tác chỉnh sửa sẽ được lưu trữ dưới dạng các tệp nhị phân tạm thời (`.tmp`) trong thư mục `/app/storage/temp/` và tự động dọn dẹp khi phiên làm việc (Session) kết thúc.