|
- import {Note, parseNote, PITCH_CLASSES} from "./note";
- import {toRawDuration} from './duration';
-
- export interface Playable {
- key?: number,
- start: number,
- end: number,
- startIndex: number,
- endIndex: number,
- }
-
- export interface SongData<T = Playable> {
- playables: T[],
- duration: number,
- index: number,
- }
-
- export * from './note'
- export * from './duration'
-
- export const toPlayable = (n: Note, tempo: number) => {
- const rawDurationBase = toRawDuration(n.duration, tempo)
- const duration = n.dotted ? rawDurationBase * 1.5 : rawDurationBase
- const pitchClassIndex = PITCH_CLASSES.indexOf(n.pitchClass!)
- if (!isNaN(pitchClassIndex) && 0 <= pitchClassIndex && pitchClassIndex <= 11 && !isNaN(n.octave!)) {
- return {
- duration,
- key: pitchClassIndex + (12 * (n.octave! + 1))
- }
- }
- return {
- duration,
- }
- }
-
- export const parseSong = <T>(s: string, tempo: number) => {
- return s.split(' ').reduce(
- (state, n, i, nn) => {
- let note
- try {
- note = parseNote(n)
- } catch {
- return state
- }
- const playable = toPlayable(note, tempo)
- return {
- ...state,
- playables: [
- ...state.playables,
- {
- key: playable.key,
- start: state.duration,
- end: state.duration + playable.duration,
- startIndex: state.index,
- endIndex: state.index + n.length
- }
- ],
- duration: (
- i < nn.length - 1
- ? state.duration + playable.duration
- : state.duration + playable.duration + 100
- ),
- index: state.index + n.length + 1
- } as SongData<T>
- },
- {
- playables: [] as T[],
- duration: 100,
- index: 0,
- }
- )
- }
|