fcb_looper/interface_spec.md

248 lines
5.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# FCB1010 Looper Pedal - Interface Specification
## System Architecture Overview
```mermaid
graph TD
FCB1010[FCB1010 MIDI Controller]
UMC404HD[UMC404HD Audio Interface]
JACK_MIDI[JACK MIDI]
JACK_AUDIO[JACK Audio]
AudioEngine[Audio Engine Process]
Display[Display Process]
FCB1010 <-->|MIDI DIN| UMC404HD
UMC404HD <-->|MIDI USB| JACK_MIDI
UMC404HD <-->|Audio USB| JACK_AUDIO
JACK_MIDI -->|CC messages| AudioEngine
AudioEngine -->|MIDI Clock/Click| JACK_MIDI
JACK_AUDIO <-->|Audio Data| AudioEngine
AudioEngine -->|OSC Unix Socket| Display
subgraph "Hardware"
FCB1010
UMC404HD
end
subgraph "Software"
JACK_MIDI
JACK_AUDIO
AudioEngine
Display
end
```
## MIDI Interface
### Input: FCB1010 → Audio Engine
#### Button Mappings (State-Independent)
```
Button 1: CC #20 (Record/Arm / Tap Tempo)
Button 2: CC #21 (Play/Mute Track / Click Toggle)
Button 3: CC #22 (Solo Track)
Button 4: CC #23 (Overdub)
Button 5: CC #24 (Clear Track / Clear Column)
Button 6: CC #25 (Column 1 Select)
Button 7: CC #26 (Column 2 Select)
Button 8: CC #27 (Column 3 Select)
Button 9: CC #28 (Column 4 Select)
Button 10: CC #29 (Column 5 Select)
UP: CC #30 (Row Up / Mode Switch)
DOWN: CC #31 (Row Down / Mode Switch)
```
#### Expression Pedals
```
Expression A: CC #1 (Track Volume / Click Volume)
Expression B: CC #7 (Master Volume)
```
**Note**: FCB1010 sends identical CC messages regardless of current system state.
The Audio Engine interprets these based on its internal mode (Menu vs Performance).
### Output: Audio Engine → External Devices
#### MIDI Clock (Continuous)
```
Clock (F8H): 24 PPQN, sent continuously while application running
```
#### Transport Control
```
Start (FAH): When any column starts from all-stopped state
Stop (FCH): When all columns stop
```
#### Song Position Pointer
```
SPP (F2H): Reset to 0 on Start message
Increments during playback
Stops incrementing on Stop message
1 MIDI beat = 6 MIDI clocks = 1/4 quarter note
```
## OSC Interface (Audio Engine → Display)
### Transport: Unix Domain Socket
- **Protocol**: OSC 1.0 over SLIP-encoded stream
- **Direction**: Unidirectional (Audio Engine → Display only)
### Message Categories
#### 1. System State Messages
```osc
/looper/mode <string>
Values: "menu" | "performance"
Update frequency: On change only
/looper/tempo <float>
Range: 50.0 - 200.0 BPM
Update frequency: On change only
/looper/click/enabled <int>
Values: 0 (disabled) | 1 (enabled)
Update frequency: On change only
/looper/click/volume <float>
Range: 0.0 - 1.0
Update frequency: On expression pedal change
/looper/master/volume <float>
Range: 0.0 - 1.0
Update frequency: On expression pedal change
```
#### 2. Navigation State Messages
```osc
/looper/selected/column <int>
Range: 1-5
Update frequency: On change only
/looper/selected/row <int>
Range: 1-5
Update frequency: On change only
```
#### 3. Matrix Cell State Messages
```osc
/looper/cell/<column>/<row>/state <string>
Column: 1-5, Row: 1-5
Values: "empty" | "loading" | "ready" | "recording" | "playing" | "solo"
Update frequency: On change only
/looper/cell/<column>/<row>/volume <float>
Column: 1-5, Row: 1-5
Range: 0.0 - 1.0
Update frequency: On change only
```
#### 4. Column State Messages
```osc
/looper/column/<column>/beats <int>
Column: 1-5
Value: Number of beats in column (set by first recording, 0 = not set)
Update frequency: On first recording in column
/looper/column/<column>/beat <int>
Column: 1-5
Value: Current beat (1 = start of loop, 1+ = beat N)
Update frequency: On change
```
#### 5. Metronome Messages
```osc
/looper/metronome/position <float>
Range: 0.0 - 1.0 (position within current beat)
Update frequency: same as PPQN midi signal
```
### OSC Implementation Details
#### Initial State Synchronization
OSC is stateless - there's no "subscription" mechanism.
When the display process connects:
1. **Display connects** to Unix socket
2. **Audio engine detects** new connection
3. **Complete state dump** sent immediately:
4. **Regular updates** begin (position updates, state changes)
#### OSC Message Bundling
For efficiency, column-beat messages are bundled:
## Session Persistence
**Single Source of Truth**
- **Timing authority**: `samples_per_beat` in state.json
- **Track existence**: WAV file presence in filesystem
- **Tempo**: Derived from `(sample_rate × 60) ÷ samples_per_beat`
- **Column beats**: Derived from `wav_length_samples ÷ samples_per_beat`
- **Delete files**:
- If it's not a multiple of `samples_per_beat`
- If it doesn't match the sample rate
- When a track is cleared
## Auto-Save Triggers
- Track data changes (record/clear)
- Tempo/timing changes
- Volume adjustments (when constant for 5 seconds)
- Application shutdown
## Directory Structure
```
~/.fcb_looper/
├── state.json # System state and timing authority
├── col_1_row_1.wav # Audio tracks
├── col_1_row_2.wav
└── ...
```
## State File Format
```json
{
"version": "1.0",
"connections": {
"midi_in": [
"sendmidi:midi_out"
],
"audio_out": [
],
"audio_in": [
]
},
"ui_state": {
"selected_column": 3,
"selected_row": 2
},
"user_preferences": {
"click_enabled": true,
"click_volume": 0.5,
"master_volume": 0.8
},
"track_volumes": {
"col_1_row_1": 0.75,
"col_2_row_3": 0.9
},
"timing": {
"sample_rate": 44100,
"samples_per_beat": 105840,
}
}
```