Skip to content

Instantly share code, notes, and snippets.

@LongJohnCoder
Forked from OverlappingElvis/index.js
Created December 17, 2020 17:18
Show Gist options
  • Save LongJohnCoder/363d8697db8b858c945defce673a40a4 to your computer and use it in GitHub Desktop.
Save LongJohnCoder/363d8697db8b858c945defce673a40a4 to your computer and use it in GitHub Desktop.

Revisions

  1. @OverlappingElvis OverlappingElvis revised this gist Dec 17, 2020. 1 changed file with 130 additions and 29 deletions.
    159 changes: 130 additions & 29 deletions index.js
    Original file line number Diff line number Diff line change
    @@ -1,9 +1,12 @@
    const fs = require(`fs`)
    const _ = require(`lodash`)
    const { Player } = require(`midi-player-js`)
    const blessed = require(`blessed`)
    const contrib = require(`blessed-contrib`)

    const VOWELS = _.range(5)
    const CONSONANTS = _.range(15)
    const VOICES = [`Soprano`, `Mezzo-Soprano`, `Tenor`, `Bass`]

    const player = new Player()

    @@ -15,43 +18,141 @@ const allEvents = player.getEvents()

    const MAX_TICKS = _.last(_.maxBy(allEvents, (events) => _.last(events).tick)).tick

    const parsedEvents = allEvents.map((track) => {
    const noteEventsOnly = allEvents.map(track => track.filter(event => event.name === `Note on`)).filter(track => !_.isEmpty(track))

    return track.filter(event => event.name === `Note on`).map((event) => {
    const timelines = noteEventsOnly.map((track, index) => {

    return {
    timeSeconds: (event.tick / MAX_TICKS) * songTime + (Math.random() * 0.1),
    midiPitch: event.noteNumber,
    librettoChunk: {
    vowel: {
    name: _.sample(VOWELS),
    duration: 0.20000000298023224
    },
    suffix: [
    {
    name: _.sample(CONSONANTS),
    duration: 0.10000000149011612
    }
    ]
    return {
    title: `Track ${index}`,
    x: track.map(event => event.tick),
    y: track.map(event => event.noteNumber),
    style: {
    line: _.times(3, () => Math.random() * 255)
    }
    }
    })

    const trackAssignments = [``, ``, ``, ``]

    const screen = blessed.screen()
    const grid = new contrib.grid({
    rows: 8,
    cols: 2,
    screen: screen
    })

    const trackList = grid.set(0, 0, 6, 1, contrib.table, {
    keys: true,
    columnWidth: [14, 8]
    })

    const line = grid.set(0, 1, 6, 1, contrib.line, {
    showLegend: true
    })

    const log = grid.set(6, 0, 1, 2, contrib.log)

    const save = grid.set(6, 1, 1, 2, blessed.button, {
    mouse: true,
    content: `Export`
    })

    save.on(`press`, () => {

    const parsedEvents = trackAssignments.map((trackIndex) => {

    const track = noteEventsOnly[parseInt(trackIndex, 10)]

    return track.map((event) => {

    return {
    timeSeconds: (event.tick / MAX_TICKS) * songTime + (Math.random() * 0.025 * _.sample([1, -1])),
    midiPitch: event.noteNumber,
    librettoChunk: {
    vowel: {
    name: _.sample(VOWELS),
    duration: 0.20000000298023224
    },
    suffix: [
    {
    name: _.sample(CONSONANTS),
    duration: 0.10000000149011612
    }
    ]
    }
    }
    })
    }).map((track) => {

    return {
    notes: track,
    startSuffix: [
    {
    name: _.sample(CONSONANTS),
    duration: 0.10000000149011612
    }
    ]
    }
    })
    }).filter(track => !_.isEmpty(track)).map((track) => {

    return {
    notes: track,
    startSuffix: [
    {
    name: _.sample(CONSONANTS),
    duration: 0.10000000149011612
    }
    ]
    const song = {
    theme: 1,
    parts: parsedEvents
    }

    fs.writeFile(`test.json`, JSON.stringify(song), () => {

    log.log(`Wrote song to test.json`)

    screen.render()
    })
    })

    line.setData(timelines)

    screen.key(['escape', 'q', 'C-c'], function(ch, key) {

    return process.exit(0);
    })

    const song = {
    theme: 1,
    parts: parsedEvents.reverse()
    trackList.focus()

    const setTracklistData = () => {

    trackList.setData({
    headers: [`Part`, `Track`],
    data: VOICES.map((val, index) => [val, trackAssignments[index]])
    })
    }

    fs.writeFile(`test.json`, JSON.stringify(song), () => console.log(`done`))
    setTracklistData()

    trackList.rows.on(`select`, function(event) {

    let prompt = blessed.prompt({
    left: `center`,
    top: `center`,
    height: `shrink`,
    width: `shrink`,
    border: `line`
    })

    screen.append(prompt)

    prompt.input(`Set track number`, ``, (err, value) => {

    log.log(`Assigning track ${value} to ${event.index}`)

    trackAssignments[event.index - 2] = value

    prompt = null

    setTracklistData()

    screen.render()
    })
    })

    log.log(`Started MIDI to Blob Opera.`)

    screen.render()
  2. @OverlappingElvis OverlappingElvis revised this gist Dec 16, 2020. 1 changed file with 4 additions and 4 deletions.
    8 changes: 4 additions & 4 deletions index.js
    Original file line number Diff line number Diff line change
    @@ -2,8 +2,8 @@ const fs = require(`fs`)
    const _ = require(`lodash`)
    const { Player } = require(`midi-player-js`)

    const VOWELS = [`a`, `e`, `i`, `o`, `u`]
    const CONSONANTS = [`p`, `g`, `f`, `c`, `qu`, `h`, `j`, `n`, `l`, `m`, `t`, `d`, `ch`, `r`]
    const VOWELS = _.range(5)
    const CONSONANTS = _.range(15)

    const player = new Player()

    @@ -20,7 +20,7 @@ const parsedEvents = allEvents.map((track) => {
    return track.filter(event => event.name === `Note on`).map((event) => {

    return {
    timeSeconds: (event.tick / MAX_TICKS) * songTime,
    timeSeconds: (event.tick / MAX_TICKS) * songTime + (Math.random() * 0.1),
    midiPitch: event.noteNumber,
    librettoChunk: {
    vowel: {
    @@ -51,7 +51,7 @@ const parsedEvents = allEvents.map((track) => {

    const song = {
    theme: 1,
    parts: parsedEvents
    parts: parsedEvents.reverse()
    }

    fs.writeFile(`test.json`, JSON.stringify(song), () => console.log(`done`))
  3. @OverlappingElvis OverlappingElvis revised this gist Dec 15, 2020. 1 changed file with 9 additions and 9 deletions.
    18 changes: 9 additions & 9 deletions index.js
    Original file line number Diff line number Diff line change
    @@ -39,19 +39,19 @@ const parsedEvents = allEvents.map((track) => {
    }).filter(track => !_.isEmpty(track)).map((track) => {

    return {
    notes: track
    notes: track,
    startSuffix: [
    {
    name: _.sample(CONSONANTS),
    duration: 0.10000000149011612
    }
    ]
    }
    })

    const song = {
    theme: `Festive`,
    parts: parsedEvents,
    startSuffix: [
    {
    name: _.sample(CONSONANTS),
    duration: 0.10000000149011612
    }
    ]
    theme: 1,
    parts: parsedEvents
    }

    fs.writeFile(`test.json`, JSON.stringify(song), () => console.log(`done`))
  4. @OverlappingElvis OverlappingElvis created this gist Dec 15, 2020.
    57 changes: 57 additions & 0 deletions index.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,57 @@
    const fs = require(`fs`)
    const _ = require(`lodash`)
    const { Player } = require(`midi-player-js`)

    const VOWELS = [`a`, `e`, `i`, `o`, `u`]
    const CONSONANTS = [`p`, `g`, `f`, `c`, `qu`, `h`, `j`, `n`, `l`, `m`, `t`, `d`, `ch`, `r`]

    const player = new Player()

    player.loadFile(`./test.mid`)

    const songTime = player.getSongTime()

    const allEvents = player.getEvents()

    const MAX_TICKS = _.last(_.maxBy(allEvents, (events) => _.last(events).tick)).tick

    const parsedEvents = allEvents.map((track) => {

    return track.filter(event => event.name === `Note on`).map((event) => {

    return {
    timeSeconds: (event.tick / MAX_TICKS) * songTime,
    midiPitch: event.noteNumber,
    librettoChunk: {
    vowel: {
    name: _.sample(VOWELS),
    duration: 0.20000000298023224
    },
    suffix: [
    {
    name: _.sample(CONSONANTS),
    duration: 0.10000000149011612
    }
    ]
    }
    }
    })
    }).filter(track => !_.isEmpty(track)).map((track) => {

    return {
    notes: track
    }
    })

    const song = {
    theme: `Festive`,
    parts: parsedEvents,
    startSuffix: [
    {
    name: _.sample(CONSONANTS),
    duration: 0.10000000149011612
    }
    ]
    }

    fs.writeFile(`test.json`, JSON.stringify(song), () => console.log(`done`))