UNPKG

beepody

Version:
323 lines (313 loc) 9.04 kB
/*! * beepody v0.3.33333333 * (c) Dylan Ferris * Released under the GPL-3.0 License. */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.beepody = {})); })(this, (function (exports) { 'use strict'; var version = '0.3.33333333'; /** * Default beep frequency in hertz. */ const DEFAULT_FREQUENCY = 440; /** * Default beep length in milliseconds. */ const DEFAULT_LENGTH = 200; /** * Character to separate notes in beep sequence URL hash. */ const NOTE_DELIMITER = '|'; /** * Character to separate parameters in notes in beep sequence URL hash. */ const PARAMETER_DELIMITER = '^'; /** * @class Tone player * @name Tone */ class Tone { ctx; gainNode; outNode; /** * Initialize a tone beeper. */ /* istanbul ignore next */ constructor() { if (typeof window !== 'undefined' && typeof window.AudioContext !== 'undefined') { this.ctx = new window.AudioContext(); this.gainNode = this.ctx.createGain(); this.gainNode.gain.value = 1 / 8; this.outNode = this.ctx.destination; this.gainNode.connect(this.outNode); } else { throw 'AudioContext is required'; } } /** * Play a beep after wait seconds, stopping after length seconds. */ /* istanbul ignore next */ beepOnBeepOff(frequency, length, wait) { const osc = this.ctx.createOscillator(); osc.type = 'square'; osc.frequency.value = frequency; osc.connect(this.gainNode); osc.start(wait); osc.stop(wait + length); } } /** * @class Beep utility * @name Beep */ class Beep { frequency; length; repeats; /** * Initialize a beep. */ constructor(frequency = DEFAULT_FREQUENCY, length = DEFAULT_LENGTH, repeats = 1) { this.frequency = frequency; this.length = length; this.repeats = repeats; } /** * The text representation. */ toString() { return `Beep(${this.frequency} ${this.length} ${this.repeats})`; } } /** * @class Beep sequence * @name BeepSequence */ class BeepSequence { beeps; tempo; /** * Initialize a beep sequence. */ constructor(beeps) { this.beeps = beeps; this.tempo = 600; } /** * Return the URL hash for the sequence. * Each note is "frequency (Hz), length (ms), repeats" separated by "|", with defaults (440 200 1). * Notes are separated by ",". */ toHash() { const notes = []; for (const beep of this.beeps) { notes.push(`${beep.frequency}${PARAMETER_DELIMITER}${beep.length}`); } return notes.join(NOTE_DELIMITER); } /** * Return the `beep` command. */ toBeepCommand() { const notes = []; for (const beep of this.beeps) { let s = `-f ${beep.frequency} -l ${beep.length}`; if (beep.repeats !== 1) { s += ` -r ${beep.repeats}`; } notes.push(s); } return `beep ${notes.join(' -n ')}`; } /** * Return the GRUB init tune. */ toGRUBInitTune() { const notes = []; let s = `play ${this.tempo}`; for (const beep of this.beeps) { notes.push(`${beep.frequency} ${beep.length / 100}`); } if (notes.length) s += ` ${notes.join(' ')}`; return s; } /** * The text representation. */ toString() { return `${this.constructor.name}(${this.toHash()})`; } /** * The length of the playtime in seconds. */ lengthInSeconds() { let s = 0; for (const beep of this.beeps) { for (let r = -1; r < beep.repeats; r++) { s += beep.length; } } return s * 0.001; } } /** * Play a beep sequence to the browser audio. */ /* istanbul ignore next */ const playBeepSequence = (bs) => { if (typeof window === 'undefined') return; let wait = 0; const tone = new Tone(); for (const beep of bs.beeps) { const seconds = beep.length * 0.001; tone.beepOnBeepOff(beep.frequency, seconds, wait); wait += seconds; } }; /** * Play the default beep. */ const playDefaultBeep = () => { playBeepSequence(new BeepSequence([new Beep()])); }; const BEEP_OPTIONS = [ ['f', 'frequency', 'FREQ'], ['l', 'length', 'LEN'], ['r', 'repeats', 'REPEATS'], ['d', 'delay', 'DELAY'], ]; const BEEP_COMMANDS = [['n', 'new', 'NEW']]; /** * Parse a Linux "beep" command. */ const parseBeepCommand = (s) => { const sequence = new BeepSequence([]); const args = s.split(/\s+/); console.assert(args.shift() === 'beep'); let beep = new Beep(); const processOption = (name, value) => { switch (name) { case 'frequency': beep.frequency = parseFloat(value); break; case 'length': beep.length = parseFloat(value); break; case 'repeats': beep.repeats = parseInt(value, 10); break; } }; const processCommand = (name) => { switch (name) { case 'new': sequence.beeps.push(beep); beep = new Beep(); break; } }; let option; for (const arg of args) { if (arg[0] === '-') { if (arg[1] === '-') { // # eg: --frequency const name = arg.substring(2); for (const opt of BEEP_OPTIONS) { if (opt[1] === name) { option = opt[1]; } } for (const opt of BEEP_COMMANDS) { if (opt[1] === name) { processCommand(opt[1]); } } } else { // # eg: -f const letter = arg[1]; for (const opt of BEEP_OPTIONS) { if (opt[0] === letter) { option = opt[1]; } } for (const opt of BEEP_COMMANDS) { if (opt[0] === letter && typeof opt[1] === 'string') { processCommand(opt[1]); } } } } else { if (option) { processOption(option, arg); } } } sequence.beeps.push(beep); return sequence; }; /** * Parse a Grub init tune "play" line. */ const parseGRUBInitTune = (s) => { const sequence = new BeepSequence([]); const args = s.split(/\s+/); console.assert(args.shift() === 'play'); sequence.tempo = parseFloat(args.shift() || '60'); let pitch; for (const arg of args) { if (pitch) { const duration = parseFloat(arg) * 100; const beep = new Beep(); beep.frequency = pitch; beep.length = duration; sequence.beeps.push(beep); pitch = null; } else { pitch = parseFloat(arg); } } return sequence; }; /** * Parse a beep sequence hash. */ const parseBeepHash = (s) => { const sequence = new BeepSequence([]); for (const note of s.split(NOTE_DELIMITER)) { const params = note .split(PARAMETER_DELIMITER) .map((s) => parseFloat(s)); const beep = new Beep(...params); sequence.beeps.push(beep); } return sequence; }; class beepody { static get version() { return version; } } exports.Beep = Beep; exports.BeepSequence = BeepSequence; exports["default"] = beepody; exports.parseBeepCommand = parseBeepCommand; exports.parseBeepHash = parseBeepHash; exports.parseGRUBInitTune = parseGRUBInitTune; exports.playBeepSequence = playBeepSequence; exports.playDefaultBeep = playDefaultBeep; exports.version = version; Object.defineProperty(exports, '__esModule', { value: true }); })); //# sourceMappingURL=index.umd.js.map