New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

gameboy-sound

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

gameboy-sound - npm Package Compare versions

Comparing version 0.1.1 to 0.1.2

84

lib/gameboy-sound.js

@@ -27,3 +27,3 @@ window.AudioContext = window.AudioContext || window.webkitAudioContext;

function baseChannel(ctx, dest=ctx.destination) {
function baseChannel(/**@type{AudioContext}*/ctx, dest=ctx.destination) {
const gainNode = ctx.createGain();

@@ -43,5 +43,28 @@ gainNode.gain.setValueAtTime(0, ctx.currentTime);

/**
* Previous hz changes are tracked and applied retroactively
* to all future buffers played later on. This is to keep the
* waveforms in sync to prevent popping when a new note is
* played, making vibrato possible
*/
let prevHertzChanges = [];
/** @type{AudioBufferSourceNode} */
let currentSourceNode = null;
return function play({ buffer, rate, rateChanges=[], trigger=true, length=Infinity, volume=15, fade=0, left=true, right=true, time=0 }) {
/**
* TODO!!!
* two wrongs do make a right!
* the value passed in to "hertz" is not actually the hertz of the waveform!
* however, this function also calculates things wrong, in exactly the right way
* so it all still works...
*
* when refactoring it to use the real hertz value (maybe?),
* make sure to test with vibrato to ensure that there's no popping
*/
return function play({ buffer, hertz, hertzChanges=[], trigger=true, length=Infinity, volume=15, fade=0, left=true, right=true, time=0 }) {
// calculate playback rate(s)
prevHertzChanges = prevHertzChanges.filter(x => x.time < time);
prevHertzChanges.push({ time, hertz });
// no left/right = no sound
if (!left && !right) {

@@ -58,6 +81,19 @@ volume = 0;

sourceNode.buffer = buffer;
sourceNode.playbackRate.setValueAtTime(rate, time)
for (const x of prevHertzChanges) {
const rate = buffer.sampleRate/buffer.length/x.hertz;
sourceNode.playbackRate.setValueAtTime(rate, x.time);
}
sourceNode.loop = true;
const prevWiggles = prevHertzChanges.reduce((sum, x, i, src) => {
if (i === 0) return 0;
return (sum + (x.time-src[i-1].time) * buffer.sampleRate/buffer.length/src[i-1].hertz);
// TODO "real hertz" calculations
// const realhertz = 1/(src[i-1].hertz * buffer.duration**2);
// console.log('realh',realhertz)
// return (sum + (x.time-src[i-1].time) * realhertz);
}, 0);
const offset = prevWiggles % buffer.duration
// console.log(buffer.duration, offset);
sourceNode.connect(gainNode);
sourceNode.start(time);
sourceNode.start(time, offset);
currentSourceNode = sourceNode;

@@ -80,8 +116,11 @@ // volume + envelope + length

// rate changes
rateChanges.forEach(({ rate, time }) => {
if (rate == null) {
hertzChanges.forEach(({ hertz, time }) => {
if (hertz == null) {
gainNode.gain.cancelScheduledValues(time);
gainNode.gain.setValueAtTime(0, time);
}
else sourceNode.playbackRate.setValueAtTime(rate, time)
else {
const rate = buffer.sampleRate/buffer.length/hertz;
sourceNode.playbackRate.setValueAtTime(rate, time)
}
});

@@ -115,5 +154,10 @@ // pan

const buffer = pulseWaves[duty];
const rate = 256 / (2048-freq);
const hertz = 2 * (2048-freq);
// TODO "real hertz" calculations
// console.log(buffer.sampleRate/buffer.length, buffer.duration)
// const realhertz = 1/((2 * (2048 - freq)) * buffer.duration**2);
const rateChanges = [];
// console.log(realhertz, realhertz*buffer.duration);
const hertzChanges = [];
if (sweepFactor !== 0) {

@@ -132,12 +176,12 @@ let shadowFreq = freq;

if (shadowFreq + dFreq >= 2048) {
rateChanges.push({ time: t1, rate: null });
hertzChanges.push({ time: t1, hertz: null });
break;
}
const rate = 256 / (2048-shadowFreq);
rateChanges.push({ time: t1, rate });
const hertz = 2 * (2048-shadowFreq);
hertzChanges.push({ time: t1, hertz });
}
}
ch({ buffer, rate, rateChanges, trigger, length, volume, fade, left, right, time });
ch({ buffer, hertz, hertzChanges, trigger, length, volume, fade, left, right, time });
};

@@ -163,6 +207,7 @@ }

return function ({ samples=defaultPCM, freq=1798, trigger, length, left, right, time }) {
/** @type{AudioBuffer} */
const buffer = (lastSamples && samples.join() === lastSamples) ?
cachedBuffer :
samplesToBuffer(samples);
const rate = 256 / (2048-freq);
const hertz = (2048-freq);

@@ -172,3 +217,3 @@ lastSamples = samples.join();

ch({ buffer, rate, trigger, length, left, right, time });
ch({ buffer, hertz, trigger, length, left, right, time });
};

@@ -208,9 +253,10 @@ }

const cats = upsampleAmounts.map(n=>256*n);
cats[cats.length-1]=Infinity;
return function ({ buzzy=false, freq=3<<7, trigger, length, volume, fade, left, right, time }) {
const cats = upsampleAmounts.map(n=>256*n);
cats[cats.length-1]=Infinity;
const resampleCategory = cats.findIndex(c => freq < c);
const buffer = resampledNoiseWaves[resampleCategory][+buzzy];
const rate = 0x40 / freq * upsampleAmounts[resampleCategory];
ch({ buffer, rate, trigger, length, volume, fade, left, right, time })
const hertz = (buffer.sampleRate/buffer.length) * freq / upsampleAmounts[resampleCategory] / 0x40;
ch({ buffer, hertz, trigger, length, volume, fade, left, right, time })
};

@@ -217,0 +263,0 @@ }

{
"name": "gameboy-sound",
"version": "0.1.1",
"version": "0.1.2",
"description": "Easy 3 kB library for 98% accurate Gameboy audio",

@@ -5,0 +5,0 @@ "main": "lib/index.js",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc