scribbletune 5.2.0 → 5.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/browser.cjs +1183 -0
  2. package/dist/browser.cjs.map +1 -0
  3. package/dist/browser.js +1135 -1
  4. package/dist/browser.js.map +1 -1
  5. package/dist/{index.mjs → index.cjs} +225 -169
  6. package/dist/index.cjs.map +1 -0
  7. package/dist/index.d.cts +323 -0
  8. package/dist/index.d.ts +303 -350
  9. package/dist/index.js +524 -1
  10. package/dist/index.js.map +1 -1
  11. package/dist/scribbletune.global.js +1944 -0
  12. package/dist/scribbletune.global.js.map +1 -0
  13. package/package.json +29 -40
  14. package/dist/lib/arp.d.ts +0 -10
  15. package/dist/lib/browser-clip.d.ts +0 -14
  16. package/dist/lib/browser-index.d.ts +0 -7
  17. package/dist/lib/channel.d.ts +0 -61
  18. package/dist/lib/clip.d.ts +0 -2
  19. package/dist/lib/index.d.ts +0 -7
  20. package/dist/lib/midi.d.ts +0 -11
  21. package/dist/lib/progression.d.ts +0 -25
  22. package/dist/lib/session.d.ts +0 -14
  23. package/dist/lib/types/arp-params.d.ts +0 -6
  24. package/dist/lib/types/channel-params.d.ts +0 -92
  25. package/dist/lib/types/channel-pattern.d.ts +0 -24
  26. package/dist/lib/types/clip-params.d.ts +0 -104
  27. package/dist/lib/types/event-fn.d.ts +0 -7
  28. package/dist/lib/types/index.d.ts +0 -14
  29. package/dist/lib/types/note-object.d.ts +0 -6
  30. package/dist/lib/types/nvp.d.ts +0 -4
  31. package/dist/lib/types/play-params.d.ts +0 -15
  32. package/dist/lib/types/player-observer-fn.d.ts +0 -6
  33. package/dist/lib/types/progression-scale.d.ts +0 -2
  34. package/dist/lib/types/seq-fn.d.ts +0 -2
  35. package/dist/lib/types/sizzle-style.d.ts +0 -2
  36. package/dist/lib/types/synth-params.d.ts +0 -20
  37. package/dist/lib/types/tpd.d.ts +0 -15
  38. package/dist/lib/utils.d.ts +0 -56
  39. package/dist/scribbletune.js +0 -2
  40. package/dist/scribbletune.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/browser-index.ts","../node_modules/harmonics/dist/index.mjs","../src/utils.ts","../src/arp.ts","../src/channel/instrument-factory.ts","../src/channel/sequence-builder.ts","../src/clip-utils.ts","../src/browser-clip.ts","../src/midi.ts","../node_modules/@scribbletune/midi/src/util.ts","../node_modules/@scribbletune/midi/src/types.ts","../node_modules/@scribbletune/midi/src/event.ts","../node_modules/@scribbletune/midi/src/meta-event.ts","../node_modules/@scribbletune/midi/src/constants.ts","../node_modules/@scribbletune/midi/src/track.ts","../node_modules/@scribbletune/midi/src/file.ts","../node_modules/@scribbletune/midi/src/index.ts","../src/progression.ts","../src/channel/effects-chain.ts","../src/channel.ts","../src/session.ts"],"sourcesContent":["import { chord, chords, scale, scales } from 'harmonics';\nimport { arp } from './arp';\nimport { clip } from './browser-clip';\nimport { midi } from './midi';\nimport {\n getChordDegrees,\n getChordsByProgression,\n progression,\n} from './progression';\nimport { Session } from './session';\n\nexport * from './types';\nexport {\n scale,\n scale as mode,\n scales,\n scales as modes,\n chord,\n chords,\n clip,\n getChordDegrees,\n getChordsByProgression,\n progression,\n arp,\n midi,\n Session,\n};\n","// src/gen/scaleMaps.json\nvar scaleMaps_default = {\n \"major pentatonic\": \"101010010100\",\n \"ionian pentatonic\": \"100011010001\",\n \"mixolydian pentatonic\": \"100011010010\",\n ritusen: \"101001010100\",\n egyptian: \"101001010010\",\n \"neopolitan major pentatonic\": \"100011100010\",\n \"vietnamese 1\": \"100101011000\",\n pelog: \"110100011000\",\n kumoijoshi: \"110001011000\",\n hirajoshi: \"101100011000\",\n iwato: \"110001100010\",\n \"in-sen\": \"110001010010\",\n \"lydian pentatonic\": \"100010110001\",\n \"malkos raga\": \"100101001010\",\n \"locrian pentatonic\": \"100101100010\",\n \"minor pentatonic\": \"100101010010\",\n \"minor six pentatonic\": \"100101010100\",\n \"flat three pentatonic\": \"101100010100\",\n \"flat six pentatonic\": \"101010011000\",\n scriabin: \"110010010100\",\n \"whole tone pentatonic\": \"100010101010\",\n \"lydian #5P pentatonic\": \"100010101001\",\n \"lydian dominant pentatonic\": \"100010110010\",\n \"minor #7M pentatonic\": \"100101010001\",\n \"super locrian pentatonic\": \"100110100010\",\n \"minor hexatonic\": \"101101010001\",\n augmented: \"100110011001\",\n \"major blues\": \"101110010100\",\n piongio: \"101001010110\",\n \"prometheus neopolitan\": \"110010100110\",\n prometheus: \"101010100110\",\n \"mystery #1\": \"110010101010\",\n \"six tone symmetric\": \"110011001100\",\n \"whole tone\": \"101010101010\",\n \"messiaen's mode #5\": \"110001110001\",\n \"minor blues\": \"100101110010\",\n \"locrian major\": \"101011101010\",\n \"double harmonic lydian\": \"110010111001\",\n \"harmonic minor\": \"101101011001\",\n altered: \"110110101010\",\n \"locrian #2\": \"101101101010\",\n \"mixolydian b6\": \"101011011010\",\n \"lydian dominant\": \"101010110110\",\n lydian: \"101010110101\",\n \"lydian augmented\": \"101010101101\",\n \"dorian b2\": \"110101010110\",\n \"melodic minor\": \"101101010101\",\n locrian: \"110101101010\",\n ultralocrian: \"110110101100\",\n \"locrian 6\": \"110101100110\",\n \"augmented heptatonic\": \"100111011001\",\n \"romanian minor\": \"101100110110\",\n \"dorian #4\": \"101100110110\",\n \"lydian diminished\": \"101100110101\",\n phrygian: \"110101011010\",\n \"leading whole tone\": \"101010101011\",\n \"lydian minor\": \"101010111010\",\n \"phrygian dominant\": \"110011011010\",\n balinese: \"110101011001\",\n \"neopolitan major\": \"110101010101\",\n aeolian: \"101101011010\",\n \"harmonic major\": \"101011011001\",\n \"double harmonic major\": \"110011011001\",\n dorian: \"101101010110\",\n \"hungarian minor\": \"101100111001\",\n \"hungarian major\": \"100110110110\",\n oriental: \"110011100110\",\n flamenco: \"110110110010\",\n \"todi raga\": \"110100111001\",\n mixolydian: \"101011010110\",\n persian: \"110011101001\",\n major: \"101011010101\",\n enigmatic: \"110010101011\",\n \"major augmented\": \"101011001101\",\n \"lydian #9\": \"100110110101\",\n \"messiaen's mode #4\": \"111001111001\",\n \"purvi raga\": \"110011111001\",\n \"spanish heptatonic\": \"110111011010\",\n bebop: \"101011010111\",\n \"bebop minor\": \"101111010110\",\n \"bebop major\": \"101011011101\",\n \"bebop locrian\": \"110101111010\",\n \"minor bebop\": \"101101011011\",\n diminished: \"101101101101\",\n ichikosucho: \"101011110101\",\n \"minor six diminished\": \"101101011101\",\n \"half-whole diminished\": \"110110110110\",\n \"kafi raga\": \"100111010111\",\n \"messiaen's mode #6\": \"101011101011\",\n \"composite blues\": \"101111110110\",\n \"messiaen's mode #3\": \"101110111011\",\n \"messiaen's mode #7\": \"111101111101\",\n chromatic: \"111111111111\",\n ionian: \"101011010101\",\n minor: \"101101011010\",\n Kanakangi: \"111001011100\",\n Ratnangi: \"111001011010\",\n Ganamurti: \"111001011001\",\n Vanaspati: \"111001010110\",\n Manavati: \"111001010101\",\n Tanarupi: \"111001010011\",\n Senavati: \"110101011100\",\n Hanumatodi: \"110101011010\",\n Dhenuka: \"110101011001\",\n Natakapriya: \"110101010110\",\n Kokilapriya: \"110101010101\",\n Rupavati: \"110101010011\",\n Gayakapriya: \"110011011100\",\n Vakulabharanam: \"110011011010\",\n Mayamalavagowla: \"110011011001\",\n Chakravakam: \"110011010110\",\n Suryakantam: \"110011010101\",\n Hatakambari: \"110011010011\",\n Jhankaradhwani: \"101101011100\",\n Natabhairavi: \"101101011010\",\n Keeravani: \"101101011001\",\n Kharaharapriya: \"101101010110\",\n Gourimanohari: \"101101010101\",\n Varunapriya: \"101101010011\",\n Mararanjani: \"101011011100\",\n Charukesi: \"101011011010\",\n Sarasangi: \"101011011001\",\n Harikambhoji: \"101011010110\",\n Dheerasankarabaranam: \"101011010101\",\n Naganandini: \"101011010011\",\n Yagapriya: \"100111011100\",\n Ragavardhini: \"100111011010\",\n Gangeyabhushani: \"100111011001\",\n Vagadheeswari: \"100111010110\",\n Shulini: \"100111010101\",\n Chalanata: \"100111010011\",\n Salagam: \"111000111100\",\n Jalarnavam: \"111000111010\",\n Jhalavarali: \"111000111001\",\n Navaneetam: \"111000110110\",\n Pavani: \"111000110101\",\n Raghupriya: \"111000110011\",\n Gavambhodi: \"110100111100\",\n Bhavapriya: \"110100111010\",\n Shubhapantuvarali: \"110100111001\",\n Shadvidamargini: \"110100110110\",\n Suvarnangi: \"110100110101\",\n Divyamani: \"110100110011\",\n Dhavalambari: \"110010111100\",\n Namanarayani: \"110010111010\",\n Kamavardhini: \"110010111001\",\n Ramapriya: \"110010110110\",\n Gamanashrama: \"110010110101\",\n Vishwambari: \"110010110011\",\n Shamalangi: \"101100111100\",\n Shanmukhapriya: \"101100111010\",\n Simhendramadhyamam: \"101100111001\",\n Hemavati: \"101100110110\",\n Dharmavati: \"101100110101\",\n Neetimati: \"101100110011\",\n Kantamani: \"101010111100\",\n Rishabhapriya: \"101010111010\",\n Latangi: \"101010111001\",\n Vachaspati: \"101010110110\",\n Mechakalyani: \"101010110101\",\n Chitrambari: \"101010110011\",\n Sucharitra: \"100110111100\",\n \"Jyoti swarupini\": \"100110111010\",\n Dhatuvardani: \"100110111001\",\n Nasikabhushini: \"100110110110\",\n Kosalam: \"100110110101\",\n Rasikapriya: \"100110110011\"\n};\n\n// src/gen/chordMaps.json\nvar chordMaps_default = {\n \"5th\": \"100000010000\",\n \"M7#5sus4\": \"100001001001\",\n \"7#5sus4\": \"100001001010\",\n sus4: \"100001010000\",\n M7sus4: \"100001010001\",\n \"7sus4\": \"100001010010\",\n \"7no5\": \"100010000010\",\n aug: \"100010001000\",\n M7b6: \"100010001001\",\n \"maj7#5\": \"100010001001\",\n \"7#5\": \"100010001010\",\n \"7b13\": \"100010001010\",\n M: \"100010010000\",\n maj7: \"100010010001\",\n \"7th\": \"100010010010\",\n \"6th\": \"100010010100\",\n \"7add6\": \"100010010110\",\n \"7b6\": \"100010011010\",\n Mb5: \"100010100000\",\n M7b5: \"100010100001\",\n \"7b5\": \"100010100010\",\n \"maj#4\": \"100010110001\",\n \"7#11\": \"100010110010\",\n \"M6#11\": \"100010110100\",\n \"7#11b13\": \"100010111010\",\n \"m#5\": \"100100001000\",\n mb6M7: \"100100001001\",\n \"m7#5\": \"100100001010\",\n m: \"100100010000\",\n \"m/ma7\": \"100100010001\",\n m7: \"100100010010\",\n m6: \"100100010100\",\n mMaj7b6: \"100100011001\",\n dim: \"100100100000\",\n oM7: \"100100100001\",\n m7b5: \"100100100010\",\n dim7: \"100100100100\",\n o7M7: \"100100100101\",\n \"4th\": \"100101000010\",\n madd4: \"100101010000\",\n m7add11: \"100101010010\",\n \"+add#9\": \"100110001000\",\n \"7#5#9\": \"100110001010\",\n \"7#9\": \"100110010010\",\n \"13#9\": \"100110010110\",\n \"7#9b13\": \"100110011010\",\n \"maj7#9#11\": \"100110110001\",\n \"7#9#11\": \"100110110010\",\n \"13#9#11\": \"100110110110\",\n \"7#9#11b13\": \"100110111010\",\n sus2: \"101000010000\",\n \"M9#5sus4\": \"101001001001\",\n sus24: \"101001010000\",\n M9sus4: \"101001010001\",\n \"11th\": \"101001010010\",\n \"9sus4\": \"101001010010\",\n \"13sus4\": \"101001010110\",\n \"9no5\": \"101010000010\",\n \"13no5\": \"101010000110\",\n \"M#5add9\": \"101010001000\",\n \"maj9#5\": \"101010001001\",\n \"9#5\": \"101010001010\",\n \"9b13\": \"101010001010\",\n Madd9: \"101010010000\",\n maj9: \"101010010001\",\n \"9th\": \"101010010010\",\n \"6/9\": \"101010010100\",\n maj13: \"101010010101\",\n M7add13: \"101010010101\",\n \"13th\": \"101010010110\",\n M9b5: \"101010100001\",\n \"9b5\": \"101010100010\",\n \"13b5\": \"101010100110\",\n \"9#5#11\": \"101010101010\",\n \"maj9#11\": \"101010110001\",\n \"9#11\": \"101010110010\",\n \"69#11\": \"101010110100\",\n \"M13#11\": \"101010110101\",\n \"13#11\": \"101010110110\",\n \"9#11b13\": \"101010111010\",\n \"m9#5\": \"101100001010\",\n madd9: \"101100010000\",\n mM9: \"101100010001\",\n m9: \"101100010010\",\n m69: \"101100010100\",\n m13: \"101100010110\",\n mMaj9b6: \"101100011001\",\n m9b5: \"101100100010\",\n m11A: \"101101001010\",\n m11: \"101101010010\",\n b9sus: \"110001010010\",\n \"11b9\": \"110001010010\",\n \"7sus4b9b13\": \"110001011010\",\n alt7: \"110010000010\",\n \"7#5b9\": \"110010001010\",\n Maddb9: \"110010010000\",\n M7b9: \"110010010001\",\n \"7b9\": \"110010010010\",\n \"13b9\": \"110010010110\",\n \"7b9b13\": \"110010011010\",\n \"7#5b9#11\": \"110010101010\",\n \"7b9#11\": \"110010110010\",\n \"13b9#11\": \"110010110110\",\n \"7b9b13#11\": \"110010111010\",\n mb6b9: \"110100001000\",\n \"7b9#9\": \"110110010010\"\n};\n\n// src/scalesAndChords.ts\nvar DEFAULT_OCTAVE = 4;\nvar sharpToFlatMap = {\n \"C#\": \"Db\",\n \"D#\": \"Eb\",\n \"F#\": \"Gb\",\n \"G#\": \"Ab\",\n \"A#\": \"Bb\",\n \"CB\": \"B\",\n \"FB\": \"E\",\n \"E#\": \"F\",\n \"B#\": \"C\"\n};\nfunction sharpToFlat(root) {\n return sharpToFlatMap[root.toUpperCase()] || root.charAt(0).toUpperCase() + root.slice(1);\n}\nvar CHROMATIC = [\n \"C\",\n \"Db\",\n \"D\",\n \"Eb\",\n \"E\",\n \"F\",\n \"Gb\",\n \"G\",\n \"Ab\",\n \"A\",\n \"Bb\",\n \"B\"\n];\nfunction getChromatic(root, octave) {\n const index = CHROMATIC.indexOf(root);\n if (index === -1) {\n throw new Error(`${root} is not a valid root note`);\n }\n const o1 = CHROMATIC.map((n) => n + octave);\n const o2 = CHROMATIC.map((n) => n + (octave + 1));\n const c = o1.concat(o2);\n return c.slice(index);\n}\nvar scaleMap = scaleMaps_default;\nvar chordMap = chordMaps_default;\nfunction _getNotesForScaleOrChord({ scale: scale2, chord: chord2 }) {\n const input = scale2 || chord2;\n const SCALE_OR_CHORD = scale2 ? \"scale\" : \"chord\";\n if (typeof input !== \"string\") {\n throw new Error(`${input} is not a valid input for ${SCALE_OR_CHORD}`);\n }\n const rootOctaveScale = input.trim();\n const indexOfFirstSpace = rootOctaveScale.indexOf(\" \");\n let scaleOrChord;\n let rootOctave;\n if (indexOfFirstSpace === -1) {\n scaleOrChord = rootOctaveScale.slice(1);\n rootOctave = rootOctaveScale[0];\n if (rootOctaveScale[1] === \"b\" || rootOctaveScale[1] === \"#\") {\n scaleOrChord = rootOctaveScale.slice(2);\n rootOctave += rootOctaveScale[1];\n }\n } else {\n scaleOrChord = rootOctaveScale.slice(indexOfFirstSpace === -1 ? 1 : indexOfFirstSpace + 1);\n rootOctave = rootOctaveScale.slice(0, indexOfFirstSpace);\n }\n const root = sharpToFlat(rootOctave.replace(/\\d/g, \"\"));\n const octaveNumber = rootOctave.replace(/\\D/g, \"\");\n const octave = octaveNumber !== \"\" ? +rootOctave.replace(/\\D/g, \"\") : DEFAULT_OCTAVE;\n if (isNaN(octave)) {\n throw new Error(`${rootOctave[0]} does not have a valid octave`);\n }\n if (!scaleMap[scaleOrChord] && !chordMap[scaleOrChord]) {\n throw new Error(`${rootOctaveScale} is not a valid ${SCALE_OR_CHORD}`);\n }\n const chroma = getChromatic(root, octave);\n const acc = [];\n let p1 = 0, p2 = 0;\n const map = scale2 ? scaleMap : chordMap;\n while (p1 < map[scaleOrChord].length) {\n if (map[scaleOrChord][p1] === \"1\") {\n acc.push(chroma[p2]);\n }\n p1++;\n p2++;\n }\n return acc;\n}\nfunction inlineChord(rootChord_Oct) {\n const B9SUS = \"b9sus\";\n let root, chord2, octave = DEFAULT_OCTAVE;\n if (rootChord_Oct.includes(B9SUS)) {\n chord2 = B9SUS;\n root = rootChord_Oct.slice(0, rootChord_Oct.indexOf(B9SUS));\n } else {\n root = rootChord_Oct[0];\n chord2 = rootChord_Oct.slice(1);\n if (rootChord_Oct[1] === \"b\" || rootChord_Oct[1] === \"#\") {\n root += rootChord_Oct[1];\n chord2 = rootChord_Oct.slice(2);\n }\n }\n if (rootChord_Oct.includes(\"_\")) {\n octave = +rootChord_Oct.split(\"_\")[1];\n chord2 = chord2.slice(0, chord2.indexOf(\"_\"));\n }\n return _getNotesForScaleOrChord({ chord: root + octave + \" \" + chord2 });\n}\nfunction chords() {\n return Object.keys(chordMap);\n}\nfunction scales() {\n return Object.keys(scaleMap);\n}\nfunction chord(chord2) {\n return _getNotesForScaleOrChord({ chord: chord2 });\n}\nfunction scale(scale2) {\n return _getNotesForScaleOrChord({ scale: scale2 });\n}\nfunction getIndicesFromScale(scaleOrBitmap) {\n const str = scaleMap[scaleOrBitmap] || scaleOrBitmap;\n const intervals = [];\n for (let i = 0; i < str.length; i++) {\n if (str[i] === \"1\") {\n intervals.push(i);\n }\n }\n intervals.push(12);\n return intervals;\n}\nexport {\n chord,\n chords,\n getIndicesFromScale,\n inlineChord,\n scale,\n scales\n};\n","import { chord, inlineChord } from 'harmonics';\nimport type { PatternElement } from './types';\n\n/**\n * Take a string input and check if it s a note name or not\n * @param {String} str Note name e.g. c4\n * @return {Boolean} Return true for c4 or return false for something like CM\n */\nexport const isNote = (str: string): boolean =>\n /^[a-gA-G](?:#|b)?\\d$/.test(str);\n\n/**\n * Take a String input such as xxx[xx[xx]]\n * and return an Array as ['x', 'x', 'x', ['x', 'x', ['x', 'x']]]\n * @param {String} str\n * @return {Array}\n */\nexport const expandStr = (str: string): PatternElement[] => {\n str = JSON.stringify(str.split(''));\n str = str.replace(/,\"\\[\",/g, ', [');\n str = str.replace(/\"\\[\",/g, '[');\n str = str.replace(/,\"\\]\"/g, ']');\n return JSON.parse(str);\n};\n\n/**\n * Basic Array randomizer\n * @param {Array} arr\n * @param {boolean} fullShuffle Ensure no elements remain in old place\n * @return {Array}\n */\nexport const shuffle = <T>(arr: T[], fullShuffle = true): T[] => {\n const lastIndex: number = arr.length - 1;\n\n // Shuffle algorithm by Richard Durstenfeld (Donald E. Knuth), also Ronald Fisher and Frank Yates.\n // \"Full Shuffle\" Modification to ensure no elements remain in their original place (by taking each element once\n // and swapping with any remaining elements)\n arr.forEach((el, idx: number) => {\n if (idx >= lastIndex) {\n // No shuffling last element\n // One before last is always swapped with last at the end of the loop\n // Since previous swaps can move last element into other places, there is still a random shuffle of last element\n return;\n }\n // Swap el with one of the higher elements randomly\n const rnd = fullShuffle\n ? // Pick random number from idx+1 to lastIndex (Modified algorithm, (N-1)! combinations)\n // Math.random -> [0, 1) -> [0, lastIndex-idx ) --floor-> [0, lastIndex-idx-1]\n // rnd = [0, lastIndex-idx-1] + 1 + idx = [1 + idx, lastIndex]\n // (Original algorithm would pick rnd = [idx, lastIndex], thus any element could arrive back into its slot)\n Math.floor(Math.random() * (lastIndex - idx)) + 1 + idx\n : // Pick random number from idx to lastIndex (Unmodified Richard Durstenfeld, N! combinations)\n Math.floor(Math.random() * (lastIndex + 1 - idx)) + idx;\n arr[idx] = arr[rnd];\n arr[rnd] = el;\n });\n\n return arr;\n};\n\n/**\n * Pick one item randomly from an array and return it\n * @param arr\n */\nexport const pickOne = <T = unknown>(arr: T[]): T =>\n arr[Math.floor(Math.random() * arr.length)];\n\n/**\n * Boolean generator\n */\nexport const dice = (): boolean => !!Math.round(Math.random());\n\n/** Type guard: check if a caught value has a string `message` property. */\nexport const errorHasMessage = (x: unknown): x is { message: string } => {\n return (\n typeof x === 'object' &&\n x !== null &&\n 'message' in x &&\n typeof (x as { message: unknown }).message === 'string'\n );\n};\n\n/**\n * 'el' could be an inlineChord() e.g. Cmaj7 or Dbsus2_5\n * or a chord() e.g. 'C3 M'\n */\nexport const convertChordToNotes = (el: string): string[] => {\n // Try both inlineChord() and chord()\n let c1: string[] | undefined;\n let c2: string[] | undefined;\n let e1: unknown;\n let e2: unknown;\n try {\n c1 = inlineChord(el);\n } catch (e) {\n e1 = e;\n }\n try {\n c2 = chord(el.replace(/_/g, ' ')); // chord() is not friendly to underscores\n } catch (e) {\n e2 = e;\n }\n\n if (!e1 && !e2) {\n // Both inlineChord() and chord() have result\n if (c1!.toString() !== c2!.toString()) {\n throw new Error(`Chord ${el} cannot decode, guessing ${c1} or ${c2}`);\n }\n return c1!;\n } // else\n if (!e1) {\n return c1!;\n } // else\n if (!e2) {\n return c2!;\n } // else\n\n // Give up, last try:\n return chord(el);\n};\n\n/**\n * Normalize a note, chord name, or array of notes into a string array.\n * Single notes become `['C4']`, chord names are expanded via harmonics.\n */\nexport const convertChordsToNotes = (\n el: string | (string | string[])[]\n): string[] => {\n if (typeof el === 'string' && isNote(el as string)) {\n // A note needs to be an array so that it can accomodate chords or single notes with a single interface\n return [el];\n }\n\n if (Array.isArray(el)) {\n // This could be a chord provided as an array or an array of arrays\n el.forEach(n => {\n // This could be a chord provided as an array\n if (Array.isArray(n)) {\n // TODO: Can we convert it to something useful?\n // make sure it uses valid notes\n n.forEach(n1 => {\n if (typeof n1 !== 'string' || !isNote(n1)) {\n throw new TypeError('array of arrays must comprise valid notes');\n }\n });\n // throw new TypeError('cannot decode array of arrays');\n } else if (typeof n !== 'string' || !isNote(n)) {\n // make sure it uses valid notes\n throw new TypeError('array must comprise valid notes');\n }\n });\n\n return el as string[];\n // ? return el as (string | string[])[];\n }\n\n if (!Array.isArray(el)) {\n const c = convertChordToNotes(el);\n if (c?.length) {\n return c;\n }\n }\n\n throw new Error(`Chord ${el} not found`);\n};\n\n/** Return a random integer from 0 to `num` (inclusive). */\nexport const randomInt = (num = 1): number => Math.round(Math.random() * num);\n","import { inlineChord } from 'harmonics';\nimport type { ArpParams } from './types';\nimport { errorHasMessage } from './utils';\n\nconst DEFAULT_OCTAVE = 4;\n\n/**\n * Take an array and fill it with it s own elements in the next octave till it s of the specified `len`\n * @param {Array} arr e.g. ['a4', 'b4']\n * @param {Number} e.g. len 4\n * @return {Array} e.g. ['a4', 'b4', 'a5', 'b5']\n */\nconst fillArr = (arr: string[], len: number): string[] => {\n const bumpOctave = (el: string): string => {\n if (!el) {\n throw new Error('Empty element');\n }\n const note = el.replace(/\\d/, '');\n const oct = el.replace(/\\D/g, '') || DEFAULT_OCTAVE;\n if (!note) {\n throw new Error('Incorrect note');\n }\n return note + (+oct + 1);\n };\n\n // Create a couple of chord arrays with bumped octaves\n // so that something like [c3, e3, g4] turns into [c4, e4, g5] and [c5, e5, g6]\n const arr1 = arr.map(bumpOctave);\n const arr2 = arr1.map(bumpOctave);\n const finalArr = [...arr, ...arr1, ...arr2];\n\n // Slice and return only as much as required\n return finalArr.slice(0, len);\n};\n\n/**\n *\n * @param chordsOrParams a string that denotes space (comma?) separated chords to be used or an object with additional properties\n * By default, if this is a string, the count of notes generated is 8 and the order is ascending.\n * For instance arp('CM FM') will result in an array of notes [C4, E4, G4, F4, A4, C4, C5, E5]\n * You can even provide Params as an object.\n * For e.g. arp({count: 8, order: '10325476', chords: 'FM_4 Gm7b5_4 AbM_4 Bbm_4 Cm_5 DbM_5 EbM_5})\n */\nexport const arp = (chordsOrParams: string | ArpParams): string[] => {\n let finalArr: string[] = [];\n const params: ArpParams = {\n count: 4,\n order: '0123',\n chords: '',\n };\n\n if (typeof chordsOrParams === 'string') {\n params.chords = chordsOrParams;\n } else {\n if (chordsOrParams.order?.match(/\\D/g)) {\n throw new TypeError('Invalid value for order');\n }\n\n if (chordsOrParams.count > 8 || chordsOrParams.count < 2) {\n throw new TypeError('Invalid value for count');\n }\n\n // Provision a order for the notes in case only count was provided\n if (chordsOrParams.count && !chordsOrParams.order) {\n params.order = Array.from(Array(chordsOrParams.count).keys()).join('');\n }\n Object.assign(params, chordsOrParams);\n }\n\n // Chords can be passed as a string, e.g. 'CM_4 FM_4'\n // or as an array of notes arrays e.g. [['C3', 'E3', 'G3', 'B3'], ['F3', 'A3', 'C4', 'E4']]\n if (typeof params.chords === 'string') {\n const chordsArr: string[] = params.chords.split(' ');\n chordsArr.forEach((c, i) => {\n try {\n const filledArr = fillArr(inlineChord(c), params.count);\n // reorder the filledArr as per params.order\n const reorderedArr = (params.order as string)\n .split('')\n .map((idx: string) => filledArr[Number(idx)]);\n finalArr = [...finalArr, ...reorderedArr];\n } catch (_e) {\n throw new Error(\n `Cannot decode chord ${i + 1} \"${c}\" in given \"${params.chords}\"`\n );\n }\n });\n } else if (Array.isArray(params.chords)) {\n params.chords.forEach((c, i) => {\n try {\n const filledArr = fillArr(c as string[], params.count);\n // reorder the filledArr as per params.order\n const reorderedArr = (params.order as string)\n .split('')\n .map((idx: string) => filledArr[Number(idx)]);\n finalArr = [...finalArr, ...reorderedArr];\n } catch (e) {\n throw new Error(\n `${errorHasMessage(e) ? e.message : e} in chord ${i + 1} \"${c}\"`\n );\n }\n });\n } else {\n throw new TypeError('Invalid value for chords');\n }\n\n return finalArr;\n};\n","import type { ChannelParams, SynthParams } from '../types';\nimport { errorHasMessage } from '../utils';\n\n/**\n * Check Tone.js object loaded state and either invoke `resolve` right away, or attach to and wait using Tone onload cb.\n * It's an ugly hack that reaches into Tone's internal ._buffers or ._buffer to insert itself into .onload() callback.\n * Tone has different ways to pull the onload callback from within to the API, so this implementation is very brittle.\n * The sole reason for its existence is to handle async loaded state of Tone instruments that we allow to pass in from outside.\n * If that option is eliminated, then this hacky function can be killed (or re-implemented via public onload API)\n * @param toneObject Tone.js object (will work with non-Tone objects that have same loaded/onload properties)\n * @param resolve onload callback\n */\nexport function checkToneObjLoaded(\n toneObject: ToneLoadable,\n resolve: () => void\n): void {\n const skipRecursion = toneObject instanceof Tone.Sampler; // Sampler has a Map of ToneAudioBuffer, and our method to find inner .onload() does not work since there is no single one.\n\n if ('loaded' in toneObject) {\n if (toneObject.loaded) {\n resolve();\n return;\n }\n if (skipRecursion) {\n return;\n }\n // Try Recursion into inner objects:\n let handled = false;\n ['buffer', '_buffer', '_buffers'].forEach(key => {\n if (key in toneObject) {\n checkToneObjLoaded(toneObject[key] as ToneLoadable, resolve);\n handled = true;\n }\n });\n if (handled) {\n return;\n }\n }\n\n // Check object type if it has load/onload (and _buffers or _buffer), then call resolve()\n // The list was created for Tone@14.8.0 by grepping and reviewing the source code.\n // Known objecs to have:\n const hasOnload =\n toneObject instanceof Tone.ToneAudioBuffer ||\n toneObject instanceof Tone.ToneBufferSource ||\n // Falback for \"future\" objects\n ('loaded' in toneObject && 'onload' in toneObject);\n\n if (!hasOnload) {\n // This is not a good assumption. E.g. it does not work for Tone.ToneAudioBuffers\n resolve();\n } else {\n const oldOnLoad = toneObject.onload;\n toneObject.onload = () => {\n if (oldOnLoad && typeof oldOnLoad === 'function') {\n toneObject.onload = oldOnLoad;\n oldOnLoad();\n }\n resolve();\n };\n }\n}\n\n/** Clone a Tone instrument into a different audio context, waiting for it to load. */\nexport function recreateToneObjectInContext(\n toneObject: ToneInstrument,\n context: ToneAudioContext\n): Promise<ToneInstrument> {\n context = context || Tone.getContext();\n\n return new Promise<ToneInstrument>((resolve, _reject) => {\n if (toneObject instanceof Tone.PolySynth) {\n const newObj = new (Tone as unknown as ToneDynamic)[\n toneObject._dummyVoice.name\n ]({\n ...toneObject.get(),\n context,\n });\n checkToneObjLoaded(newObj as ToneLoadable, () => resolve(newObj));\n } else if (toneObject instanceof Tone.Player) {\n const newObj = new Tone.Player({\n url: toneObject._buffer,\n context,\n onload: () =>\n checkToneObjLoaded(newObj as ToneLoadable, () => resolve(newObj)),\n } as Record<string, unknown>);\n } else if (toneObject instanceof Tone.Sampler) {\n const { attack, curve, release, volume } = toneObject.get();\n const paramsFromSampler = {\n attack,\n curve,\n release,\n volume,\n };\n const paramsFromBuffers = {\n baseUrl: toneObject._buffers.baseUrl,\n urls: Object.fromEntries(toneObject._buffers._buffers.entries()),\n };\n const newObj = new Tone.Sampler({\n ...paramsFromSampler,\n ...paramsFromBuffers,\n context,\n onload: () =>\n checkToneObjLoaded(newObj as unknown as ToneLoadable, () =>\n resolve(newObj)\n ),\n } as Record<string, unknown>);\n } else {\n const newObj = new (Tone as unknown as ToneDynamic)[toneObject.name]({\n ...toneObject.get(),\n context,\n onload: () =>\n checkToneObjLoaded(newObj as ToneLoadable, () => resolve(newObj)),\n });\n checkToneObjLoaded(newObj as ToneLoadable, () => resolve(newObj));\n }\n });\n}\n\nexport interface InstrumentResult {\n instrument: ToneInstrument;\n external?: ExternalOutput;\n}\n\n/**\n * Create an instrument from channel params. The instrument is available\n * synchronously on the returned object; `initPromise` resolves once the\n * instrument is fully loaded, recreated in the correct context, and\n * volume-adjusted.\n */\nexport function createInstrument(\n context: ToneAudioContext,\n params: ChannelParams,\n channelMeta: { idx: number | string; name: string }\n): {\n instrument: ToneInstrument;\n external?: ExternalOutput;\n initPromise: Promise<ToneInstrument>;\n} {\n let instrument!: ToneInstrument;\n let external: ExternalOutput | undefined;\n\n context = context || Tone.getContext();\n\n const loadPromise = new Promise<void>((resolve, reject) => {\n /*\n * 1. The params object can be used to pass a sample (sound source) OR a synth(Synth/FMSynth/AMSynth etc) or samples.\n * Scribbletune will then create a Tone.js Player or Tone.js Instrument or Tone.js Sampler respectively\n * 2. It can also be used to pass a Tone.js Player object or instrument that was created elsewhere\n * (mostly by Scribbletune itself in the channel creation method)\n **/\n\n if (params.synth) {\n if (params.instrument) {\n throw new Error(\n 'Either synth or instrument can be provided, but not both.'\n );\n }\n if ((params.synth as SynthParams).synth) {\n const synthName = (params.synth as SynthParams).synth;\n const preset = (params.synth as SynthParams).preset || {};\n instrument = new (Tone as unknown as ToneDynamic)[synthName]({\n ...preset,\n context,\n // Use onload for cases when synthName calls out Tone.Sample/Player/Sampler.\n // It could be a universal way to load Tone.js instruments.\n onload: () => checkToneObjLoaded(instrument, resolve),\n // This onload is ignored in all synths. Therefore we call checkToneObjLoaded() again below.\n // It is safe to call resolve() multiple times for Promise<void>\n });\n checkToneObjLoaded(instrument, resolve);\n } else {\n instrument = params.synth as unknown as ToneInstrument; // TODO: This is dangerous by-reference assignment.\n console.warn(\n 'The \"synth\" parameter with instrument will be deprecated in the future. Please use the \"instrument\" parameter instead.'\n );\n // params.synth describing the Tone[params.synth.synth] is allowed.\n checkToneObjLoaded(instrument, resolve);\n }\n } else if (typeof params.instrument === 'string') {\n instrument = new (Tone as unknown as ToneDynamic)[\n params.instrument as string\n ]({ context });\n checkToneObjLoaded(instrument, resolve);\n } else if (params.instrument) {\n instrument = params.instrument; // TODO: This is dangerous by-reference assignment.\n checkToneObjLoaded(instrument, resolve);\n } else if (params.sample || params.buffer) {\n instrument = new Tone.Player({\n url: params.sample || params.buffer,\n context,\n onload: () => checkToneObjLoaded(instrument, resolve),\n });\n } else if (params.samples) {\n instrument = new Tone.Sampler({\n urls: params.samples,\n context,\n onload: () => checkToneObjLoaded(instrument, resolve),\n });\n } else if (params.sampler) {\n instrument = params.sampler; // TODO: This is dangerous by-reference assignment.\n checkToneObjLoaded(instrument, resolve);\n } else if (params.player) {\n instrument = params.player; // TODO: This is dangerous by-reference assignment.\n checkToneObjLoaded(instrument, resolve);\n } else if (params.external) {\n external = { ...params.external }; // Sanitize object by shallow clone\n instrument = {\n context,\n volume: { value: 0 },\n } as unknown as ToneInstrument;\n // Do not call! checkToneObjLoaded(instrument, resolve);\n\n if (params.external.init) {\n return params.external\n .init(context.rawContext)\n .then(() => {\n resolve();\n })\n .catch((e: unknown) => {\n reject(\n new Error(\n `${errorHasMessage(e) ? e.message : e} loading external output module of channel idx ${\n channelMeta.idx\n }, ${channelMeta.name ?? '(no name)'}`\n )\n );\n });\n } else {\n resolve();\n }\n } else {\n throw new Error(\n 'One of required synth|instrument|sample|sampler|samples|buffer|player|external is not provided!'\n );\n }\n\n if (!instrument) {\n throw new Error('Failed instantiating instrument from given params.');\n }\n });\n\n const initPromise = loadPromise\n .then(() => {\n // Recreate instrument in the target context if needed\n if (!external && instrument?.context !== context) {\n return recreateToneObjectInContext(instrument, context).then(newObj => {\n instrument = newObj;\n });\n }\n })\n .then(() => {\n // Adjust volume\n if (params.volume) {\n instrument.volume.value = params.volume;\n external?.setVolume?.(params.volume);\n }\n return instrument;\n });\n\n return { instrument, external, initPromise };\n}\n","import { getDuration, getNote } from '../browser-clip';\nimport type { ClipParams, SeqFn } from '../types';\n\n/** Subset of Channel properties needed by the sequence callback. */\nexport interface SequenceHost {\n instrument: ToneInstrument;\n external?: ExternalOutput;\n hasLoaded: boolean;\n clipNoteCount: number;\n}\n\n/**\n * Build the callback function for a Tone.Sequence based on the instrument type.\n * Returns a function that triggers notes/samples at each step of the sequence.\n */\nexport function buildSequenceCallback(\n params: ClipParams,\n host: SequenceHost,\n playerCb: (params: Record<string, unknown>) => void,\n eventCb: (event: string, params: Record<string, unknown>) => void\n): SeqFn {\n if (host.external) {\n const ext = host.external;\n return (time: string, el: string) => {\n if (el === 'x' || el === 'R') {\n const counter = host.clipNoteCount;\n if (host.hasLoaded) {\n const note = getNote(el, params, counter)[0] as string;\n const duration = getDuration(params, counter);\n const durSeconds = Tone.Time(duration).toSeconds();\n playerCb({ note, duration, time, counter });\n try {\n ext.triggerAttackRelease?.(note, durSeconds, time);\n } catch (e) {\n eventCb('error', { e }); // Report play errors.\n }\n }\n host.clipNoteCount++;\n }\n };\n }\n\n if (host.instrument instanceof Tone.Player) {\n return (time: string, el: string) => {\n if (el === 'x' || el === 'R') {\n const counter = host.clipNoteCount;\n if (host.hasLoaded) {\n playerCb({ note: '', duration: '', time, counter });\n try {\n host.instrument.start(time);\n } catch (e) {\n eventCb('error', { e }); // Report play errors.\n }\n }\n host.clipNoteCount++;\n }\n };\n }\n\n if (\n host.instrument instanceof Tone.PolySynth ||\n host.instrument instanceof Tone.Sampler\n ) {\n return (time: string, el: string) => {\n if (el === 'x' || el === 'R') {\n const counter = host.clipNoteCount;\n if (host.hasLoaded) {\n const note = getNote(el, params, counter) as string | string[];\n const duration = getDuration(params, counter);\n playerCb({ note, duration, time, counter });\n try {\n host.instrument.triggerAttackRelease(note, duration, time);\n } catch (e) {\n eventCb('error', { e }); // Report play errors.\n }\n }\n host.clipNoteCount++;\n }\n };\n }\n\n if (host.instrument instanceof Tone.NoiseSynth) {\n return (time: string, el: string) => {\n if (el === 'x' || el === 'R') {\n const counter = host.clipNoteCount;\n if (host.hasLoaded) {\n const duration = getDuration(params, counter);\n playerCb({ note: '', duration, time, counter });\n try {\n (host.instrument as Tone.NoiseSynth).triggerAttackRelease(\n duration,\n time\n );\n } catch (e) {\n eventCb('error', { e }); // Report play errors.\n }\n }\n host.clipNoteCount++;\n }\n };\n }\n\n return (time: string, el: string) => {\n if (el === 'x' || el === 'R') {\n const counter = host.clipNoteCount;\n if (host.hasLoaded) {\n const note = getNote(el, params, counter)[0] as string;\n const duration = getDuration(params, counter);\n playerCb({ note, duration, time, counter });\n try {\n host.instrument.triggerAttackRelease(note, duration, time);\n } catch (e) {\n eventCb('error', { e }); // Report play errors.\n }\n }\n host.clipNoteCount++;\n }\n };\n}\n","import type { ClipParams } from './types';\nimport { convertChordsToNotes, shuffle } from './utils';\n\nconst defaultParams: ClipParams = {\n notes: ['C4'],\n pattern: 'x',\n shuffle: false,\n sizzle: false,\n sizzleReps: 1,\n arpegiate: false,\n subdiv: '4n',\n amp: 100,\n accentLow: 70,\n randomNotes: null,\n offlineRendering: false,\n};\n\n/** Throw if the pattern string contains characters outside `x - _ [ ] R`. */\nexport const validatePattern = (pattern: string): void => {\n if (/[^x\\-_[\\]R]/.test(pattern)) {\n throw new TypeError(\n `pattern can only comprise x - _ [ ] R, found ${pattern}`\n );\n }\n};\n\n/**\n * Merge defaults into clip params, normalize notes/randomNotes from strings\n * to arrays, validate the pattern, and optionally shuffle notes.\n */\nexport const preprocessClipParams = (\n params: ClipParams,\n extraDefaults?: Partial<ClipParams>\n): ClipParams => {\n params = { ...defaultParams, ...extraDefaults, ...(params || {}) };\n\n // Notes: string → array\n if (typeof params.notes === 'string') {\n params.notes = params.notes.replace(/\\s{2,}/g, ' ').split(' ');\n }\n params.notes = params.notes ? params.notes.map(convertChordsToNotes) : [];\n\n // Pattern validation\n validatePattern(params.pattern);\n\n // Shuffle\n if (params.shuffle) {\n params.notes = shuffle(params.notes);\n }\n\n // Random notes preprocessing\n if (params.randomNotes && typeof params.randomNotes === 'string') {\n params.randomNotes = params.randomNotes.replace(/\\s{2,}/g, ' ').split(/\\s/);\n }\n if (params.randomNotes) {\n params.randomNotes = (params.randomNotes as string[]).map(\n convertChordsToNotes\n );\n }\n\n return params;\n};\n","import type { Channel } from './channel';\nimport { checkToneObjLoaded } from './channel/instrument-factory';\nimport {\n buildSequenceCallback,\n type SequenceHost,\n} from './channel/sequence-builder';\nimport { preprocessClipParams } from './clip-utils';\nimport type { ClipParams, PatternElement, SeqFn } from './types';\nimport { expandStr, randomInt } from './utils';\n\nconst defaultSubdiv = '4n';\nconst defaultDur = '8n';\n\n/** Get the note(s) for the current step, cycling through the notes array. */\nexport const getNote = (\n el: string,\n params: ClipParams,\n counter: number\n): string | (string | string[])[] => {\n if (el === 'R' && params.randomNotes && params.randomNotes.length > 0) {\n return params.randomNotes[randomInt(params.randomNotes.length - 1)];\n }\n if (params.notes) {\n return params.notes[counter % (params.notes.length || 1)];\n }\n return '';\n};\n\n/** Get the duration for the current step, cycling through the durations array. */\nexport const getDuration = (\n params: ClipParams,\n counter: number\n): string | number => {\n return params.durations\n ? params.durations[counter % params.durations.length]\n : params.dur || params.subdiv || defaultDur;\n};\n\n/**\n * Walk a nested pattern array and compute a flat list of note durations (in seconds).\n * Underscores (`_`) extend the previous note's duration.\n */\nexport const recursivelyApplyPatternToDurations = (\n patternArr: PatternElement[],\n length: number,\n durations: number[] = []\n): number[] => {\n patternArr.forEach(char => {\n if (typeof char === 'string') {\n if (char === 'x' || char === 'R') {\n durations.push(length);\n }\n if (char === '_' && durations.length) {\n durations[durations.length - 1] += length;\n }\n }\n if (Array.isArray(char)) {\n recursivelyApplyPatternToDurations(char, length / char.length, durations);\n }\n });\n return durations;\n};\n\n/**\n * Create a Tone.Sequence from clip parameters for live browser playback.\n * When a Channel is provided, uses its instrument. When omitted, creates a\n * standalone Tone.Player from `params.sample`.\n */\nconst generateSequence = (\n params: ClipParams,\n channel?: Channel,\n context?: ToneAudioContext\n): ToneSequence => {\n context = context || Tone.getContext();\n\n if (!params.pattern) {\n throw new Error('No pattern provided!');\n }\n\n if (!params.durations && !params.dur) {\n params.durations = recursivelyApplyPatternToDurations(\n expandStr(params.pattern),\n Tone.Ticks(params.subdiv || defaultSubdiv).toSeconds()\n );\n }\n\n let callback: SeqFn;\n\n if (channel) {\n // Channel-based path (existing behavior)\n callback = channel.getSeqFn(params);\n } else if (params.sample) {\n // Standalone sample-based path\n const player = new Tone.Player({ url: params.sample, context });\n player.toDestination();\n player.sync();\n\n const host: SequenceHost = {\n instrument: player,\n hasLoaded: false,\n clipNoteCount: 0,\n };\n\n checkToneObjLoaded(player as ToneLoadable, () => {\n host.hasLoaded = true;\n });\n\n const noop = () => {};\n callback = buildSequenceCallback(params, host, noop, noop);\n } else {\n throw new Error(\n 'Either a Channel or a sample URL must be provided to create a clip.'\n );\n }\n\n return new Tone.Sequence({\n callback,\n events: expandStr(params.pattern),\n subdivision: params.subdiv || defaultSubdiv,\n context,\n });\n};\n\n/** Calculate total duration (in seconds) of a pattern at the given subdivision. */\nexport const totalPatternDuration = (\n pattern: string,\n subdivOrLength: string | number\n): number => {\n return typeof subdivOrLength === 'number'\n ? subdivOrLength * expandStr(pattern).length\n : Tone.Ticks(subdivOrLength).toSeconds() * expandStr(pattern).length;\n};\n\n/** Compute the least common multiple of two positive integers. */\nconst leastCommonMultiple = (n1: number, n2: number): number => {\n const [smallest, largest] = n1 < n2 ? [n1, n2] : [n2, n1];\n let i = largest;\n while (i % smallest !== 0) {\n i += largest;\n }\n return i;\n};\n\n/**\n * Calculate the minimum duration (in seconds) needed to offline-render a clip\n * so that all notes cycle through completely.\n */\nexport const renderingDuration = (\n pattern: string,\n subdivOrLength: string | number,\n notes: string | (string | string[])[],\n randomNotes: undefined | null | string | (string | string[])[]\n): number => {\n const patternRegularNotesCount = pattern.split('').filter(c => {\n return c === 'x';\n }).length;\n const patternRandomNotesCount = pattern.split('').filter(c => {\n return c === 'R';\n }).length;\n const patternNotesCount = randomNotes?.length\n ? patternRegularNotesCount\n : patternRegularNotesCount + patternRandomNotesCount;\n const notesCount = notes.length || 1;\n return (\n (totalPatternDuration(pattern, subdivOrLength) / patternNotesCount) *\n leastCommonMultiple(notesCount, patternNotesCount)\n );\n};\n\nlet ongoingRenderingCounter = 0;\nlet originalContext: ToneAudioContext | undefined;\n\n/** Render a clip offline into a Tone.Player buffer for later playback. */\nconst offlineRenderClip = (params: ClipParams, duration: number) => {\n if (!originalContext) {\n originalContext = Tone.getContext();\n }\n ongoingRenderingCounter++;\n const player = new Tone.Player({ context: originalContext, loop: true });\n Tone.Offline(async (context: ToneAudioContext): Promise<void> => {\n const sequence = generateSequence(params, context as unknown as Channel);\n await Tone.loaded();\n sequence.start();\n context.transport.start();\n }, duration).then((buffer: ToneLoadable) => {\n player.buffer = buffer;\n ongoingRenderingCounter--;\n if (ongoingRenderingCounter === 0) {\n Tone.setContext(originalContext!);\n params.offlineRenderingCallback?.();\n }\n });\n player.toDestination();\n player.sync();\n return player;\n};\n\n/**\n * @param {Object}\n * @return {Tone.js Sequence Object}\n * Take a object literal that may have a Tone.js player OR instrument\n * or simply a sample or synth with a pattern and return a Tone.js sequence\n */\nexport const clip = (\n params: ClipParams,\n channel?: Channel\n): ToneSequence | ToneInstrument => {\n params = preprocessClipParams(params, { align: '1m', alignOffset: '0' });\n\n if (params.offlineRendering) {\n return offlineRenderClip(\n params,\n renderingDuration(\n params.pattern,\n params.subdiv || defaultSubdiv,\n params.notes || [],\n params.randomNotes\n )\n );\n }\n return generateSequence(params, channel, originalContext);\n};\n","import fs from 'node:fs';\nimport { File, Track } from '@scribbletune/midi';\nimport type { NoteObject } from './types';\n\n/**\n * Take an array of note objects to generate a MIDI file in the same location as this method is called\n * @param {NoteObject[]} notes Notes are in the format: {note: ['c3'], level: 127, length: 64}\n * @param {String | null} fileName If a filename is not provided, then `music.mid` is used by default\n * If `null` is passed for `fileName`, bytes are returned instead of creating a file\n * If this method is called from a browser then it will return a HTML link that you can append in your page\n * This link will enable the generated MIDI as a downloadable file.\n * @param {Number | null} bpm If a value is provided, the generated midi file will be set to this bpm value.\n */\nexport const midi = (\n notes: NoteObject[],\n fileName: string | null = 'music.mid',\n bpm?: number\n): string | HTMLAnchorElement | undefined => {\n const file = createFileFromNotes(notes, bpm);\n const bytes = file.toBytes();\n\n if (fileName === null) {\n return bytes;\n }\n\n if (!fileName.endsWith('.mid')) {\n fileName = `${fileName}.mid`;\n }\n\n if (\n typeof window !== 'undefined' &&\n window.URL &&\n typeof window.URL.createObjectURL === 'function'\n ) {\n return createDownloadLink(bytes, fileName);\n }\n\n fs.writeFileSync(fileName, bytes, 'binary');\n console.log(`MIDI file generated: ${fileName}.`);\n};\n\n/**\n * Create a downloadable link\n * @param b\n */\nconst createDownloadLink = (b: string, fileName: string): HTMLAnchorElement => {\n // Convert bytes to array buffer\n // Accepted answer on https://stackoverflow.com/questions/35038884/download-file-from-bytes-in-javascript\n const bytes = new Uint8Array(b.length);\n for (let i = 0; i < b.length; i++) {\n const ascii = b.charCodeAt(i);\n bytes[i] = ascii;\n }\n\n // Create a Blob so that we can set it up with the type of file we want (for eg MIDI)\n const blob = new Blob([bytes], { type: 'audio/midi' });\n\n // Create a link element to be used (you can use an existing link on the page as well)\n const link = document.createElement('a');\n link.href =\n (typeof window !== 'undefined' &&\n typeof window.URL !== 'undefined' &&\n typeof window.URL.createObjectURL !== 'undefined' &&\n window.URL.createObjectURL(blob)) ||\n '';\n\n // Give the downloadable file a name\n link.download = fileName;\n link.innerText = 'Download MIDI file';\n\n return link;\n};\n\n/** Build a MIDI File with a single track from the given note objects. */\nconst createFileFromNotes = (notes: NoteObject[], bpm?: number) => {\n const file = new File();\n const track = new Track();\n\n // set the track's bpm if it is provided\n if (typeof bpm === 'number') {\n track.setTempo(bpm);\n }\n\n file.addTrack(track);\n\n for (const noteObj of notes) {\n const level = noteObj.level || 127;\n // While writing chords (multiple notes per tick)\n // only the first noteOn (or noteOff) needs the complete arity of the function call\n // subsequent calls need only the first 2 args (channel and note)\n if (noteObj.note) {\n if (typeof noteObj.note === 'string') {\n track.noteOn(0, noteObj.note, noteObj.length, level); // channel, pitch(note), length, velocity\n track.noteOff(0, noteObj.note, noteObj.length, level);\n } else {\n track.addChord(0, noteObj.note, noteObj.length, level);\n }\n } else {\n track.noteOff(0, '', noteObj.length);\n }\n }\n\n return file;\n};\n","export const midi_letter_pitches: Record<string, number> = {\n a: 21,\n b: 23,\n c: 12,\n d: 14,\n e: 16,\n f: 17,\n g: 19,\n};\n\nexport const midi_pitches_letter: Record<string, string> = {\n '12': 'c',\n '13': 'c#',\n '14': 'd',\n '15': 'd#',\n '16': 'e',\n '17': 'f',\n '18': 'f#',\n '19': 'g',\n '20': 'g#',\n '21': 'a',\n '22': 'a#',\n '23': 'b',\n};\n\nexport const midi_flattened_notes: Record<string, string> = {\n 'a#': 'bb',\n 'c#': 'db',\n 'd#': 'eb',\n 'f#': 'gb',\n 'g#': 'ab',\n};\n\n/**\n * Convert a symbolic note name (e.g. \"c4\") to a numeric MIDI pitch (e.g. 60).\n */\nexport function midiPitchFromNote(n: string): number {\n const matches = /([a-g])(#+|b+)?([0-9]+)$/i.exec(n);\n if (!matches) {\n throw new Error(`Invalid note name: ${n}`);\n }\n const note = matches[1]!.toLowerCase();\n const accidental = matches[2] || '';\n const octave = parseInt(matches[3]!, 10);\n return (\n 12 * octave +\n midi_letter_pitches[note]! +\n (accidental.substring(0, 1) === '#' ? 1 : -1) * accidental.length\n );\n}\n\n/**\n * Ensure that the given argument is converted to a MIDI pitch.\n * Accepts a numeric pitch, a numeric string, or a note name.\n */\nexport function ensureMidiPitch(p: number | string): number {\n if (typeof p === 'number' || !/[^0-9]/.test(p)) {\n return parseInt(String(p), 10);\n }\n return midiPitchFromNote(p);\n}\n\n/**\n * Convert a numeric MIDI pitch value (e.g. 60) to a symbolic note name (e.g. \"c4\").\n */\nexport function noteFromMidiPitch(\n n: number,\n returnFlattened?: boolean,\n): string {\n let octave = 0;\n let noteNum = n;\n\n if (n > 23) {\n octave = Math.floor(n / 12) - 1;\n noteNum = n - octave * 12;\n }\n\n let noteName = midi_pitches_letter[String(noteNum)];\n if (!noteName) {\n throw new Error(`Invalid MIDI pitch: ${n}`);\n }\n\n if (returnFlattened && noteName.indexOf('#') > 0) {\n noteName = midi_flattened_notes[noteName]!;\n }\n\n return noteName + octave;\n}\n\n/**\n * Convert beats per minute (BPM) to microseconds per quarter note (MPQN).\n * Returns a 3-byte array.\n */\nexport function mpqnFromBpm(bpm: number): number[] {\n let mpqn = Math.floor(60000000 / bpm);\n const ret: number[] = [];\n do {\n ret.unshift(mpqn & 0xff);\n mpqn >>= 8;\n } while (mpqn);\n while (ret.length < 3) {\n ret.push(0);\n }\n return ret;\n}\n\n/**\n * Convert microseconds per quarter note (MPQN) to beats per minute (BPM).\n */\nexport function bpmFromMpqn(mpqn: number | number[]): number {\n let m: number;\n if (Array.isArray(mpqn)) {\n m = 0;\n for (let i = 0, l = mpqn.length - 1; l >= 0; ++i, --l) {\n m |= mpqn[i]! << (l * 8);\n }\n } else {\n m = mpqn;\n }\n return Math.floor(60000000 / m);\n}\n\n/**\n * Converts an array of bytes to a string of characters.\n */\nexport function codes2Str(byteArray: number[]): string {\n return String.fromCharCode(...byteArray);\n}\n\n/**\n * Converts a hex string to an array of bytes, optionally padded to finalBytes length.\n */\nexport function str2Bytes(str: string, finalBytes?: number): number[] {\n let s = str;\n if (finalBytes) {\n while (s.length / 2 < finalBytes) {\n s = '0' + s;\n }\n }\n\n const bytes: number[] = [];\n for (let i = s.length - 1; i >= 0; i = i - 2) {\n const chars = i === 0 ? s[i]! : s[i - 1]! + s[i]!;\n bytes.unshift(parseInt(chars, 16));\n }\n\n return bytes;\n}\n\n/**\n * Translates number of ticks to MIDI variable-length quantity format.\n */\nexport function translateTickTime(ticks: number): number[] {\n let buffer = ticks & 0x7f;\n let t = ticks >> 7;\n\n while (t) {\n buffer <<= 8;\n buffer |= (t & 0x7f) | 0x80;\n t = t >> 7;\n }\n\n const bList: number[] = [];\n while (true) {\n bList.push(buffer & 0xff);\n if (buffer & 0x80) {\n buffer >>= 8;\n } else {\n break;\n }\n }\n return bList;\n}\n\n/** Aggregated Util object for backwards compatibility */\nexport const Util = {\n midi_letter_pitches,\n midi_pitches_letter,\n midi_flattened_notes,\n midiPitchFromNote,\n ensureMidiPitch,\n noteFromMidiPitch,\n mpqnFromBpm,\n bpmFromMpqn,\n codes2Str,\n str2Bytes,\n translateTickTime,\n};\n","/** Channel voice message status bytes */\nexport const MidiEventType = {\n NOTE_OFF: 0x80,\n NOTE_ON: 0x90,\n AFTER_TOUCH: 0xa0,\n CONTROLLER: 0xb0,\n PROGRAM_CHANGE: 0xc0,\n CHANNEL_AFTERTOUCH: 0xd0,\n PITCH_BEND: 0xe0,\n} as const;\n\nexport type MidiEventTypeValue =\n (typeof MidiEventType)[keyof typeof MidiEventType];\n\n/** Meta event type bytes */\nexport const MetaEventType = {\n SEQUENCE: 0x00,\n TEXT: 0x01,\n COPYRIGHT: 0x02,\n TRACK_NAME: 0x03,\n INSTRUMENT: 0x04,\n LYRIC: 0x05,\n MARKER: 0x06,\n CUE_POINT: 0x07,\n CHANNEL_PREFIX: 0x20,\n END_OF_TRACK: 0x2f,\n TEMPO: 0x51,\n SMPTE: 0x54,\n TIME_SIG: 0x58,\n KEY_SIG: 0x59,\n SEQ_EVENT: 0x7f,\n} as const;\n\nexport type MetaEventTypeValue =\n (typeof MetaEventType)[keyof typeof MetaEventType];\n\nexport interface MidiEventParams {\n type: number;\n channel: number;\n param1: number;\n param2?: number;\n time?: number;\n}\n\nexport interface MetaEventParams {\n type: number;\n data?: number[] | number | string;\n time?: number;\n}\n\nexport interface FileConfig {\n ticks?: number;\n}\n\n/** Either a numeric MIDI pitch or a symbolic note name like \"c4\" */\nexport type PitchInput = number | string;\n","import { MidiEventType } from './types.js';\nimport type { MidiEventParams } from './types.js';\nimport { translateTickTime } from './util.js';\n\nexport class MidiEvent {\n static readonly NOTE_OFF = MidiEventType.NOTE_OFF;\n static readonly NOTE_ON = MidiEventType.NOTE_ON;\n static readonly AFTER_TOUCH = MidiEventType.AFTER_TOUCH;\n static readonly CONTROLLER = MidiEventType.CONTROLLER;\n static readonly PROGRAM_CHANGE = MidiEventType.PROGRAM_CHANGE;\n static readonly CHANNEL_AFTERTOUCH = MidiEventType.CHANNEL_AFTERTOUCH;\n static readonly PITCH_BEND = MidiEventType.PITCH_BEND;\n\n time!: number[];\n type!: number;\n channel!: number;\n param1!: number;\n param2: number | undefined;\n\n constructor(params: MidiEventParams) {\n this.setTime(params.time);\n this.setType(params.type);\n this.setChannel(params.channel);\n this.setParam1(params.param1);\n if (params.param2 !== undefined) {\n this.setParam2(params.param2);\n }\n }\n\n setTime(ticks?: number): void {\n this.time = translateTickTime(ticks || 0);\n }\n\n setType(type: number): void {\n if (type < MidiEvent.NOTE_OFF || type > MidiEvent.PITCH_BEND) {\n throw new Error('Trying to set an unknown event: ' + type);\n }\n this.type = type;\n }\n\n setChannel(channel: number): void {\n if (channel < 0 || channel > 15) {\n throw new Error('Channel is out of bounds.');\n }\n this.channel = channel;\n }\n\n setParam1(p: number): void {\n this.param1 = p;\n }\n\n setParam2(p: number): void {\n this.param2 = p;\n }\n\n toBytes(): number[] {\n const byteArray: number[] = [];\n const typeChannelByte = this.type | (this.channel & 0xf);\n\n byteArray.push(...this.time);\n byteArray.push(typeChannelByte);\n byteArray.push(this.param1);\n\n if (this.param2 !== undefined && this.param2 !== null) {\n byteArray.push(this.param2);\n }\n\n return byteArray;\n }\n}\n","import { MetaEventType } from './types.js';\nimport type { MetaEventParams } from './types.js';\nimport { translateTickTime } from './util.js';\n\nexport class MetaEvent {\n static readonly SEQUENCE = MetaEventType.SEQUENCE;\n static readonly TEXT = MetaEventType.TEXT;\n static readonly COPYRIGHT = MetaEventType.COPYRIGHT;\n static readonly TRACK_NAME = MetaEventType.TRACK_NAME;\n static readonly INSTRUMENT = MetaEventType.INSTRUMENT;\n static readonly LYRIC = MetaEventType.LYRIC;\n static readonly MARKER = MetaEventType.MARKER;\n static readonly CUE_POINT = MetaEventType.CUE_POINT;\n static readonly CHANNEL_PREFIX = MetaEventType.CHANNEL_PREFIX;\n static readonly END_OF_TRACK = MetaEventType.END_OF_TRACK;\n static readonly TEMPO = MetaEventType.TEMPO;\n static readonly SMPTE = MetaEventType.SMPTE;\n static readonly TIME_SIG = MetaEventType.TIME_SIG;\n static readonly KEY_SIG = MetaEventType.KEY_SIG;\n static readonly SEQ_EVENT = MetaEventType.SEQ_EVENT;\n\n time: number[];\n type: number;\n data: number[] | number | string | undefined;\n\n constructor(params: MetaEventParams) {\n this.time = translateTickTime(0);\n this.type = 0;\n this.setTime(params.time);\n this.setType(params.type);\n this.setData(params.data);\n }\n\n setTime(ticks?: number): void {\n this.time = translateTickTime(ticks || 0);\n }\n\n setType(t: number): void {\n this.type = t;\n }\n\n setData(d?: number[] | number | string): void {\n this.data = d;\n }\n\n toBytes(): number[] {\n if (!this.type) {\n throw new Error('Type for meta-event not specified.');\n }\n\n const byteArray: number[] = [];\n byteArray.push(...this.time);\n byteArray.push(0xff, this.type);\n\n if (Array.isArray(this.data)) {\n byteArray.push(this.data.length);\n byteArray.push(...this.data);\n } else if (typeof this.data === 'number') {\n byteArray.push(1, this.data);\n } else if (this.data !== null && this.data !== undefined) {\n // string data\n byteArray.push(this.data.length);\n const dataBytes = this.data.split('').map((x) => x.charCodeAt(0));\n byteArray.push(...dataBytes);\n } else {\n byteArray.push(0);\n }\n\n return byteArray;\n }\n}\n","export const DEFAULT_VOLUME = 90;\nexport const DEFAULT_DURATION = 128;\nexport const DEFAULT_CHANNEL = 0;\n","import { MidiEvent } from './event.js';\nimport { MetaEvent } from './meta-event.js';\nimport { ensureMidiPitch, mpqnFromBpm, str2Bytes } from './util.js';\nimport { DEFAULT_VOLUME } from './constants.js';\nimport type { PitchInput } from './types.js';\n\nexport class Track {\n static readonly START_BYTES = [0x4d, 0x54, 0x72, 0x6b];\n static readonly END_BYTES = [0x00, 0xff, 0x2f, 0x00];\n\n events: Array<MidiEvent | MetaEvent>;\n\n constructor(config?: { events?: Array<MidiEvent | MetaEvent> }) {\n this.events = config?.events ?? [];\n }\n\n addEvent(event: MidiEvent | MetaEvent): this {\n this.events.push(event);\n return this;\n }\n\n addNoteOn(\n channel: number,\n pitch: PitchInput,\n time?: number,\n velocity?: number,\n ): this {\n this.events.push(\n new MidiEvent({\n type: MidiEvent.NOTE_ON,\n channel: channel,\n param1: ensureMidiPitch(pitch),\n param2: velocity || DEFAULT_VOLUME,\n time: time || 0,\n }),\n );\n return this;\n }\n\n addNoteOff(\n channel: number,\n pitch: PitchInput,\n time?: number,\n velocity?: number,\n ): this {\n this.events.push(\n new MidiEvent({\n type: MidiEvent.NOTE_OFF,\n channel: channel,\n param1: ensureMidiPitch(pitch),\n param2: velocity || DEFAULT_VOLUME,\n time: time || 0,\n }),\n );\n return this;\n }\n\n addNote(\n channel: number,\n pitch: PitchInput,\n dur?: number,\n time?: number,\n velocity?: number,\n ): this {\n this.addNoteOn(channel, pitch, time, velocity);\n if (dur) {\n this.addNoteOff(channel, pitch, dur, velocity);\n }\n return this;\n }\n\n addChord(\n channel: number,\n chord: PitchInput[],\n dur?: number,\n velocity?: number,\n ): this {\n if (!Array.isArray(chord) || chord.length === 0) {\n throw new Error('Chord must be a non-empty array of pitches');\n }\n chord.forEach((note) => {\n this.addNoteOn(channel, note, 0, velocity);\n });\n chord.forEach((note, index) => {\n if (index === 0) {\n this.addNoteOff(channel, note, dur);\n } else {\n this.addNoteOff(channel, note);\n }\n });\n return this;\n }\n\n setInstrument(channel: number, instrument: number, time?: number): this {\n this.events.push(\n new MidiEvent({\n type: MidiEvent.PROGRAM_CHANGE,\n channel: channel,\n param1: instrument,\n time: time || 0,\n }),\n );\n return this;\n }\n\n setTempo(bpm: number, time?: number): this {\n this.events.push(\n new MetaEvent({\n type: MetaEvent.TEMPO,\n data: mpqnFromBpm(bpm),\n time: time || 0,\n }),\n );\n return this;\n }\n\n setTimeSignature(\n numerator: number,\n denominator: number,\n time?: number,\n ): this {\n const ddlog2 = Math.log2(denominator);\n if (ddlog2 !== Math.floor(ddlog2)) {\n throw new Error(\n 'Time signature denominator must be an exact power of 2!',\n );\n }\n this.events.push(\n new MetaEvent({\n type: MetaEvent.TIME_SIG,\n data: [numerator & 0xff, Math.floor(ddlog2) & 0xff, 0x18, 0x08],\n time: time || 0,\n }),\n );\n return this;\n }\n\n setKeySignature(\n accidentals: number,\n minor?: boolean,\n time?: number,\n ): this {\n this.events.push(\n new MetaEvent({\n type: MetaEvent.KEY_SIG,\n data: [accidentals & 0xff, minor ? 1 : 0],\n time: time || 0,\n }),\n );\n return this;\n }\n\n toBytes(): number[] {\n let trackLength = 0;\n const eventBytes: number[] = [];\n const startBytes = Track.START_BYTES;\n const endBytes = Track.END_BYTES;\n\n this.events.forEach((event) => {\n const bytes = event.toBytes();\n trackLength += bytes.length;\n eventBytes.push(...bytes);\n });\n\n trackLength += endBytes.length;\n\n const lengthBytes = str2Bytes(trackLength.toString(16), 4);\n\n return startBytes.concat(lengthBytes, eventBytes, endBytes);\n }\n\n // Aliases for fluent API\n declare noteOn: Track['addNoteOn'];\n declare noteOff: Track['addNoteOff'];\n declare note: Track['addNote'];\n declare chord: Track['addChord'];\n declare instrument: Track['setInstrument'];\n declare tempo: Track['setTempo'];\n declare timeSignature: Track['setTimeSignature'];\n declare keySignature: Track['setKeySignature'];\n}\n\n// Prototype-level aliases (no per-instance overhead)\nTrack.prototype.noteOn = Track.prototype.addNoteOn;\nTrack.prototype.noteOff = Track.prototype.addNoteOff;\nTrack.prototype.note = Track.prototype.addNote;\nTrack.prototype.chord = Track.prototype.addChord;\nTrack.prototype.instrument = Track.prototype.setInstrument;\nTrack.prototype.tempo = Track.prototype.setTempo;\nTrack.prototype.timeSignature = Track.prototype.setTimeSignature;\nTrack.prototype.keySignature = Track.prototype.setKeySignature;\n","import { Track } from './track.js';\nimport { codes2Str, str2Bytes } from './util.js';\nimport type { FileConfig } from './types.js';\n\nexport class File {\n static readonly HDR_CHUNKID = 'MThd';\n static readonly HDR_CHUNK_SIZE = '\\x00\\x00\\x00\\x06';\n static readonly HDR_TYPE0 = '\\x00\\x00';\n static readonly HDR_TYPE1 = '\\x00\\x01';\n\n ticks: number;\n tracks: Track[];\n\n constructor(config?: FileConfig) {\n const c = config || {};\n if (c.ticks !== undefined) {\n if (typeof c.ticks !== 'number') {\n throw new Error('Ticks per beat must be a number!');\n }\n if (c.ticks <= 0 || c.ticks >= 1 << 15 || c.ticks % 1 !== 0) {\n throw new Error('Ticks per beat must be an integer between 1 and 32767!');\n }\n }\n this.ticks = c.ticks || 128;\n this.tracks = [];\n }\n\n addTrack(): Track;\n addTrack(track: Track): this;\n addTrack(track?: Track): Track | this {\n if (track) {\n this.tracks.push(track);\n return this;\n } else {\n const newTrack = new Track();\n this.tracks.push(newTrack);\n return newTrack;\n }\n }\n\n toBytes(): string {\n const trackCount = this.tracks.length.toString(16);\n\n let bytes = File.HDR_CHUNKID + File.HDR_CHUNK_SIZE;\n\n if (parseInt(trackCount, 16) > 1) {\n bytes += File.HDR_TYPE1;\n } else {\n bytes += File.HDR_TYPE0;\n }\n\n bytes += codes2Str(str2Bytes(trackCount, 2));\n bytes += String.fromCharCode(this.ticks / 256, this.ticks % 256);\n\n this.tracks.forEach((track) => {\n bytes += codes2Str(track.toBytes());\n });\n\n return bytes;\n }\n\n toUint8Array(): Uint8Array {\n const str = this.toBytes();\n const arr = new Uint8Array(str.length);\n for (let i = 0; i < str.length; i++) {\n arr[i] = str.charCodeAt(i);\n }\n return arr;\n }\n\n toBlob(genericType?: boolean): Blob {\n return new Blob([this.toUint8Array() as BlobPart], {\n type: genericType ? 'application/octet-stream' : 'audio/x-midi',\n });\n }\n}\n","import { Util } from './util.js';\nimport { MidiEvent } from './event.js';\nimport { MetaEvent } from './meta-event.js';\nimport { Track } from './track.js';\nimport { File } from './file.js';\nimport { DEFAULT_VOLUME, DEFAULT_DURATION, DEFAULT_CHANNEL } from './constants.js';\n\n// Named exports (modern usage)\nexport { Util } from './util.js';\nexport { MidiEvent as Event, MidiEvent } from './event.js';\nexport { MetaEvent } from './meta-event.js';\nexport { Track } from './track.js';\nexport { File } from './file.js';\nexport { DEFAULT_VOLUME, DEFAULT_DURATION, DEFAULT_CHANNEL } from './constants.js';\nexport type {\n MidiEventParams,\n MetaEventParams,\n FileConfig,\n PitchInput,\n MidiEventTypeValue,\n MetaEventTypeValue,\n} from './types.js';\nexport { MidiEventType, MetaEventType } from './types.js';\n\n// Default namespace export (backwards compatibility)\nconst Midi = {\n Util,\n File,\n Track,\n Event: MidiEvent,\n MetaEvent,\n DEFAULT_VOLUME,\n DEFAULT_DURATION,\n DEFAULT_CHANNEL,\n};\n\nexport default Midi;\n","import { scale } from 'harmonics';\nimport type { NVP, ProgressionScale, TPD } from './types';\nimport { dice, pickOne } from './utils';\n\n/**\n * Get the chords that go with a given scale/mode\n * This is useful only in case you want to check what chords work with a scale/mode\n * so that you can come up with chord progressions\n * @param {String} mode e.g. major\n * @return {Array} e.g.['I', 'ii', 'iii', 'IV', 'V', 'vi', 'vii°']\n */\nexport const getChordDegrees = (mode: string): string[] => {\n const theRomans: NVP<string[]> = {\n ionian: ['I', 'ii', 'iii', 'IV', 'V', 'vi', 'vii°'],\n dorian: ['i', 'ii', 'III', 'IV', 'v', 'vi°', 'VII'],\n phrygian: ['i', 'II', 'III', 'iv', 'v°', 'VI', 'vii'],\n lydian: ['I', 'II', 'iii', 'iv°', 'V', 'vi', 'vii'],\n mixolydian: ['I', 'ii', 'iii°', 'IV', 'v', 'vi', 'VII'],\n aeolian: ['i', 'ii°', 'III', 'iv', 'v', 'VI', 'VII'],\n locrian: ['i°', 'II', 'iii', 'iv', 'V', 'VI', 'vii'],\n 'melodic minor': ['i', 'ii', 'III+', 'IV', 'V', 'vi°', 'vii°'],\n 'harmonic minor': ['i', 'ii°', 'III+', 'iv', 'V', 'VI', 'vii°'],\n };\n theRomans.major = theRomans.ionian;\n theRomans.minor = theRomans.aeolian;\n\n return theRomans[mode] || [];\n};\n\nconst idxByDegree: NVP<number> = {\n i: 0,\n ii: 1,\n iii: 2,\n iv: 3,\n v: 4,\n vi: 5,\n vii: 6,\n};\n\n/**\n * Get a chord name from degree\n * @param {String} roman e.g. ii OR ii° OR V7\n * @return {String} e.g. m OR m7b5 OR Maj7\n */\nconst getChordName = (roman: string): string => {\n // remove any non character\n const str = roman.replace(/\\W/g, '');\n let prefix = 'M';\n // check if it s lowercase\n if (str.toLowerCase() === str) {\n prefix = 'm';\n }\n if (roman.indexOf('°') > -1) {\n return `${prefix}7b5`;\n }\n if (roman.indexOf('+') > -1) {\n return `${prefix}#5`;\n }\n\n if (roman.indexOf('7') > -1) {\n return prefix === 'M' ? 'maj7' : 'm7';\n }\n\n return prefix;\n};\n\n/**\n * Take the specified scale and degrees and return the chord names for them\n * These can be used as the value for the `notes` param of the `clip` method\n * @param {String} noteOctaveScale e.g. 'C4 major'\n * @param {String} chordDegress e.g. 'I IV V IV'\n * @return {String} e.g. 'CM FM GM FM'\n */\nexport const getChordsByProgression = (\n noteOctaveScale: string,\n chordDegress: string\n): string => {\n // Set the octave if missing\n // For example if the method was called with `C major` instead of `C4 major`, then add the 4\n const noteOctaveScaleArr = noteOctaveScale.split(' ');\n if (!noteOctaveScaleArr[0].match(/\\d/)) {\n noteOctaveScaleArr[0] += '4';\n noteOctaveScale = noteOctaveScaleArr.join(' ');\n }\n\n // Get the scale from the given note and scale/mode combination\n const mode = scale(noteOctaveScale);\n const chordDegreesArr = chordDegress.replace(/\\s*,+\\s*/g, ' ').split(' ');\n // Now we have something like ['i', 'ii', 'IV']\n // Convert it to a chord family such as ['Cm', 'Dm', 'FM']\n const chordFamily = chordDegreesArr.map(roman => {\n const chordName = getChordName(roman); // e.g. m\n // get the index to be used by removing any digit or non alphabet character\n const scaleId = idxByDegree[roman.replace(/\\W|\\d/g, '').toLowerCase()]; // e.g. 0\n // get the note itself\n const note = mode[scaleId]; // e.g. C\n // get the octave of the note;\n const oct = note.replace(/\\D+/, ''); // e.g. 4\n // now get the chord\n return `${note.replace(/\\d/, '') + chordName}_${oct}`;\n });\n\n return chordFamily.toString().replace(/,/g, ' ');\n};\n\n/** Create a progression generator that follows tonic -> predominant -> dominant flow. */\nconst getProgFactory = ({ T, P, D }: TPD) => {\n return (count = 4) => {\n const chords = [];\n\n // Push root/tonic\n chords.push(pickOne(T));\n\n let i = 1;\n\n // Pick a predominant\n if (i < count - 1) {\n chords.push(pickOne(P));\n i++;\n }\n\n // Try another predominant\n if (i < count - 1 && dice()) {\n chords.push(pickOne(P));\n i++;\n }\n\n // /////// 4 or more//////////\n if (i < count - 1) {\n // Pick a dominant\n chords.push(pickOne(D));\n i++;\n }\n\n if (i < count - 1) {\n // Pick a predominant\n chords.push(pickOne(P));\n i++;\n }\n\n if (i < count - 1) {\n // Pick a dominant\n chords.push(pickOne(D));\n i++;\n }\n\n // Pick a predominant if possible\n if (i < count - 1 && dice()) {\n chords.push(pickOne(P));\n i++;\n }\n // //////////////////////////\n\n // Fill the rest with dominant\n while (i < count) {\n chords.push(pickOne(D));\n i++;\n }\n\n return chords;\n };\n};\n\nconst M = getProgFactory({ T: ['I', 'vi'], P: ['ii', 'IV'], D: ['V'] });\nconst m = getProgFactory({ T: ['i', 'VI'], P: ['ii', 'iv'], D: ['V'] });\n\n/**\n * Generate a chord progression based on basic music theory\n * where we follow tonic to optionally predominant and then dominant\n * and then randomly to predominant and continue this till we reach `count`\n * @param scaleType e.g. M (for major chord progression), m (for minor chord progression)\n * @param count e.g. 4\n */\nexport const progression = (\n scaleType: ProgressionScale,\n count = 4\n): string[] => {\n if (scaleType === 'major' || scaleType === 'M') {\n return M(count);\n }\n\n if (scaleType === 'minor' || scaleType === 'm') {\n return m(count);\n }\n\n return [];\n};\n","import type { ChannelParams } from '../types';\nimport { recreateToneObjectInContext } from './instrument-factory';\n\n/** Create effects from channel params and chain them onto the instrument. */\nexport function initEffects(\n instrument: ToneInstrument,\n context: ToneAudioContext,\n params: ChannelParams\n): Promise<void> {\n context = context || Tone.getContext();\n\n const createEffect = (effect: string | ToneNode): Promise<ToneNode> => {\n return new Promise<ToneNode>((resolve, _reject) => {\n if (typeof effect === 'string') {\n resolve(\n new (Tone as unknown as ToneDynamic)[effect]({\n context,\n }) as unknown as ToneNode\n );\n } else if (effect.context !== context) {\n return recreateToneObjectInContext(\n effect as unknown as ToneInstrument,\n context\n );\n } else {\n resolve(effect);\n }\n }).then(effectOut => {\n return effectOut.toDestination();\n });\n };\n\n const startEffect = (eff: ToneNode) => {\n return typeof eff.start === 'function' ? eff.start() : eff;\n };\n\n const toArray = <T>(someVal: T | T[] | undefined): T[] => {\n if (!someVal) {\n return [];\n }\n if (Array.isArray(someVal)) {\n return someVal;\n }\n return [someVal];\n };\n\n const effectsIn = toArray(params.effects);\n if (params.external) {\n if (effectsIn.length !== 0) {\n throw new Error('Effects cannot be used with external output');\n }\n return Promise.resolve();\n }\n\n return Promise.all(effectsIn.map(createEffect))\n .then(results => results.map(startEffect))\n .then(effects => {\n instrument.chain(...effects).toDestination();\n });\n}\n","import { clip } from './browser-clip';\nimport { initEffects } from './channel/effects-chain';\nimport { createInstrument } from './channel/instrument-factory';\nimport { buildSequenceCallback } from './channel/sequence-builder';\nimport type {\n ChannelParams,\n ClipParams,\n EventFn,\n PlayerObserverFn,\n SeqFn,\n} from './types';\nimport { errorHasMessage } from './utils';\n\n/**\n * Get the next logical position to play in the session\n * Tone has a build-in method `Tone.Transport.nextSubdivision('4n')`\n * but I think it s better to round off as follows for live performance\n */\nconst getNextPos = (\n clip: null | { align?: string; alignOffset?: string }\n): number | ToneTicksValue => {\n const transportPosTicks = Tone.Transport.ticks;\n // If we are still in the first beat (bar 0, beat 0), start immediately\n if (transportPosTicks < Tone.Ticks('4n').toTicks()) {\n return 0;\n }\n\n // Else set it to the next aligned position\n const align = clip?.align || '1m';\n const alignOffset = clip?.alignOffset || '0';\n const alignTicks: number = Tone.Ticks(align).toTicks();\n const alignOffsetTicks: number = Tone.Ticks(alignOffset).toTicks();\n const nextPosTicks = Tone.Ticks(\n Math.floor(transportPosTicks / alignTicks + 1) * alignTicks +\n alignOffsetTicks\n );\n return nextPosTicks;\n};\n\n/**\n * Channel\n * A channel is made up of a Tone.js Player/Instrument, one or more\n * Tone.js sequences (known as clips in Scribbletune)\n * & optionally a set of effects (with or without presets)\n *\n * API:\n * clips -> Get all clips for this channel\n * addClip -> Add a new clip to the channel\n * startClip -> Start a clip at the provided index\n * stopClip -> Stop a clip at the provided index\n * activeClipIdx -> Get the clip that is currently playing\n */\nexport class Channel {\n idx: number | string;\n name: string;\n activePatternIdx: number;\n channelClips: (ToneSequence | null)[];\n clipNoteCount: number;\n counterResetTask: number | undefined;\n instrument!: ToneInstrument;\n external: ExternalOutput | undefined;\n initializerTask: Promise<void>;\n hasLoaded: boolean;\n hasFailed: boolean | Error;\n private eventCbFn: EventFn | undefined;\n private playerCbFn: PlayerObserverFn | undefined;\n constructor(params: ChannelParams) {\n this.idx = params.idx || 0;\n this.name = params.name || `ch ${params.idx}`;\n this.activePatternIdx = -1;\n this.channelClips = [];\n this.clipNoteCount = 0;\n\n // Filter out unrequired params and create clip params object\n\n const { clips, samples, sample, synth, ...params1 } = params;\n\n const { external, sampler, buffer, ...params2 } = params1;\n\n const { player, instrument, volume, ...params3 } = params2;\n\n const { eventCb, playerCb, effects, ...params4 } = params3;\n const { context = Tone.getContext(), ...originalParamsFiltered } = params4;\n\n this.eventCbFn = eventCb;\n this.playerCbFn = playerCb;\n\n // Async section\n this.hasLoaded = false;\n this.hasFailed = false;\n const result = createInstrument(context, params, {\n idx: this.idx,\n name: this.name,\n });\n this.instrument = result.instrument;\n this.external = result.external;\n this.initializerTask = result.initPromise.then(finalInstrument => {\n this.instrument = finalInstrument;\n return initEffects(this.instrument, context, params);\n });\n // End Async section\n\n // Sync section\n let clipsFailed: { message: string } | false = false;\n try {\n (params.clips ?? []).forEach((c: ClipParams, i: number) => {\n try {\n this.addClip({\n ...c,\n ...originalParamsFiltered,\n });\n } catch (e) {\n // Annotate the error with Clip info\n throw new Error(\n `${errorHasMessage(e) ? e.message : e} in clip ${i + 1}`\n );\n }\n }, this);\n } catch (e) {\n clipsFailed = e as { message: string }; // Stash the error\n }\n // End Sync section\n\n // Reconcile sync section with async section\n this.initializerTask\n .then(() => {\n if (clipsFailed) {\n throw clipsFailed;\n }\n this.hasLoaded = true;\n this.eventCb('loaded', {}); // Report async load completion.\n })\n .catch(e => {\n this.hasFailed = e;\n this.eventCb('error', { e }); // Report async errors.\n });\n }\n\n /** Set the global transport tempo in BPM. */\n static setTransportTempo(valueBpm: number): void {\n Tone.Transport.bpm.value = valueBpm;\n }\n\n /** Resume the audio context and start the global transport. */\n static startTransport(): void {\n Tone.start();\n Tone.Transport.start();\n }\n\n /**\n * Stop the global transport.\n * @param deleteEvents - If true (default), cancels all scheduled transport events.\n */\n static stopTransport(deleteEvents = true): void {\n Tone.Transport.stop();\n if (deleteEvents) {\n // Delete all events in the Tone.Transport\n Tone.Transport.cancel();\n }\n }\n\n /** Set the volume (in dB) of this channel's instrument and external output. */\n setVolume(volume: number): void {\n if (this.instrument) {\n this.instrument.volume.value = volume;\n }\n\n if (this.external) {\n this.external.setVolume?.(volume);\n }\n }\n\n /**\n * Start the clip at the given index, stopping any other active clip first.\n * @param idx - Clip index in this channel\n * @param position - Transport time to start at; defaults to the next aligned position\n */\n startClip(idx: number, position?: number | string | ToneTicksValue): void {\n const clip = this.channelClips[idx];\n position = position || (position === 0 ? 0 : getNextPos(clip));\n // Stop any other currently running clip\n if (this.activePatternIdx > -1 && this.activePatternIdx !== idx) {\n this.stopClip(this.activePatternIdx, position);\n }\n\n if (clip && clip.state !== 'started') {\n // We need to schedule that for just before when clip?.start(position) events start coming.\n this.counterResetTask = Tone.Transport.scheduleOnce(\n (/* time: Tone.Seconds */) => {\n this.clipNoteCount = 0;\n },\n position\n );\n\n this.activePatternIdx = idx;\n clip?.start(position);\n }\n }\n\n /**\n * Stop the clip at the given index.\n * @param idx - Clip index in this channel\n * @param position - Transport time to stop at; defaults to the next aligned position\n */\n stopClip(idx: number, position?: number | string | ToneTicksValue): void {\n const clip = this.channelClips[idx];\n position = position || (position === 0 ? 0 : getNextPos(clip));\n clip?.stop(position);\n if (idx === this.activePatternIdx) {\n this.activePatternIdx = -1;\n }\n }\n\n /**\n * Add a clip to this channel. If the clip has a pattern, a Tone.Sequence is\n * created; otherwise an empty (null) slot is reserved.\n * @param clipParams - Clip configuration\n * @param idx - Slot index; defaults to the next available position\n */\n addClip(clipParams: ClipParams, idx?: number): void {\n idx = idx || this.channelClips.length;\n if (clipParams.pattern) {\n this.channelClips[idx as number] = clip(\n {\n ...clipParams,\n },\n this\n ) as ToneSequence;\n // Pass certain clipParams into getNextPos()\n const seq = this.channelClips[idx as number];\n if (seq && clipParams.align) seq.align = clipParams.align;\n if (seq && clipParams.alignOffset)\n seq.alignOffset = clipParams.alignOffset;\n } else {\n // Allow creation of empty clips\n this.channelClips[idx as number] = null;\n }\n }\n\n /**\n * @param {Object} ClipParams clip parameters\n * @return {Function} function that can be used as the callback in Tone.Sequence https://tonejs.github.io/docs/Sequence\n */\n getSeqFn(params: ClipParams): SeqFn {\n return buildSequenceCallback(\n params,\n this,\n p => this.playerCb(p),\n (e, p) => this.eventCb(e, p)\n );\n }\n\n /** Invoke the user-provided event callback, if set. */\n private eventCb(event: string, params: Record<string, unknown>): void {\n if (typeof this.eventCbFn === 'function') {\n params.channel = this;\n this.eventCbFn(event, params);\n }\n }\n\n /** Invoke the user-provided player observer callback, if set. */\n private playerCb(params: Record<string, unknown>): void {\n if (typeof this.playerCbFn === 'function') {\n params.channel = this;\n this.playerCbFn(params);\n }\n }\n\n /** All clips (sequences) belonging to this channel. */\n get clips(): (ToneSequence | null)[] {\n return this.channelClips;\n }\n\n /** Index of the currently playing clip, or -1 if none. */\n get activeClipIdx(): number {\n return this.activePatternIdx;\n }\n}\n","import { Channel } from './channel';\nimport type { ChannelParams, ChannelPattern, PlayParams } from './types';\n\n/**\n * A Session manages multiple Channels and coordinates clip playback\n * across them, similar to a scene/row in a DAW.\n */\nexport class Session {\n sessionChannels: Channel[];\n\n /** Create a session, optionally pre-populated with channels. */\n constructor(arr: ChannelParams[]) {\n arr = arr || [];\n this.sessionChannels = arr.map((ch: ChannelParams, i: number) => {\n // Make sure ch.idx is not empty and unique in this.sessionChannels\n ch.idx = ch.idx || i;\n ch.idx = this.uniqueIdx(this.sessionChannels, ch.idx);\n return new Channel(ch);\n });\n }\n\n /** Return a unique channel index, generating a new one if `idx` is taken or missing. */\n uniqueIdx(channels: Channel[], idx?: string | number): string | number {\n if (!channels) {\n return idx || 0;\n }\n // Channel idx's\n const idxs = channels.reduce((acc: (string | number)[], c) => {\n return (!acc.find(i => i === c.idx) && acc.concat(c.idx)) || acc;\n }, []);\n\n if (!idx || idxs.find(i => i === idx)) {\n let newIdx = channels.length;\n while (idxs.find(i => i === newIdx)) {\n newIdx = newIdx + 1;\n }\n return newIdx;\n }\n\n return idx;\n }\n\n /** Create a new channel with a unique index and add it to the session. */\n createChannel(ch: ChannelParams): Channel {\n // Make sure ch.idx is unique in this.sessionChannels\n ch.idx = this.uniqueIdx(this.sessionChannels, ch.idx);\n const newChannel = new Channel(ch);\n this.sessionChannels.push(newChannel);\n return newChannel;\n }\n\n /** All channels in this session. */\n get channels(): Channel[] {\n return this.sessionChannels;\n }\n\n /** Set the global transport tempo in BPM. */\n setTransportTempo(valueBpm: number): void {\n Channel.setTransportTempo(valueBpm);\n }\n\n /** Resume the audio context and start the global transport. */\n startTransport(): void {\n Channel.startTransport();\n }\n\n /**\n * Stop the global transport.\n * @param deleteEvents - If true (default), cancels all scheduled transport events.\n */\n stopTransport(deleteEvents = true): void {\n Channel.stopTransport(deleteEvents);\n }\n\n /** Start the clip at the given index across all channels simultaneously. */\n startRow(idx: number): void {\n this.sessionChannels.forEach((ch: Channel) => {\n ch.startClip(idx);\n });\n }\n\n /**\n * Schedule clip playback across channels using a song-structure pattern.\n * Each channel pattern is a string where each character is a clip index\n * (or `-` for silence, `_` to sustain the previous clip).\n */\n play(params: PlayParams): void {\n const channelPatterns = params.channelPatterns;\n const clipDuration = params.clipDuration || '4:0:0';\n const clipDurationInSeconds: number = Tone.Time(clipDuration).toSeconds();\n\n const stopClips = (clips: ToneSequence[], time: number) => {\n clips.forEach(c => {\n c.stop(time);\n });\n };\n\n const startClips = (\n channelIdx: string | number,\n clipIdx: string,\n time: number\n ): ToneSequence[] => {\n if (clipIdx === '-') return [];\n const clips = this.channels\n .filter(c => c.idx === channelIdx)\n .map(c => c.clips[Number(clipIdx)])\n .filter((c): c is ToneSequence => c != null);\n for (const c of clips) c.start(time);\n return clips;\n };\n\n channelPatterns.forEach(({ channelIdx, pattern }: ChannelPattern) => {\n let clips: ToneSequence[] = [];\n let time = 0;\n let prevClipIdx = '-';\n pattern.split('').forEach((clipIdx: string) => {\n if (clipIdx !== prevClipIdx && clipIdx !== '_') {\n stopClips(clips, time);\n clips = startClips(channelIdx, clipIdx, time);\n }\n prevClipIdx = clipIdx;\n time += clipDurationInSeconds;\n });\n stopClips(clips, time);\n });\n }\n}\n"],"mappings":"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","names":["DEFAULT_OCTAVE","_a","_a","chord","fs","chords","clip"]}
