Ringtone app
Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 

73 linhas
1.5 KiB

  1. import {Note, parseNote, PITCH_CLASSES} from "./note";
  2. import {toRawDuration} from './duration';
  3. export interface Playable {
  4. key?: number,
  5. start: number,
  6. end: number,
  7. startIndex: number,
  8. endIndex: number,
  9. }
  10. export interface SongData<T = Playable> {
  11. playables: T[],
  12. duration: number,
  13. index: number,
  14. }
  15. export * from './note'
  16. export * from './duration'
  17. export const toPlayable = (n: Note, tempo: number) => {
  18. const rawDurationBase = toRawDuration(n.duration, tempo)
  19. const duration = n.dotted ? rawDurationBase * 1.5 : rawDurationBase
  20. const pitchClassIndex = PITCH_CLASSES.indexOf(n.pitchClass!)
  21. if (!isNaN(pitchClassIndex) && 0 <= pitchClassIndex && pitchClassIndex <= 11 && !isNaN(n.octave!)) {
  22. return {
  23. duration,
  24. key: pitchClassIndex + (12 * (n.octave! + 1))
  25. }
  26. }
  27. return {
  28. duration,
  29. }
  30. }
  31. export const parseSong = <T>(s: string, tempo: number) => {
  32. return s.split(' ').reduce(
  33. (state, n, i, nn) => {
  34. let note
  35. try {
  36. note = parseNote(n)
  37. } catch {
  38. return state
  39. }
  40. const playable = toPlayable(note, tempo)
  41. return {
  42. ...state,
  43. playables: [
  44. ...state.playables,
  45. {
  46. key: playable.key,
  47. start: state.duration,
  48. end: state.duration + playable.duration,
  49. startIndex: state.index,
  50. endIndex: state.index + n.length
  51. }
  52. ],
  53. duration: (
  54. i < nn.length - 1
  55. ? state.duration + playable.duration
  56. : state.duration + playable.duration + 100
  57. ),
  58. index: state.index + n.length + 1
  59. } as SongData<T>
  60. },
  61. {
  62. playables: [] as T[],
  63. duration: 100,
  64. index: 0,
  65. }
  66. )
  67. }