Files
units-ui/lib/tempo.ts
Sebastian Krüger 75f895284f feat: add custom tempo/BPM converter with musical note units
Add comprehensive tempo conversion system supporting:
- BPM (beats per minute) as base unit
- Musical note durations: whole, half, quarter, eighth, sixteenth, thirty-second
- Dotted notes (1.5x duration): dotted-half, dotted-quarter, dotted-eighth, dotted-sixteenth
- Triplet notes (2/3 duration): quarter-triplet, eighth-triplet, sixteenth-triplet
- Time units: milliseconds, seconds, Hertz

Technical implementation:
- Created lib/tempo.ts with custom measure definition
- Extended lib/units.ts with tempo integration and reciprocal conversion logic
- Added tempo category color (orange #F97316) to globals.css
- Conversion formula: milliseconds per beat = 60000 / BPM
- Special handling for BPM ↔ time unit conversions using reciprocal relationship

The tempo converter integrates seamlessly with existing UX:
- Appears as "Tempo / BPM" category in category selector
- Supports all features: search, favorites, history, visual comparison, draggable bars
- Enables musicians to convert between BPM and note durations for tempo calculations

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-08 11:53:50 +01:00

118 lines
3.5 KiB
TypeScript

/**
* Custom tempo/BPM measure for convert-units
*
* Converts between BPM and note durations in milliseconds.
* Uses a reciprocal relationship where BPM (beats per minute) is the base unit.
*
* Formula: milliseconds per beat = 60000 / BPM
*
* The to_anchor value represents the conversion factor:
* - For BPM → time units: multiply by to_anchor to get milliseconds
* - For time units → BPM: divide by to_anchor to get BPM
*/
export const tempoMeasure = {
tempo: {
systems: {
metric: {
// BPM as the base unit (1 BPM = 60000 ms per beat)
'BPM': {
name: { singular: 'Beat per Minute', plural: 'Beats per Minute' },
to_anchor: 1
},
// Whole note (4 beats) = 240000 / BPM
'whole': {
name: { singular: 'Whole Note', plural: 'Whole Notes' },
to_anchor: 240000
},
// Half note (2 beats) = 120000 / BPM
'half': {
name: { singular: 'Half Note', plural: 'Half Notes' },
to_anchor: 120000
},
// Quarter note (1 beat) = 60000 / BPM
'quarter': {
name: { singular: 'Quarter Note', plural: 'Quarter Notes' },
to_anchor: 60000
},
// Eighth note (0.5 beats) = 30000 / BPM
'eighth': {
name: { singular: 'Eighth Note', plural: 'Eighth Notes' },
to_anchor: 30000
},
// Sixteenth note (0.25 beats) = 15000 / BPM
'sixteenth': {
name: { singular: 'Sixteenth Note', plural: 'Sixteenth Notes' },
to_anchor: 15000
},
// Thirty-second note (0.125 beats) = 7500 / BPM
'thirty-second': {
name: { singular: 'Thirty-Second Note', plural: 'Thirty-Second Notes' },
to_anchor: 7500
},
// Dotted notes (1.5x the duration)
'dotted-half': {
name: { singular: 'Dotted Half Note', plural: 'Dotted Half Notes' },
to_anchor: 180000 // 3 beats
},
'dotted-quarter': {
name: { singular: 'Dotted Quarter Note', plural: 'Dotted Quarter Notes' },
to_anchor: 90000 // 1.5 beats
},
'dotted-eighth': {
name: { singular: 'Dotted Eighth Note', plural: 'Dotted Eighth Notes' },
to_anchor: 45000 // 0.75 beats
},
'dotted-sixteenth': {
name: { singular: 'Dotted Sixteenth Note', plural: 'Dotted Sixteenth Notes' },
to_anchor: 22500 // 0.375 beats
},
// Triplet notes (2/3 of the duration)
'quarter-triplet': {
name: { singular: 'Quarter Note Triplet', plural: 'Quarter Note Triplets' },
to_anchor: 40000 // 2/3 beat
},
'eighth-triplet': {
name: { singular: 'Eighth Note Triplet', plural: 'Eighth Note Triplets' },
to_anchor: 20000 // 1/3 beat
},
'sixteenth-triplet': {
name: { singular: 'Sixteenth Note Triplet', plural: 'Sixteenth Note Triplets' },
to_anchor: 10000 // 1/6 beat
},
// Milliseconds as direct time unit
'ms': {
name: { singular: 'Millisecond', plural: 'Milliseconds' },
to_anchor: 60000 // Same as quarter note
},
// Seconds
's': {
name: { singular: 'Second', plural: 'Seconds' },
to_anchor: 60 // 60 seconds per beat at 1 BPM
},
// Hertz (beats per second)
'Hz': {
name: { singular: 'Hertz', plural: 'Hertz' },
to_anchor: 1 / 60 // 1 BPM = 1/60 Hz
}
}
}
}
};