package/package.json CHANGED
@@ -1,32 +1,37 @@
1
1
  {
2
2
  "name": "scribbletune",
3
- "version": "5.2.0",
3
+ "version": "5.4.0",
4
4
  "description": "Create music with JavaScript and Node.js!",
5
- "main": "./dist/index.js",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
6
7
  "types": "./dist/index.d.ts",
7
8
  "files": [
8
9
  "dist"
9
10
  ],
11
+ "module": "./dist/index.js",
10
12
  "exports": {
11
- ".": "./dist/index.js",
12
- "./browser": "./dist/browser.js"
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.js",
16
+ "require": "./dist/index.cjs"
17
+ },
18
+ "./browser": {
19
+ "import": "./dist/browser.js",
20
+ "require": "./dist/browser.cjs"
21
+ }
13
22
  },
14
23
  "scripts": {
15
- "clean": "rm -rf dist && rm -rf docs && rm -rf lib && rm -f browser.js* index.d.ts index.js* typedoc-out.json",
24
+ "clean": "rm -rf dist lib",
16
25
  "doc": "npx typedoc --out docs src/ src/typings.d.ts",
17
26
  "doc:json": "npx typedoc --json typedoc-out.json src",
18
- "lint": "eslint src tests -c .eslintrc --ext .ts",
19
- "lint:fix": "eslint src tests -c .eslintrc --ext .ts --fix",
20
- "test": "jest --config ./jest.config.js",
21
- "test:coverage": "jest --config ./jest.config.js --coverage",
22
- "test:watch": "jest --config ./jest.config.js --watch",
23
- "build:node": "npx webpack --mode=production",
24
- "build:browser": "cross-env TARGET=browser npx webpack --mode=production",
25
- "build:cdn": "cross-env TARGET=cdn npx webpack --mode=production",
26
- "build": "npm run build:node && npm run build:browser && npm run build:cdn",
27
- "watch:browser": "cross-env TARGET=browser npx webpack --watch --mode=development",
28
- "watch:cdn": "cross-env TARGET=cdn npx webpack --watch --mode=production",
29
- "watch:node": "npx webpack --watch --mode=production",
27
+ "lint": "biome check src tests",
28
+ "lint:fix": "biome check --write src tests",
29
+ "format": "biome format --write src tests",
30
+ "test": "vitest run",
31
+ "test:coverage": "vitest run --coverage",
32
+ "test:watch": "vitest",
33
+ "build": "tsup",
34
+ "dev": "tsup --watch",
30
35
  "prepare": "npm run build",
31
36
  "package": "npm t && npm run build && npm pack",
32
37
  "rebuild": "rm -rf node_modules && rm package-lock.json && npm i && npm run build",
@@ -39,25 +44,12 @@
39
44
  "harmonics": "^1.1.2"
40
45
  },
41
46
  "devDependencies": {
42
- "@types/jest": "^27.0.1",
43
- "@types/node": "^12.19.15",
44
- "@typescript-eslint/eslint-plugin": "^6.21.0",
45
- "@typescript-eslint/parser": "^6.21.0",
46
- "cross-env": "^7.0.3",
47
- "dts-bundle": "^0.7.3",
48
- "eslint": "^8.57.1",
49
- "eslint-config-prettier": "^8.3.0",
50
- "eslint-loader": "^4.0.2",
51
- "eslint-plugin-prettier": "^4.0.0",
52
- "jest": "^27.2.0",
53
- "prettier": "^2.4.0",
54
- "ts-jest": "^27.0.5",
55
- "ts-loader": "^9.2.5",
56
- "ts-node": "^10.2.0",
57
- "typedoc": "^0.21.5",
47
+ "@biomejs/biome": "^2.3.15",
48
+ "@types/node": "^22.15.0",
49
+ "tsup": "^8.5.1",
50
+ "typedoc": "^0.28.17",
58
51
  "typescript": "^5.9.3",
59
- "webpack": "^5.53.0",
60
- "webpack-cli": "^4.8.0"
52
+ "vitest": "^4.0.18"
61
53
  },
62
54
  "repository": {
63
55
  "type": "git",
@@ -74,17 +66,14 @@
74
66
  ],
