( el: string | (string | string[])[] )
| 157 | * Single notes become `['C4']`, chord names are expanded via harmonics. |
| 158 | */ |
| 159 | export const convertChordsToNotes = ( |
| 160 | el: string | (string | string[])[] |
| 161 | ): string[] => { |
| 162 | if (typeof el === 'string' && isNote(el as string)) { |
| 163 | // A note needs to be an array so that it can accomodate chords or single notes with a single interface |
| 164 | return [el]; |
| 165 | } |
| 166 | |
| 167 | if (Array.isArray(el)) { |
| 168 | // This could be a chord provided as an array or an array of arrays |
| 169 | el.forEach(n => { |
| 170 | // This could be a chord provided as an array |
| 171 | if (Array.isArray(n)) { |
| 172 | // TODO: Can we convert it to something useful? |
| 173 | // make sure it uses valid notes |
| 174 | n.forEach(n1 => { |
| 175 | if (typeof n1 !== 'string' || !isNote(n1)) { |
| 176 | throw new TypeError('array of arrays must comprise valid notes'); |
| 177 | } |
| 178 | }); |
| 179 | // throw new TypeError('cannot decode array of arrays'); |
| 180 | } else if (typeof n !== 'string' || !isNote(n)) { |
| 181 | // make sure it uses valid notes |
| 182 | throw new TypeError('array must comprise valid notes'); |
| 183 | } |
| 184 | }); |
| 185 | |
| 186 | return el as string[]; |
| 187 | // ? return el as (string | string[])[]; |
| 188 | } |
| 189 | |
| 190 | if (!Array.isArray(el)) { |
| 191 | const c = convertChordToNotes(el); |
| 192 | if (c?.length) { |
| 193 | return c; |
| 194 | } |
| 195 | } |
| 196 | |
| 197 | throw new Error(`Chord ${el} not found`); |
| 198 | }; |
| 199 | |
| 200 | /** Return a random integer from 0 to `num` (inclusive). */ |
| 201 | export const randomInt = (num = 1): number => Math.round(Math.random() * num); |
no test coverage detected