Skip to content

Latest commit

 

History

History
147 lines (119 loc) · 4.76 KB

File metadata and controls

147 lines (119 loc) · 4.76 KB

Note Duration Visualization (DURA Tasks) - Implementation Summary

Overview

Implemented note duration visualization feature that shows:

  1. Blue LED emitter for note-on triggers
  2. Full-brightness colored cells for note duration (sustain tail)
  3. Sustain tail at 40-60% brightness following note-on
  4. Fade effect on last 2-3 rows of sustain

Files Modified

1. utils/gpuPacking.ts

Added Constants

  • NOTE_OFF = 97 - MOD note-off command
  • NOTE_CUT = 98 - MOD note-cut command
  • NOTE_FADE = 99 - MOD note-fade command
  • NOTE_MIN = 1 - Minimum valid note
  • NOTE_MAX = 96 - Maximum valid note

Added Interfaces

interface NoteDurationInfo {
  duration: number;    // Total duration in rows (1-255)
  rowOffset: number;   // Offset from note start (0 = note-on row)
  isNoteOff: boolean;  // Whether this is a note-off/cut/fade row
}

Added Functions

calculateNoteDurations(matrix) - DURA-001

  • Scans pattern data per-channel to calculate note spans
  • Detects note-off commands (97, 98, 99) and volume-zero cuts
  • Returns 2D array of duration info for each cell

Updated packPatternMatrixHighPrecision() - DURA-002

  • Calls calculateNoteDurations() to get note span data
  • Packs duration into packedA bits 8-15
  • Packs rowOffset and isNoteOff flag into packedB bits 8-14

New Packing Format (High Precision Mode)

packedA: [note:8][inst:8][duration:8][volPacked:8]
  - note: 8 bits (0-255, where 97=note-off)
  - inst: 8 bits (bit 7 is expression-only flag)
  - duration: 8 bits (1-255 rows)
  - volPacked: 4 bits volCmd + 4 bits volVal (upper nibbles)

packedB: [effCmd:8][effVal:8][durationFlags:7][reserved:1][volCmd:8]
  - effCmd: 8 bits (effect command)
  - effVal: 8 bits (effect value)
  - durationFlags: 7 bits [rowOffset:6][isNoteOff:1]
  - reserved: 1 bit
  - volCmd: 8 bits (full volume command for shader)

2. shaders/patternv0.50.wgsl

Added Constants

const NOTE_MIN: u32 = 1u;
const NOTE_MAX: u32 = 96u;
const NOTE_OFF: u32 = 97u;
const NOTE_CUT: u32 = 98u;
const NOTE_FADE: u32 = 99u;

Added Structs

struct NoteDurationInfo {
  duration: u32,      // Total note duration in rows
  rowOffset: u32,     // How many rows from note start (0 = note-on)
  isNoteOff: bool,    // Whether this cell is the note-off row
}

Added Functions

unpackDurationInfo(packedA, packedB) - DURA-003

  • Extracts duration from packedA bits 8-15
  • Extracts rowOffset and isNoteOff from packedB bits 8-14

calculateSustainBrightness(info, baseIntensity) - DURA-004

  • Returns full brightness on note-on row
  • Returns 40-60% brightness during middle of sustain
  • Fades from 60% to 30% over last 3 rows

isSustaining(info, hasNote) - DURA-005

  • Returns true if cell is within the note's sustain period

calculateBlueIntensity(info, hasNote, isPlayhead, trigger, beatPhase) - DURA-006

  • Bright blue flash (100%+) on note trigger
  • Dim blue glow (60%) on playhead row
  • Fading blue glow (40%→20%) during sustain tail

Updated Fragment Shader (fs function)

  • Reads new packed format with duration data
  • Uses calculateBlueIntensity() for top emitter
  • Uses calculateSustainBrightness() for middle emitter brightness
  • Shows full note color on note-on rows
  • Shows 40-60% brightness during sustain
  • Shows fade effect on last 2-3 rows of sustain

DURA Task Completion

Task Description Status
DURA-001 Implement note duration calculation ✅ Complete
DURA-002 Add noteDuration field to packed cell struct ✅ Complete
DURA-003 Add isSustained boolean to row data ✅ Complete
DURA-004 Implement blue LED emitter for note triggers ✅ Complete
DURA-005 Tie glow intensity to volume/expression ✅ Partial (structure ready)
DURA-006 Add current row pulse on note trigger ✅ Complete

Behavior

Blue LED Emitter (Top)

  • Note trigger row: Bright blue flash (100% + bloom)
  • Playhead on trigger: Blue glow (60%)
  • Sustain tail: Dim blue glow fading 40% → 20%
  • Muted: 20% intensity

Note Color (Middle)

  • Note-on row: Full brightness (80% + bloom)
  • Sustain middle: 40-60% brightness
  • Last 3 rows: Fade 60% → 30%
  • Muted: 25% of calculated brightness

Amber LED (Bottom)

  • Expression-only: 60% + bloom
  • Note-on + expression: 100% + bloom (DURA enhancement)
  • Note + expression: 40% + bloom

Testing

To test the implementation:

  1. Load a MOD file with sustained notes
  2. Observe blue LED flash on note triggers
  3. Observe sustain tail with reduced brightness (40-60%)
  4. Observe fade effect on last 2-3 rows of sustain
  5. Check that note-off commands properly terminate the sustain visualization

Build Status

✅ TypeScript compilation successful ✅ Vite build successful ✅ No errors