Files
SonicForgeStudio/md/4_SUB_EDITOR.md
T

182 lines
8.5 KiB
Markdown

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:
# Technical Specification: Sub-Tab Audio Clip Editor & DSP Operations
This document outlines the software engineering specification for the temporary isolated Sub-Tab Audio Clip Editor. It defines internal clipboard mechanics, DSP algorithms for selection-based operations, Context Menu structures, and main application menu shortcuts.
---
## 1. Clipboard & Cursor-Aligned Insertion Mechanics
The Sub-Tab workspace features an isolated, low-latency stereo/mono audio buffer. The editor tracks a local virtual playhead position $t_{\text{cursor}}$ and handles clipboard buffers using non-destructive splicing techniques.
```text
Local Timeline Buffer
+-------------------------------------------------------+
| Track Waveform Segment │ |
+-------------------------------┼-----------------------+
t_cursor (Insertion Point)
▼ [ PASTE TRIGGERED ]
+-------------------------------------------------------+
| Track Waveform Segment │ CLIPBOARD DATA │ |
+-------------------------------------------------------+
◄──────────────►
clip_duration
```
### 1.1. Cursor Paste Action
When a paste command is issued (either via Context Menu, Application Menu, or Hotkey):
* **Payload Extraction:** Retrieve the copied `AudioBufferSegment` from the system/application clipboard.
* **Splicing Boundary Calculations:** Slice the current active timeline buffer at $t_{\text{cursor}}$.
* **Re-allocation & Stitching:**
* Compute the new duration: $T_{\text{new}} = T_{\text{original}} + T_{\text{clipboard}}$.
* Allocate a new virtual audio array $Y_{\text{new}}$:
$$Y_{\text{new}}(t) = \begin{cases} Y_{\text{original}}(t) & 0 \le t < t_{\text{cursor}} \\ Y_{\text{clipboard}}(t - t_{\text{cursor}}) & t_{\text{cursor}} \le t < t_{\text{cursor}} + T_{\text{clipboard}} \\ Y_{\text{original}}(t - T_{\text{clipboard}}) & t_{\text{cursor}} + T_{\text{clipboard}} \le t \le T_{\text{new}} \end{cases}$$
* **Playhead Update:** Advance the active playhead $t_{\text{cursor}}$ immediately to $t_{\text{cursor}} + T_{\text{clipboard}}$.
---
## 2. Selection Context Menu & DSP Engine
Right-clicking inside a highlighted region $[T_{\text{start}}, T_{\text{end}}]$ of the Waveform Canvas triggers an overlay context menu containing the following DSP and editing commands.
```text
+---------------------------------------------+
| Selection: [ 01:02.100 - 01:05.400 ] |
+---------------------------------------------+
| Normalize Selection To Peak |
| Adjust Gain/Volume... |
| Adjust Panning (Stereo Balance)... |
| Fade In (Linear/Exponential) |
| Fade Out (Linear/Exponential) |
|---------------------------------------------|
| Cut Ctrl+X |
| Copy Ctrl+C |
| Paste Ctrl+V |
| Delete Selected Segment Del |
|---------------------------------------------|
| Loop Selection: [ ▲ ] [ 4 ] [ ▼ ] times |
+---------------------------------------------+
```
### 2.1. Normalize Selection
Scales the peak amplitude of the selected segment to a target ceiling $A_{\text{target}}$ (defaulting to $1.0$ or $0\text{ dBFS}$):
$$Y_{\text{norm}}(t) = Y(t) \cdot \frac{A_{\text{target}}}{\max_{u \in [T_{\text{start}}, T_{\text{end}}]} \vert{}Y(u)\vert{}} \quad \text{for } t \in [T_{\text{start}}, T_{\text{end}}]$$
### 2.2. Volume (Gain dB) Adjustment
Applies a static linear gain multiplier derived from user-specified decibel scaling values ($\Delta\text{dB}$):
$$G = 10^{\frac{\Delta\text{dB}}{20}}$$
$$Y_{\text{gained}}(t) = Y(t) \cdot G \quad \text{for } t \in [T_{\text{start}}, T_{\text{end}}]$$
### 2.3. Panning (Stereo Balance)
Applies a constant-power panning law across Left ($L$) and Right ($R$) channels based on the panning angle $\theta \in [0, \pi/2]$, where $\theta = \pi/4$ represents absolute center:
$$Y_L(t) = Y_{\text{mono}}(t) \cdot \cos(\theta), \quad Y_R(t) = Y_{\text{mono}}(t) \cdot \sin(\theta)$$
### 2.4. Fade-In and Fade-Out (Linear / Exponential)
* **Linear Fade-In Curve:**
$$f_{\text{in}}(t) = \frac{t - T_{\text{start}}}{T_{\text{end}} - T_{\text{start}}} \quad \text{for } t \in [T_{\text{start}}, T_{\text{end}}]$$
* **Linear Fade-Out Curve:**
$$f_{\text{out}}(t) = 1.0 - \frac{t - T_{\text{start}}}{T_{\text{end}} - T_{\text{start}}} \quad \text{for } t \in [T_{\text{start}}, T_{\text{end}}]$$
### 2.5. Delete, Cut, and Copy
* **Delete:** Erases the selected segment $[T_{\text{start}}, T_{\text{end}}]$ and shifts all subsequent samples leftward.
* **Cut:** Copies the selected samples to the clipboard, then executes the *Delete* routine.
* **Copy:** Writes the targeted buffer segment to the clip memory without modifying the timeline.
### 2.6. Segment Looping with Step Multiplier
Repeats the selected segment $[T_{\text{start}}, T_{\text{end}}]$ consecutively $N$ times. The menu provides a numeric spinner (Up/Down buttons) to adjust $N$:
1. Extract segment: $Y_{\text{segment}} = Y(t)$ for $t \in [T_{\text{start}}, T_{\text{end}}]$.
2. Compute new duration adjustment: $\Delta L = (N - 1) \cdot (T_{\text{end}} - T_{\text{start}})$.
3. Duplicate and insert $Y_{\text{segment}}$ array $N-1$ times directly after $T_{\text{end}}$.
---
## 3. Global Menu Bar & Keyboard Shortcut Matrix
All context-dependent sub-tab actions are mapped directly to the global Menu Bar at the top of the DAW window, as specified in `image_e0e462.png`.
```text
File Edit View Insert Track Options Actions Extensions Help
├── Normalize Selection [Ctrl+Alt+N]
├── Adjust Volume... [V]
├── Adjust Panning... [P]
├── Fade In [F]
├── Fade Out [G]
├── Cut [Ctrl+X]
├── Copy [Ctrl+C]
├── Paste [Ctrl+V]
├── Delete [Del]
└── Loop Clip... [Ctrl+L]
```
### 3.1. Keyboard Mapping Table
To maximize speed and accessibility, the system listens for global key event hooks within the Sub-Tab window focus:
| Action Command | Main Menu Category | Recommended Keyboard Shortcut | Python Event Trigger (`QKeyEvent`) |
| --- | --- | --- | --- |
| **Cut** | Edit -> Cut | `Ctrl + X` | `Qt.Key.Key_X` + `ControlModifier` |
| **Copy** | Edit -> Copy | `Ctrl + C` | `Qt.Key.Key_C` + `ControlModifier` |
| **Paste** | Edit -> Paste | `Ctrl + V` | `Qt.Key.Key_V` + `ControlModifier` |
| **Delete** | Edit -> Delete | `Del` / `Backspace` | `Qt.Key.Key_Delete` / `Key_Backspace` |
| **Normalize** | Actions -> Normalize | `Ctrl + Alt + N` | `Qt.Key.Key_N` + `ControlModifier` + `AltModifier` |
| **Fade In** | Actions -> Fade In | `F` | `Qt.Key.Key_F` |
| **Fade Out** | Actions -> Fade Out | `G` | `Qt.Key.Key_G` |
| **Loop Segment** | Actions -> Loop... | `Ctrl + L` | `Qt.Key.Key_L` + `ControlModifier` |
| **Adjust Volume** | Actions -> Gain... | `V` | `Qt.Key.Key_V` |
| **Adjust Panning** | Actions -> Panning... | `P` | `Qt.Key.Key_P` |
---
## 4. Python Implementation Notes for Docker Server Porting
When porting these sub-tab operations to your Python DSP engine (`core/audio_editor.py`), use NumPy slice vectors to perform non-destructive edits on waveforms:
```python
# Prototype helper for non-destructive volume adjustment in Python
import numpy as np
def apply_gain_on_segment(y: np.ndarray, sr: int, start_sec: float, end_sec: float, gain_db: float) -> np.ndarray:
"""
Applies gain in dB to a selected segment of a mono numpy audio array.
"""
# 1. Translate time coordinates securely with boundary checking
start_sample = max(0, int(start_sec * sr))
end_sample = min(len(y), int(end_sec * sr))
# 2. Convert dB value to linear multiplier
multiplier = 10.0 ** (gain_db / 20.0)
# 3. Create a deep copy and modify segment in-place
y_edited = np.copy(y)
y_edited[start_sample:end_sample] *= multiplier
return y_edited
```