More concrete project plan
This commit is contained in:
parent
5ab36a7d02
commit
1bc1224441
@ -1,261 +0,0 @@
|
|||||||
# FCB1010 MIDI Integration Technical Reference
|
|
||||||
|
|
||||||
## 1. MIDI Controller Configuration
|
|
||||||
|
|
||||||
The FCB1010 will be configured with a consistent set of Control Change (CC) messages for all buttons and pedals:
|
|
||||||
|
|
||||||
| Control | CC Number | Value | Description |
|
|
||||||
|---------|-----------|-------|-------------|
|
|
||||||
| **Button 1** | CC 1 | 127/0 | Value 127 when pressed, 0 when released |
|
|
||||||
| **Button 2** | CC 2 | 127/0 | Value 127 when pressed, 0 when released |
|
|
||||||
| **Button 3** | CC 3 | 127/0 | Value 127 when pressed, 0 when released |
|
|
||||||
| **Button 4** | CC 4 | 127/0 | Value 127 when pressed, 0 when released |
|
|
||||||
| **Button 5** | CC 5 | 127/0 | Value 127 when pressed, 0 when released |
|
|
||||||
| **Button 6** | CC 6 | 127/0 | Value 127 when pressed, 0 when released |
|
|
||||||
| **Button 7** | CC 7 | 127/0 | Value 127 when pressed, 0 when released |
|
|
||||||
| **Button 8** | CC 8 | 127/0 | Value 127 when pressed, 0 when released |
|
|
||||||
| **Button 9** | CC 9 | 127/0 | Value 127 when pressed, 0 when released |
|
|
||||||
| **Button 10** | CC 10 | 127/0 | Value 127 when pressed, 0 when released |
|
|
||||||
| **UP** | CC 11 | 127/0 | Value 127 when pressed, 0 when released |
|
|
||||||
| **DOWN** | CC 12 | 127/0 | Value 127 when pressed, 0 when released |
|
|
||||||
| **Expression A** | CC 16 | 0-127 | Continuous controller |
|
|
||||||
| **Expression B** | CC 17 | 0-127 | Continuous controller |
|
|
||||||
| **MIDI Channel** | All on Channel 1 | | Single channel for simplicity |
|
|
||||||
|
|
||||||
## 2. System Architecture
|
|
||||||
|
|
||||||
### 2.1 Integration Diagram
|
|
||||||
|
|
||||||
```
|
|
||||||
+-------------+ +----------------+ +-------------+ +--------------+
|
|
||||||
| JACK Thread | --> | Lock-free MIDI | --> | MIDI Thread | --> | Application |
|
|
||||||
| (real-time) | | Input Queue | | | | Logic Thread |
|
|
||||||
+-------------+ +----------------+ +-------------+ +--------------+
|
|
||||||
^ |
|
|
||||||
| v
|
|
||||||
+----------------+ +----------------+
|
|
||||||
| Lock-free MIDI | | Configuration |
|
|
||||||
| Output Queue | <----------------------| Commands |
|
|
||||||
+----------------+ +----------------+
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.2 Communication Channels
|
|
||||||
|
|
||||||
The system uses Crossbeam channels for thread communication:
|
|
||||||
|
|
||||||
1. **MIDI Input Channel**: Transfers raw MIDI data from JACK thread to MIDI processing thread
|
|
||||||
2. **MIDI Output Channel**: Transfers SysEx configuration messages from MIDI thread to JACK thread
|
|
||||||
3. **Event Channel**: Delivers controller events from MIDI thread to application logic
|
|
||||||
4. **Command Channel**: Sends configuration commands from application to MIDI thread
|
|
||||||
|
|
||||||
### 2.3 MIDI Message Flow
|
|
||||||
|
|
||||||
1. **JACK Callback (Real-time Thread)**:
|
|
||||||
- Receives MIDI data from FCB1010
|
|
||||||
- Copies data to `midi_input_sender`
|
|
||||||
- Reads from `midi_output_receiver` for SysEx configuration
|
|
||||||
|
|
||||||
2. **MIDI Processing Thread**:
|
|
||||||
- Reads from `midi_input_receiver`
|
|
||||||
- Translates MIDI messages to `ControllerEvent` instances
|
|
||||||
- Sends events via `event_sender`
|
|
||||||
- Processes configuration commands from `command_receiver`
|
|
||||||
- Sends SysEx messages via `midi_output_sender`
|
|
||||||
|
|
||||||
3. **Application Logic Thread**:
|
|
||||||
- Reads from `event_receiver`
|
|
||||||
- Sends configuration commands via `command_sender`
|
|
||||||
|
|
||||||
## 3. Message Translation
|
|
||||||
|
|
||||||
### 3.1 MIDI to ControllerEvent Translation
|
|
||||||
|
|
||||||
The MIDI processing thread translates FCB1010 MIDI messages to controller-independent events according to the following mapping:
|
|
||||||
|
|
||||||
| MIDI Message | Condition | Translated Event |
|
|
||||||
|--------------|-----------|------------------|
|
|
||||||
| CC 1, Value 127 | Channel 1 | ButtonPress(1) |
|
|
||||||
| CC 2, Value 127 | Channel 1 | ButtonPress(2) |
|
|
||||||
| CC 3, Value 127 | Channel 1 | ButtonPress(3) |
|
|
||||||
| CC 4, Value 127 | Channel 1 | ButtonPress(4) |
|
|
||||||
| CC 5, Value 127 | Channel 1 | ButtonPress(5) |
|
|
||||||
| CC 6, Value 127 | Channel 1 | ButtonPress(6) |
|
|
||||||
| CC 7, Value 127 | Channel 1 | ButtonPress(7) |
|
|
||||||
| CC 8, Value 127 | Channel 1 | ButtonPress(8) |
|
|
||||||
| CC 9, Value 127 | Channel 1 | ButtonPress(9) |
|
|
||||||
| CC 10, Value 127 | Channel 1 | ButtonPress(10) |
|
|
||||||
| CC 11, Value 127 | Channel 1 | Navigation(NavigationButton::Up) |
|
|
||||||
| CC 12, Value 127 | Channel 1 | Navigation(NavigationButton::Down) |
|
|
||||||
| CC 16, Any Value | Channel 1 | ExpressionPedal(ExpressionPedal::A, value) |
|
|
||||||
| CC 17, Any Value | Channel 1 | ExpressionPedal(ExpressionPedal::B, value) |
|
|
||||||
|
|
||||||
Notes on translation:
|
|
||||||
- Only button press events (value 127) are translated for footswitches and navigation buttons
|
|
||||||
- Button release events (value 0) are ignored
|
|
||||||
- All expression pedal value changes (0-127) are translated
|
|
||||||
- Messages on MIDI channels other than Channel 1 are ignored
|
|
||||||
- Other MIDI message types (Program Change, Note On/Off, etc.) are ignored
|
|
||||||
|
|
||||||
### 3.2 Event Types
|
|
||||||
|
|
||||||
```rust
|
|
||||||
pub enum ControllerEvent {
|
|
||||||
/// Footswitch button press (1-10)
|
|
||||||
ButtonPress(u8),
|
|
||||||
|
|
||||||
/// Navigation button press
|
|
||||||
Navigation(NavigationButton),
|
|
||||||
|
|
||||||
/// Expression pedal value change
|
|
||||||
ExpressionPedal(ExpressionPedal, u8), // value 0-127
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum NavigationButton {
|
|
||||||
Up,
|
|
||||||
Down,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum ExpressionPedal {
|
|
||||||
A,
|
|
||||||
B,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum FcbCommand {
|
|
||||||
/// Configure the FCB1010 for our application
|
|
||||||
Initialize,
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 4. FCB1010 Initialization
|
|
||||||
|
|
||||||
The FCB1010 is configured at startup using SysEx messages:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
fn initialize_fcb1010(command_sender: &crossbeam::channel::Sender<FcbCommand>) {
|
|
||||||
// Send initialization command to MIDI processing thread
|
|
||||||
command_sender.send(FcbCommand::Initialize).unwrap_or_else(|e| {
|
|
||||||
error!("Failed to send FCB1010 initialization command: {}", e);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The MIDI processing thread handles the initialization by sending SysEx messages:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
fn handle_fcb_command(
|
|
||||||
command: FcbCommand,
|
|
||||||
midi_output_sender: &crossbeam::channel::Sender<Vec<u8>>
|
|
||||||
) {
|
|
||||||
match command {
|
|
||||||
FcbCommand::Initialize => {
|
|
||||||
info!("Initializing FCB1010");
|
|
||||||
|
|
||||||
// Get SysEx messages from FCB1010 SysEx generator
|
|
||||||
let sysex_messages = generate_fcb1010_configuration();
|
|
||||||
|
|
||||||
// Send each SysEx message with a delay to avoid buffer overruns
|
|
||||||
for message in sysex_messages {
|
|
||||||
midi_output_sender.send(message).unwrap_or_else(|e| {
|
|
||||||
error!("Failed to send SysEx message: {}", e);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Allow time for the message to be processed
|
|
||||||
std::thread::sleep(std::time::Duration::from_millis(50));
|
|
||||||
}
|
|
||||||
|
|
||||||
info!("FCB1010 initialization complete");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 5. JACK Integration
|
|
||||||
|
|
||||||
### 5.1 JACK Process Callback
|
|
||||||
|
|
||||||
The JACK process callback runs in a real-time thread with strict timing constraints. To maintain real-time safety:
|
|
||||||
|
|
||||||
1. **No Memory Allocations**: The callback must never allocate memory (no `Vec`, `String`, `Box`, etc.)
|
|
||||||
2. **No Blocking Operations**: The callback must not block (no file I/O, mutex locks, etc.)
|
|
||||||
3. **Minimal Processing**: Only the bare minimum work should be done in this thread
|
|
||||||
|
|
||||||
For FCB1010 integration, the JACK callback should:
|
|
||||||
|
|
||||||
1. **Read MIDI Input**: Copy raw MIDI data bytes to a pre-allocated lock-free ring buffer
|
|
||||||
2. **Write MIDI Output**: Read from a lock-free buffer and send to the MIDI output port
|
|
||||||
|
|
||||||
#### Avoiding Allocations
|
|
||||||
|
|
||||||
To avoid allocations while handling MIDI data:
|
|
||||||
|
|
||||||
1. **Pre-allocated Buffers**: Use fixed-size arrays or pre-allocated ring buffers
|
|
||||||
2. **Zero-Copy Access**: Access MIDI data directly without copying when possible
|
|
||||||
3. **Message Passing**: Use lock-free data structures that don't require allocation
|
|
||||||
4. **Byte References**: Pass references to MIDI data rather than copying the data
|
|
||||||
|
|
||||||
### 5.2 MIDI Processing Thread
|
|
||||||
|
|
||||||
The MIDI processing thread runs continuously outside of JACK's real-time constraints, allowing for:
|
|
||||||
|
|
||||||
1. Receiving MIDI data from the lock-free input buffer
|
|
||||||
2. Translating MIDI messages to controller events
|
|
||||||
3. Sending events to the application logic
|
|
||||||
4. Processing configuration commands
|
|
||||||
5. Sending SysEx messages to the FCB1010
|
|
||||||
|
|
||||||
This thread can safely perform memory allocations and more complex processing since it's not subject to real-time constraints.
|
|
||||||
|
|
||||||
## 6. Testing Approach
|
|
||||||
|
|
||||||
### 6.1 Mock FCB Implementation
|
|
||||||
|
|
||||||
For testing without hardware, a mock FCB implementation will use the same MIDI message format as the physical FCB1010:
|
|
||||||
|
|
||||||
1. **JACK-Based MIDI Device**: The mock will appear as a standard MIDI device in the JACK system
|
|
||||||
2. **Message Format Consistency**: It will generate identical CC messages following the table in section 1
|
|
||||||
3. **Bidirectional Communication**: It will receive and verify SysEx configuration messages
|
|
||||||
4. **Programmatic Control**: It can be triggered by test code to simulate button presses and pedal movements
|
|
||||||
|
|
||||||
This approach allows testing the complete integration without requiring the physical FCB1010 hardware, while ensuring message format compatibility.
|
|
||||||
|
|
||||||
The mock FCB will translate controller-independent events back to MIDI messages, effectively doing the reverse of the translation described in section 3.1. This symmetrical translation enables comprehensive testing of the entire message pipeline.
|
|
||||||
|
|
||||||
### 6.2 Integration Testing
|
|
||||||
|
|
||||||
Integration tests will verify the complete flow from MIDI messages to application events:
|
|
||||||
|
|
||||||
1. Create a mock FCB instance
|
|
||||||
2. Start the MIDI processing thread
|
|
||||||
3. Generate MIDI messages from the mock FCB
|
|
||||||
4. Verify correct `ControllerEvent` instances are produced
|
|
||||||
5. Test error conditions and recovery
|
|
||||||
|
|
||||||
### 6.3 SysEx Testing
|
|
||||||
|
|
||||||
SysEx testing will verify the FCB1010 configuration messages:
|
|
||||||
|
|
||||||
1. Create a mock FCB that captures SysEx messages
|
|
||||||
2. Send the initialization command
|
|
||||||
3. Verify the SysEx messages match the expected format
|
|
||||||
4. Test with corrupted or incomplete SysEx responses
|
|
||||||
|
|
||||||
## 7. Logging
|
|
||||||
|
|
||||||
The integration will use the Rust `log` crate for detailed logging:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
// MIDI message logging
|
|
||||||
debug!("Received MIDI message: {:?}", data);
|
|
||||||
|
|
||||||
// Controller event logging
|
|
||||||
info!("Translated to controller event: {:?}", event);
|
|
||||||
|
|
||||||
// SysEx logging
|
|
||||||
info!("Sending FCB1010 configuration SysEx");
|
|
||||||
debug!("SysEx message: {:?}", sysex_message);
|
|
||||||
|
|
||||||
// Error logging
|
|
||||||
error!("Failed to process MIDI message: {}", error);
|
|
||||||
```
|
|
||||||
|
|
||||||
Initial logs will go to standard output, with a future extension to log to a UI window.
|
|
||||||
240
interface_spec.md
Normal file
240
interface_spec.md
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
# 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)
|
||||||
|
SysEx Test: CC #127 (Trigger FCB1010 reconfiguration)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 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" | "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>/bars <int>
|
||||||
|
Column: 1-5
|
||||||
|
Value: Number of bars in column (set by first recording, 0 = not set)
|
||||||
|
Update frequency: On first recording in column
|
||||||
|
|
||||||
|
/looper/column/<column>/bar <int>
|
||||||
|
Column: 1-5
|
||||||
|
Value: Current bar (1 = start of loop, 1+ = bar N)
|
||||||
|
Update frequency: On change
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 5. Metronome Messages
|
||||||
|
|
||||||
|
```osc
|
||||||
|
/looper/metronome/position <float>
|
||||||
|
Range: 0.0 - 1.0 (position within current bar)
|
||||||
|
Update frequency: 60 FPS
|
||||||
|
```
|
||||||
|
|
||||||
|
### 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-bar messages are bundled:
|
||||||
|
|
||||||
|
## Session Persistence
|
||||||
|
|
||||||
|
**Single Source of Truth**
|
||||||
|
|
||||||
|
- **Timing authority**: `samples_per_bar` in state.json
|
||||||
|
- **Track existence**: WAV file presence in filesystem
|
||||||
|
- **Tempo**: Derived from `(sample_rate × 60) ÷ (samples_per_bar × beats_per_bar)`
|
||||||
|
- **Column bars**: Derived from `wav_length_samples ÷ samples_per_bar`
|
||||||
|
- **Delete files**:
|
||||||
|
- If it's not a multiple of `samples_per_bar`
|
||||||
|
- 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",
|
||||||
|
"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_bar": 105840,
|
||||||
|
"time_signature": [4, 4]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
@ -1,4 +1,4 @@
|
|||||||
# FCB1010 Looper Pedal - Complete Project Specification
|
# FCB1010 Looper Pedal - Project Specification
|
||||||
|
|
||||||
## System Overview
|
## System Overview
|
||||||
|
|
||||||
@ -28,6 +28,10 @@ The system provides a 5x5 matrix of loop tracks organized in columns and rows, w
|
|||||||
## Interface Design
|
## Interface Design
|
||||||
- **Metronome**: Moving indicator that pulses when in center
|
- **Metronome**: Moving indicator that pulses when in center
|
||||||
- **Progress Bars**: Show current position in each column with bar divisions
|
- **Progress Bars**: Show current position in each column with bar divisions
|
||||||
|
|
||||||
|
First recording behavior:
|
||||||
|
- Progress bar fills during bar 1, then stays full
|
||||||
|
- Additional bars appear as sliding segments (right-to-left)
|
||||||
- **Active Row**: Increased border with
|
- **Active Row**: Increased border with
|
||||||
- **Selected Cell**: Switched border and background color
|
- **Selected Cell**: Switched border and background color
|
||||||
- **Track States**:
|
- **Track States**:
|
||||||
@ -43,10 +47,10 @@ The system provides a 5x5 matrix of loop tracks organized in columns and rows, w
|
|||||||
### Menu State
|
### Menu State
|
||||||
- **Button 1**: Tap Tempo
|
- **Button 1**: Tap Tempo
|
||||||
- **Button 2**: Enable/Disable Click Track
|
- **Button 2**: Enable/Disable Click Track
|
||||||
- **Button 3**: Clear selected Column
|
- **Button 3**: Not used
|
||||||
- **Button 4**: Quantization Settings (Off, 1/4, 1/8, 1/16 note)
|
- **Button 4**: Not used
|
||||||
- **Button 5**: Save/Load Project (use buttons 6-10 for slot selection)
|
- **Button 5**: Clear current column
|
||||||
- **Buttons 6-10**: Column selection (for clear/save/load operations)
|
- **Buttons 6-10**: Column selection (1-5)
|
||||||
- **UP/DOWN**: Switch to Performance Mode
|
- **UP/DOWN**: Switch to Performance Mode
|
||||||
- **Expression Pedal A**: Click track volume
|
- **Expression Pedal A**: Click track volume
|
||||||
- **Expression Pedal B**: Master volume
|
- **Expression Pedal B**: Master volume
|
||||||
@ -93,7 +97,6 @@ The system provides a 5x5 matrix of loop tracks organized in columns and rows, w
|
|||||||
|
|
||||||
### State Management
|
### State Management
|
||||||
|
|
||||||
- **Save in Numbered Slots**: 5 project slots accessible via buttons 6-10 in save/load mode
|
- **Startup Behavior**: Load last audio tracks and configure FCB1010
|
||||||
- **Startup Behavior**: Load last used project and configure FCB1010
|
|
||||||
- **Column Consistency**: Recordings automatically match column bar count
|
- **Column Consistency**: Recordings automatically match column bar count
|
||||||
- **State Validation**: Prevent invalid operations (e.g., switching columns while recording)
|
- **State Validation**: Prevent invalid operations (e.g., switching columns while recording)
|
||||||
Loading…
x
Reference in New Issue
Block a user