UNPKG

nesly-sound

Version:
169 lines (138 loc) 3.5 kB
var noteTiming = require('./timing') var dutyMap = require('./duty') function isSquare (channel) { return channel === ('square1' || 'square2') } function Notes (prefix) { if (!(this instanceof Notes)) { return new Notes(prefix) } this.hasLoop = { square1: false, square2: false, triangle: false, noise: false } this.code = {} this.code.square1 = prefix + 'square1:\n' this.code.square2 = prefix + 'square2:\n' this.code.triangle = prefix + 'triangle:\n' this.code.noise = prefix + 'noise:\n' this.current = null this.prev = null this.currentCode = '' this.loopCounter = 0 this.temp = { square1: '', square2: '', triangle: '', noise: '' } } Notes.prototype.note = function note (channel, notes) { this.prev = this.current this.current = channel if (this.prev && this.currentCode) { this.temp[this.prev] += this.currentCode this.currentCode = null } this.currentCode = '{loop' + this.loopCounter + '}' this.currentCode += compileNotes(notes) } Notes.prototype.square1 = function square1 (notes) { if (notes) { this.note('square1', notes) } return this } Notes.prototype.square2 = function square2 (notes) { if (notes) { this.note('square2', notes) } return this } Notes.prototype.triangle = function triangle (notes) { if (notes) { this.note('triangle', notes) } return this } Notes.prototype.noise = function noise (notes) { if (notes) { this.note('noise', notes) } return this } Notes.prototype.timing = function timing (time) { var t = noteTiming[time] this.currentCode = this.currentCode.replace('{time}', t) return this } Notes.prototype.duty = function duty (n) { if (isSquare(this.current)) { var d = dutyMap[n] || dutyMap[0] this.currentCode += '\n\t.byte duty, ' + d } return this } Notes.prototype.volumeEnvelope = function ve (e) { this.currentCode += '\n\t.byte volume_envelope, ' + e return this } Notes.prototype.blip = function blip () { this.volumeEnvelope('ve_blip') return this } Notes.prototype.fadeIn = function fadeIn () { this.volumeEnvelope('ve_fade_in') return this } Notes.prototype.staccato = function staccato () { this.volumeEnvelope('ve_short_staccato') return this } Notes.prototype.volOn = function volOn () { this.volumeEnvelope('ve_on') return this } Notes.prototype.volOff = function volOff () { this.volumeEnvelope('ve_off') return this } Notes.prototype.loop = function loop (n) { n = n || 1 var current = this.current var loopCode = '\n\t.byte set_loop1_counter, ' + n + '\n.loop:\n' var loopTemp = '{loop' + this.loopCounter + '}' if (this.hasLoop[current]) { throw new Error(current + ' has already been looped and can only loop 1 time') } this.currentCode = this.currentCode.replace(loopTemp, loopCode) this.currentCode += '\n\t.byte loop1\n\t.word .loop\n' this.hasLoop[current] = true return this } function normalize (notes) { notes = notes.map(function (note) { if (note && note.letter) { var letter = note.letter var modifier = note.modifier var octave = note.octave var out = letter if (modifier && modifier === '#') { out += 's' } out += octave return out } return note }) return notes } function compileNotes (notes) { var nn = normalize(notes) var s = nn.join(',') var ret = '\n\t.byte {time}, ' + s + '\n' return ret } module.exports = Notes