75
67
  "author": "Walmik Deshpande",
76
68
  "license": "MIT",
77
- "runkitExampleFilename": "runkit.js",
69
+ "runkitExampleFilename": "runkit.cjs",
78
70
  "bugs": {
79
71
  "url": "https://github.com/scribbletune/scribbletune/issues"
80
72
  },
81
73
  "engines": {
82
- "node": ">16.x.x"
74
+ "node": ">=18"
83
75
  },
84
76
  "publishConfig": {
85
77
  "registry": "https://registry.npmjs.org/"
86
- },
87
- "eslintConfig": {
88
- "extends": ".eslintrc"
89
78
  }
90
79
  }
package/dist/lib/arp.d.ts DELETED
@@ -1,10 +0,0 @@
1
- import type { ArpParams } from './types';
2
- /**
3
- *
4
- * @param chordsOrParams a string that denotes space (comma?) separated chords to be used or an object with additional properties
5
- * By default, if this is a string, the count of notes generated is 8 and the order is ascending.
6
- * For instance arp('CM FM') will result in an array of notes [C4, E4, G4, F4, A4, C4, C5, E5]
7
- * You can even provide Params as an object.
8
- * For e.g. arp({count: 8, order: '10325476', chords: 'FM_4 Gm7b5_4 AbM_4 Bbm_4 Cm_5 DbM_5 EbM_5})
9
- */
10
- export declare const arp: (chordsOrParams: string | ArpParams) => string[];
@@ -1,14 +0,0 @@
1
- import { Channel } from './channel';
2
- import type { ClipParams } from './types';
3
- export declare const getNote: (el: string, params: ClipParams, counter: number) => string | (string | string[])[];
4
- export declare const getDuration: (params: ClipParams, counter: number) => string | number | undefined;
5
- export declare const recursivelyApplyPatternToDurations: (patternArr: string[], length: number, durations?: number[]) => number[];
6
- export declare const totalPatternDuration: (pattern: string, subdivOrLength: string | number) => number;
7
- export declare const renderingDuration: (pattern: string, subdivOrLength: string | number, notes: string | (string | string[])[], randomNotes: undefined | null | string | (string | string[])[]) => number;
8
- /**
9
- * @param {Object}
10
- * @return {Tone.js Sequence Object}
11
- * Take a object literal that may have a Tone.js player OR instrument
12
- * or simply a sample or synth with a pattern and return a Tone.js sequence
13
- */
14
- export declare const clip: (params: ClipParams, channel: Channel) => any;
@@ -1,7 +0,0 @@
1
- import { scales, chords, scale, chord } from 'harmonics';
2
- import { clip } from './browser-clip';
3
- import { getChordDegrees, getChordsByProgression, progression } from './progression';
4
- import { arp } from './arp';
5
- import { Session } from './session';
6
- export * from './types';
7
- export { scale, scale as mode, scales, scales as modes, chord, chords, clip, getChordDegrees, getChordsByProgression, progression, arp, Session, };
@@ -1,61 +0,0 @@
1
- import type { ChannelParams, ClipParams, SeqFn } from './types';
2
- /**
3
- * Channel
4
- * A channel is made up of a Tone.js Player/Instrument, one or more
5
- * Tone.js sequences (known as clips in Scribbletune)
6
- * & optionally a set of effects (with or without presets)
7
- *
8
- * API:
9
- * clips -> Get all clips for this channel
10
- * addClip -> Add a new clip to the channel
11
- * startClip -> Start a clip at the provided index
12
- * stopClip -> Stop a clip at the provided index
13
- * activeClipIdx -> Get the clip that is currently playing
14
- */
15
- export declare class Channel {
16
- idx: number | string;
17
- name: string;
18
- activePatternIdx: number;
19
- channelClips: any;
20
- clipNoteCount: number;
21
- instrument: any;
22
- external: any;
23
- initializerTask: Promise<void>;
24
- hasLoaded: boolean;
25
- hasFailed: boolean | Error;
26
- private eventCbFn;
27
- private playerCbFn;
28
- private counterResetTask;
29
- constructor(params: ChannelParams);
30
- static setTransportTempo(valueBpm: number): void;
31
- static startTransport(): void;
32
- static stopTransport(deleteEvents?: boolean): void;
33
- setVolume(volume: number): void;
34
- startClip(idx: number, position?: number | string): void;
35
- stopClip(idx: number, position?: number | string): void;
36
- addClip(clipParams: ClipParams, idx?: number): void;
37
- /**
38
- * @param {Object} ClipParams clip parameters
39
- * @return {Function} function that can be used as the callback in Tone.Sequence https://tonejs.github.io/docs/Sequence
40
- */
41
- getSeqFn(params: ClipParams): SeqFn;
42
- private eventCb;
43
- private playerCb;
44
- /**
45
- * Check Tone.js object loaded state and either invoke `resolve` right away, or attach to and wait using Tone onload cb.
46
- * It's an ugly hack that reaches into Tone's internal ._buffers or ._buffer to insert itself into .onload() callback.
47
- * Tone has different ways to pull the onload callback from within to the API, so this implementation is very brittle.
48
- * The sole reason for its existence is to handle async loaded state of Tone instruments that we allow to pass in from outside.
49
- * If that option is eliminated, then this hacky function can be killed (or re-implemented via public onload API)
50
- * @param toneObject Tone.js object (will work with non-Tone objects that have same loaded/onload properties)
51
- * @param resolve onload callback
52
- */
53
- private checkToneObjLoaded;
54
- private recreateToneObjectInContext;
55
- private initOutputProducer;
56
- private initInstrument;
57
- private adjustInstrument;
58
- private initEffects;
59
- get clips(): any[];
60
- get activeClipIdx(): number;
61
- }
@@ -1,2 +0,0 @@
1
- import type { ClipParams, NoteObject } from './types';
2
- export declare const clip: (params: ClipParams) => NoteObject[];
@@ -1,7 +0,0 @@
1
- import { scales, chords, scale, chord } from 'harmonics';
2
- import { clip } from './clip';
3
- import { getChordDegrees, getChordsByProgression, progression } from './progression';
4
- import { arp } from './arp';
5
- import { midi } from './midi';
6
- export * from './types';
7
- export { scale, scale as mode, scales, scales as modes, chord, chords, clip, getChordDegrees, getChordsByProgression, progression, arp, midi, };
@@ -1,11 +0,0 @@
1
- import type { NoteObject } from './types';
2
- /**
3
- * Take an array of note objects to generate a MIDI file in the same location as this method is called
4
- * @param {NoteObject[]} notes Notes are in the format: {note: ['c3'], level: 127, length: 64}
5
- * @param {String | null} fileName If a filename is not provided, then `music.mid` is used by default
6
- * If `null` is passed for `fileName`, bytes are returned instead of creating a file
7
- * If this method is called from a browser then it will return a HTML link that you can append in your page
8
- * This link will enable the generated MIDI as a downloadable file.
9
- * @param {Number | null} bpm If a value is provided, the generated midi file will be set to this bpm value.
10
- */
11
- export declare const midi: (notes: NoteObject[], fileName?: string | null, bpm?: number | undefined) => string | HTMLAnchorElement | undefined;
@@ -1,25 +0,0 @@
1
- import type { ProgressionScale } from './types';
2
- /**
3
- * Get the chords that go with a given scale/mode
4
- * This is useful only in case you want to check what chords work with a scale/mode
5
- * so that you can come up with chord progressions
6
- * @param {String} mode e.g. major
7
- * @return {Array} e.g.['I', 'ii', 'iii', 'IV', 'V', 'vi', 'vii°']
8
- */
9
- export declare const getChordDegrees: (mode: string) => string[];
10
- /**
11
- * Take the specified scale and degrees and return the chord names for them
12
- * These can be used as the value for the `notes` param of the `clip` method
13
- * @param {String} noteOctaveScale e.g. 'C4 major'
14
- * @param {String} chordDegress e.g. 'I IV V IV'
15
- * @return {String} e.g. 'CM FM GM FM'
16
- */
17
- export declare const getChordsByProgression: (noteOctaveScale: string, chordDegress: string) => string;
18
- /**
19
- * Generate a chord progression based on basic music theory
20
- * where we follow tonic to optionally predominant and then dominant
21
- * and then randomly to predominant and continue this till we reach `count`
22
- * @param scaleType e.g. M (for major chord progression), m (for minor chord progression)
23
- * @param count e.g. 4
24
- */
25
- export declare const progression: (scaleType: ProgressionScale, count?: number) => any[];
@@ -1,14 +0,0 @@
1
- import { Channel } from './channel';
2
- import type { ChannelParams, PlayParams } from './types';
3
- export declare class Session {
4
- sessionChannels: Channel[];
5
- constructor(arr: ChannelParams[]);
6
- uniqueIdx(channels: Channel[], idx?: string | number): string | number;
7
- createChannel(ch: ChannelParams): Channel;
8
- get channels(): Channel[];
9
- setTransportTempo(valueBpm: number): void;
10
- startTransport(): void;
11
- stopTransport(deleteEvents?: boolean): void;
12
- startRow(idx: number): void;
13
- play(params: PlayParams): void;
14
- }
@@ -1,6 +0,0 @@
1
- interface ArpParams {
2
- count: number;
3
- order?: string;
4
- chords: string | any[];
5
- }
6
- export type { ArpParams };