feat: cài đặt giao diện và tích hợp AI Analysis engine
This commit is contained in:
+132
@@ -0,0 +1,132 @@
|
||||
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 và định dạng các công thức toán học LaTeX:
|
||||
|
||||
# Đặc Tả Kỹ Thuật: Hành Động Chọn Vùng & Cơ Chế Phát Lặp (Solo vs. Master Loop)
|
||||
|
||||
Tài liệu này đặc tả cơ chế tương tác chuột và logic phát âm thanh tương ứng đối với hai vùng chọn: Chọn cục bộ trên Track (*Local Selection*) và Chọn toàn cục trên Timeline (*Global Selection*) dựa trên thiết kế chuẩn DAW trong hình `image_dfffa3.png`.
|
||||
|
||||
Mục tiêu là cung cấp thuật toán xử lý sự kiện chuột (`MouseEvent`) để lập trình viên chuyển đổi (*port*) trực tiếp sang Python (ví dụ sử dụng `QGraphicsView` hoặc `QWidget` tùy biến trong PyQt6/PySide6).
|
||||
|
||||
---
|
||||
|
||||
## 1. Bản Vẽ Phân Cấp Vùng Tương Tác (Layout Hitboxes)
|
||||
|
||||
Dựa trên hình `image_dfffa3.png`, khu vực biên tập bên phải được phân chia thành 2 hitbox tương tác chuột chính yếu:
|
||||
|
||||
```text
|
||||
+-------------------------------------------------------------------------+
|
||||
| [VÙNG A] TIMELINE RULER (Thước đo thời gian trên cùng - Mũi tên đỏ chỉ) |
|
||||
+-------------------------------------------------------------------------+
|
||||
| [VÙNG B] CÁC LÀN TRACK LANE (Xếp chồng dọc) |
|
||||
| - Track 01 Waveform Area (Hitbox cục bộ 1) |
|
||||
| - Track 02 Waveform Area (Hitbox cục bộ 2) |
|
||||
| - Track 03 Waveform Area (Hitbox cục bộ 3) |
|
||||
+-------------------------------------------------------------------------+
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Đặc Tả Tương Tác 1: Chọn Cục Bộ & Phát Lặp Độc Lập (Local Track Selection & Solo Loop)
|
||||
|
||||
### 2.1. Hành động người dùng (User Action)
|
||||
|
||||
* **Click chuột đơn (Mouse Press):** Người dùng nhấp chuột vào một điểm bất kỳ trên dạng sóng của một track (Ví dụ: Track 01).
|
||||
* *Hệ quả:* Track đó lập tức được highlight (*Active State*), các track khác chuyển sang trạng thái chờ.
|
||||
|
||||
|
||||
* **Kéo chuột (Mouse Drag):** Click và nhấn giữ chuột, kéo sang trái hoặc phải trên phần hiển thị sóng âm của track đó.
|
||||
* *Hệ quả:* Tạo ra một vùng chọn thời gian giới hạn bởi điểm nhấn đầu và điểm thả chuột cuối.
|
||||
|
||||
|
||||
|
||||
### 2.2. Cơ chế phát lặp (Loop Playback Logic)
|
||||
|
||||
* **Chế độ phát:** Khi nhấn nút *Play Loop*, hệ thống chỉ phát lặp duy nhất đoạn nhạc nằm trong vùng chọn của track đang active.
|
||||
* **Xử lý Audio Engine ở Python:**
|
||||
* Tự động kích hoạt cơ chế Mute tạm thời cho tất cả các track khác, hoặc kích hoạt nhanh chế độ Solo cho track đang active trong luồng phát âm thanh.
|
||||
* Giới hạn mốc thời gian phát trong khoảng $T_{\text{start}}$ đến $T_{\text{end}}$. Khi kim phát phát chạm $T_{\text{end}}$, nhảy ngay lập tức về $T_{\text{start}}$ mà không dừng phát các luồng khác (nếu có).
|
||||
|
||||
|
||||
|
||||
### 2.3. Ánh xạ mã sự kiện Python (PyQt6 / PySide6 Concept)
|
||||
|
||||
```python
|
||||
# Giả lập xử lý sự kiện trong lớp TrackWaveformWidget(QWidget)
|
||||
|
||||
def mousePressEvent(self, event):
|
||||
if event.button() == Qt.MouseButton.LeftButton:
|
||||
# 1. Kích hoạt chọn track hiện hành
|
||||
self.parent_session.set_active_track(self.track_id)
|
||||
# 2. Ghi nhận điểm mốc thời gian bắt đầu
|
||||
self.drag_start_time = self.pixel_to_time(event.position().x())
|
||||
self.is_dragging = True
|
||||
|
||||
def mouseMoveEvent(self, event):
|
||||
if self.is_dragging:
|
||||
current_time = self.pixel_to_time(event.position().x())
|
||||
# Cập nhật vùng chọn cục bộ (Local Selection Range)
|
||||
self.parent_session.update_local_selection(
|
||||
track_id=self.track_id,
|
||||
start=min(self.drag_start_time, current_time),
|
||||
end=max(self.drag_start_time, current_time)
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Đặc Tả Tương Tác 2: Chọn Toàn Cục & Phát Lặp Đa Kênh (Global Timeline Selection & Master Loop)
|
||||
|
||||
### 3.1. Hành động người dùng (User Action)
|
||||
|
||||
* **Định vị:** Di chuyển con trỏ chuột lên trên cùng, vào thanh chứa Timeline Ruler (Vị trí mũi tên màu đỏ trong hình `image_dfffa3.png`).
|
||||
* **Kéo chuột (Mouse Drag):** Click chuột vào thanh Ruler và kéo sang trái/phải.
|
||||
* *Hệ quả:* Một khung màu cam nhạt (*Selection Overlay*) xuất hiện và kéo dọc toàn bộ chiều cao màn hình xuyên qua tất cả các track từ trên xuống dưới (như hiển thị thực tế trong hình `image_dfffa3.png`).
|
||||
|
||||
|
||||
|
||||
### 3.2. Cơ chế phát lặp (Loop Playback Logic)
|
||||
|
||||
* **Chế độ phát:** Khi nhấn nút *Play Loop*, hệ thống sẽ phát đồng thời tất cả các track (*Master Playback*) nhưng giới hạn vòng lặp đồng bộ chỉ nằm trong dải thời gian được bôi màu.
|
||||
* **Xử lý Audio Engine ở Python:**
|
||||
* Giữ nguyên trạng thái Mute/Solo hiện tại của các track (không tự động tắt tiếng các track khác).
|
||||
* Đồng bộ hóa pha của tất cả các luồng phát. Khi Playhead chạm mốc kết thúc vùng chọn $T_{\text{end}}$, toàn bộ các nguồn phát (*Audio Sources*) đang hoạt động đều phải nhảy đồng bộ về vị trí $T_{\text{start}}$.
|
||||
|
||||
|
||||
|
||||
### 3.3. Ánh xạ mã sự kiện Python (PyQt6 / PySide6 Concept)
|
||||
|
||||
```python
|
||||
# Giả lập xử lý sự kiện trong lớp TimelineRulerWidget(QWidget)
|
||||
|
||||
def mousePressEvent(self, event):
|
||||
if event.button() == Qt.MouseButton.LeftButton:
|
||||
# Ghi nhận mốc thời gian toàn cục ban đầu
|
||||
self.global_drag_start = self.pixel_to_time(event.position().x())
|
||||
self.is_dragging_global = True
|
||||
# Hủy bỏ các vùng chọn cục bộ (nếu có) để ưu tiên chế độ chọn tổng thể
|
||||
self.parent_session.clear_all_local_selections()
|
||||
|
||||
def mouseMoveEvent(self, event):
|
||||
if self.is_dragging_global:
|
||||
current_time = self.pixel_to_time(event.position().x())
|
||||
# Cập nhật vùng chọn toàn cục xuyên suốt tất cả các làn track
|
||||
self.parent_session.set_global_selection(
|
||||
start=min(self.global_drag_start, current_time),
|
||||
end=max(self.global_drag_start, current_time)
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Tóm Tắt Sự Khác Biệt Giữa 2 Trạng Trạng Thái
|
||||
|
||||
Để đảm bảo hệ thống không bị xung đột khi xử lý đa luồng âm thanh trên Python Docker, bộ điều phối âm thanh (*Audio Coordinator*) cần tuân thủ bảng logic sau:
|
||||
|
||||
| Thuộc tính | Tương tác trên Track (Local) | Tương tác trên Ruler (Global) |
|
||||
| --- | --- | --- |
|
||||
| **Phạm vi hiển thị vùng chọn** | Chỉ hiển thị hoặc sáng rõ tại track đang active. | Kéo dài thẳng đứng, phủ qua tất cả các track (như hình `image_dfffa3.png`). |
|
||||
| **Phạm vi phát âm thanh** | **Solo Playback:** Chỉ phát duy nhất âm thanh của track được chọn. | **Master Playback:** Phát tất cả các track cùng lúc (không tự động Solo/Mute). |
|
||||
| **Điểm lặp (Loop Target)** | $T_{\text{start}} \rightarrow T_{\text{end}}$ của riêng track hoạt động. | $T_{\text{start}} \rightarrow T_{\text{end}}$ toàn cục đồng bộ tất cả các track. |
|
||||
| **Phục vụ AI Cut** | Chỉ cắt tệp tin của riêng track được chọn để đưa sang track mới. | Cho phép render/mixdown gộp tất cả các track trong dải chọn thành tệp mới. |
|
||||
Reference in New Issue
Block a user