Comparing version 1.1.8 to 1.2.0
{ | ||
"name": "zzfx", | ||
"version": "1.1.8", | ||
"version": "1.2.0", | ||
"description": "A Tiny JavaScript Sound FX System", | ||
@@ -5,0 +5,0 @@ "main": "ZzFX.js", |
# ZzFX - Zuper Zmall Zound Zynth | ||
## [ZzFX Sound Designer](https://killedbyapixel.github.io/ZzFX) / [ZzFX Sound Board Demo](https://codepen.io/KilledByAPixel/full/BaowKzv) | ||
# [ZzFX Sound Designer](https://killedbyapixel.github.io/ZzFX) - [Soundboard Demo](https://codepen.io/KilledByAPixel/full/BaowKzv) | ||
## ZzFX Features | ||
- Tiny synth engine with 20 controllable parameters. | ||
- Play sounds via code, no need for sound asset files. | ||
- Compatible with nearly all web browsers. | ||
- Small code footprint, the micro version is under 1 kilobyte uncompressed. | ||
- Can produce a large variety of sound effect types. | ||
- Sounds can be played with a short function call. zzfx(...[,,,,.1,,,,9]) | ||
- No additional libraries or dependencies are required. | ||
- Tiny sound generator with 20 controllable parameters | ||
- Play audio via code, no need for sound asset files | ||
- Compatible with nearly all web browsers | ||
- Small code footprint, the micro version is under 1 kilobyte uncompressed | ||
- Can produce a large variety of sound effect types | ||
- Sounds can be played with a short function call | ||
- No additional libraries or dependencies are required | ||
- Open source with MIT license, you can use this for anything! | ||
# Why Use ZzFX? | ||
- You can quickly add or change sound effects with just one line of code | ||
- Without sound asset files your game is smaller and faster for users to download | ||
- While prototyping you can use ZzFX for placeholder sound effects | ||
- For size limited game jams like [JS13K](https://js13kgames.com/), ZzFX uses very minimal overhead | ||
- ZzFX is not just for games, you can use it to easily add sounds to any website | ||
# How to Use | ||
@@ -22,7 +30,7 @@ | ||
* To play a sound just call zzfx(), something like `zzfx(...[,,,,.1,,,,9])` | ||
* Use [the ZzFX sound designer web app](https://killedbyapixel.github.io/ZzFX) to create new sounds. | ||
* Use [the ZzFX sound designer web app](https://killedbyapixel.github.io/ZzFX) to create new sounds | ||
Here are a few more examples examples... | ||
``` | ||
```javascript | ||
zzfx(...[,,925,.04,.3,.6,1,.3,,6.27,-184,.09,.17]); // Game Over | ||
@@ -36,30 +44,55 @@ zzfx(...[,,537,.02,.02,.22,1,1.59,-6.98,4.97]); // Heart | ||
## ZzFX Music | ||
## [ZzFX Music](https://keithclark.github.io/ZzFXM/) | ||
- [ZzFX now supports music via ZzFXM by Keith Clark!](https://keithclark.github.io/ZzFXM/) | ||
- Both the player and songs are super tiny and compress well. | ||
- [NoteCraft](https://killedbyapixel.github.io/NoteCraft/) can also export to ZzFXM. | ||
- Both the player and songs are super tiny and compress well | ||
- [NoteCraft](https://killedbyapixel.github.io/NoteCraft/) can also export to ZzFXM | ||
# ZzFX Micro Code | ||
Here's all the code you need to play ZzFX sounds with JavaScript! | ||
```javascript | ||
// ZzFXMicro - Zuper Zmall Zound Zynth - v1.2.0 by Frank Force ~ 880 bytes | ||
zzfxV=.3 // volume | ||
zzfx= // play sound | ||
(p=1,k=.05,b=220,e=0,r=0,t=.1,q=0,D=1,u=0,y=0,v=0,z=0,l=0,E=0,A=0,F=0,c=0,w=1,m= | ||
0,B=0,M=Math,R=44100,d=2*M.PI,G=u*=500*d/R/R,C=b*=(1-k+2*k*M.random(k=[]))*d/R,g | ||
=0,H=0,a=0,n=1,I=0,J=0,f=0,x,h)=>{e=R*e+9;m*=R;r*=R;t*=R;c*=R;y*=500*d/R**3;A*=d | ||
/R;v*=d/R;z*=R;l=R*l|0;for(h=e+m+r+t+c|0;a<h;k[a++]=f)++J%(100*F|0)||(f=q?1<q?2< | ||
q?3<q?M.sin((g%d)**3):M.max(M.min(M.tan(g),1),-1):1-(2*g/d%2+2)%2:1-4*M.abs(M. | ||
round(g/d)-g/d):M.sin(g),f=(l?1-B+B*M.sin(d*a/l):1)*(0<f?1:-1)*M.abs(f)**D*zzfxV | ||
*p*(a<e?a/e:a<e+m?1-(a-e)/m*(1-w):a<e+m+r?w:a<h-c?(h-a-c)/t*w:0),f=c?f/2+(c>a?0: | ||
(a<h-c?1:(h-a)/c)*k[a-c|0]/2):f),x=(b+=u+=y)*M.cos(A*H++),g+=x-x*E*(1-1E9*(M.sin | ||
(a)+1)%2),n&&++n>z&&(b+=v,C+=v,n=0),!l||++I%l||(b=C,u=G,n||=1);p=zzfxX. | ||
createBuffer(1,h,R);p.getChannelData(0).set(k);b=zzfxX.createBufferSource();b. | ||
buffer=p;b.connect(zzfxX.destination);b.start();return b};zzfxX=new AudioContext; | ||
``` | ||
## ZzFX UI Features | ||
- Generates random sounds from presets. | ||
- Sound list is automatically saved. | ||
- Each parameter can be modified with constraints. | ||
- Lock and mutate buttons for each parameter. | ||
- Sounds can be renamed. | ||
- Shortens code for zzfx sound calls. | ||
- Displays image of sound wave when played. | ||
- Sounds can be marked as favorites to prevent removal. | ||
- Sounds can be loaded by pasting zzfx code for easy sharing. | ||
- List of sounds can be exported and imported. | ||
- Supports drag-and-drop of exported files into sound list. | ||
- Supports saving sounds as wav files for offline playback. | ||
- Generates random sounds from presets | ||
- Sound list is automatically saved | ||
- Each parameter can be modified with constraints | ||
- Lock and mutate buttons for each parameter | ||
- Sounds can be renamed | ||
- Shortens code for zzfx sound calls | ||
- Displays image of sound wave when played | ||
- Sounds can be marked as favorites to prevent removal | ||
- Sounds can be loaded by pasting zzfx code for easy sharing | ||
- List of sounds can be exported and imported | ||
- Supports drag-and-drop of exported files into sound list | ||
- Supports saving sounds as wav files for offline playback | ||
## Games Using ZzFX | ||
- [Space Huggers](https://js13kgames.com/entries/space-huggers) | ||
- [Packabunchas](https://js13kgames.com/entries/packabunchas) | ||
- [Galaxy Rider](https://js13kgames.com/entries/galaxy-rider) | ||
- [The Adventures of Captain Callisto](https://js13kgames.com/entries/the-adventures-of-captain-callisto) | ||
- [Welcome to Space](https://js13kgames.com/entries/welcome-to-space) | ||
- [Bogus Roads](https://www.newgrounds.com/portal/view/747570) | ||
- [Note Craft](https://js13kgames.com/entries/notecraft) | ||
- [NoteCraft](https://js13kgames.com/entries/notecraft) | ||
- [The Wandering Wraith](https://js13kgames.com/entries/the-wandering-wraith) | ||
- [Bounce Back](https://www.newgrounds.com/portal/view/755171) | ||
- [Egg Time Rewind](https://killedbyapixel.itch.io/egg-time) | ||
- [Hue Jumper](https://killedbyapixel.itch.io/hue-jumper) | ||
@@ -88,3 +121,10 @@ - [Bubba's Back Room](https://js13kgames.com/entries/bubbas-back-room) | ||
- [OS13k](https://github.com/KilledByAPixel/OS13k) | ||
- [Crab Story](https://www.crabstory.io/) | ||
- [Cooking for Skully](https://github.com/gheja/js13k2022) | ||
- [Egg Time Rewind](https://js13kgames.com/entries/egg-time-rewind) | ||
- [Charon Jr.](https://js13kgames.com/entries/charon-jr) | ||
- [13](https://js13kgames.com/entries/13) | ||
- [Soul Surf](https://js13kgames.com/entries/soul-surf) | ||
- [Dead Again](https://js13kgames.com/entries/dead-again) | ||
![ZzFX Image](/favicon.png) |
@@ -1,2 +0,2 @@ | ||
// wav.js by Frank Force 2020 - https://github.com/KilledByAPixel/ZzFX | ||
// wav.js by Frank Force - https://github.com/KilledByAPixel/ZzFX | ||
@@ -3,0 +3,0 @@ export function buildWavBlob(sampleChannels, sampleRate = 44100) |
34
ZzFX.js
/* | ||
ZzFX - Zuper Zmall Zound Zynth v1.1.8 | ||
By Frank Force 2019 | ||
ZzFX - Zuper Zmall Zound Zynth v1.2.0 by Frank Force | ||
https://github.com/KilledByAPixel/ZzFX | ||
@@ -62,3 +61,3 @@ | ||
// create shared audio context | ||
x: new (window.AudioContext || webkitAudioContext), | ||
x: new AudioContext, | ||
@@ -76,4 +75,4 @@ // play a sound from zzfx paramerters | ||
// create buffer and source | ||
const buffer = this.x.createBuffer(samples.length, samples[0].length, this.sampleRate); | ||
const source = this.x.createBufferSource(); | ||
const buffer = this.x.createBuffer(samples.length, samples[0].length, this.sampleRate), | ||
source = this.x.createBufferSource(); | ||
@@ -113,9 +112,6 @@ samples.map((d,i)=> buffer.getChannelData(i).set(d)); | ||
// init parameters | ||
const PI2 = Math.PI*2; | ||
let sampleRate = this.sampleRate, | ||
sign = v => v>0?1:-1, | ||
startSlide = slide *= 500 * PI2 / sampleRate / sampleRate, | ||
startFrequency = | ||
frequency *= (1 + randomness*2*Math.random() - randomness) * PI2 / sampleRate, | ||
b=[], t=0, tm=0, i=0, j=1, r=0, c=0, s=0, f, length; | ||
let PI2 = Math.PI*2, sampleRate = this.sampleRate, sign = v => v>0?1:-1, | ||
startSlide = slide *= 500 * PI2 / sampleRate / sampleRate, | ||
startFrequency = frequency *= (1 + randomness*2*Math.random() - randomness) * PI2 / sampleRate, | ||
b=[], t=0, tm=0, i=0, j=1, r=0, c=0, s=0, f, length; | ||
@@ -171,7 +167,7 @@ // scale by sample rate | ||
if (j && ++j > pitchJumpTime) // pitch jump | ||
if (j && ++j > pitchJumpTime) // pitch jump | ||
{ | ||
frequency += pitchJump; // apply pitch jump | ||
startFrequency += pitchJump; // also apply to start | ||
j = 0; // stop pitch jump time | ||
frequency += pitchJump; // apply pitch jump | ||
startFrequency += pitchJump; // also apply to start | ||
j = 0; // stop pitch jump time | ||
} | ||
@@ -181,5 +177,5 @@ | ||
{ | ||
frequency = startFrequency; // reset frequency | ||
slide = startSlide; // reset slide | ||
j = j || 1; // reset pitch jump time | ||
frequency = startFrequency; // reset frequency | ||
slide = startSlide; // reset slide | ||
j ||= 1; // reset pitch jump time | ||
} | ||
@@ -186,0 +182,0 @@ } |
@@ -13,3 +13,3 @@ // ZzFX - Zuper Zmall Zound Zynth - Micro Edition | ||
// ZzFXMicro - Zuper Zmall Zound Zynth - v1.1.8 | ||
// ZzFXMicro - Zuper Zmall Zound Zynth - v1.2.0 by Frank Force | ||
@@ -26,7 +26,8 @@ // ==ClosureCompiler== | ||
const zzfxR = 44100; // sample rate | ||
const zzfxX = new (window.AudioContext||webkitAudioContext); // audio context | ||
const zzfxX = new AudioContext; // audio context | ||
const zzfxP = (...samples)=> // play samples | ||
{ | ||
// create buffer and source | ||
let buffer = zzfxX.createBuffer(samples.length, samples[0].length, zzfxR), source = zzfxX.createBufferSource(); | ||
let buffer = zzfxX.createBuffer(samples.length, samples[0].length, zzfxR), | ||
source = zzfxX.createBufferSource(); | ||
@@ -43,12 +44,12 @@ // copy samples to buffer and play | ||
// parameters | ||
volume = 1, randomness = .05, frequency = 220, attack = 0, sustain = 0, release = .1, shape = 0, shapeCurve = 1, slide = 0, deltaSlide = 0, pitchJump = 0, pitchJumpTime = 0, repeatTime = 0, noise = 0, modulation = 0, bitCrush = 0, delay = 0, sustainVolume = 1, decay = 0, tremolo = 0 | ||
volume = 1, randomness = .05, frequency = 220, attack = 0, sustain = 0, | ||
release = .1, shape = 0, shapeCurve = 1, slide = 0, deltaSlide = 0, | ||
pitchJump = 0, pitchJumpTime = 0, repeatTime = 0, noise = 0, modulation = 0, | ||
bitCrush = 0, delay = 0, sustainVolume = 1, decay = 0, tremolo = 0 | ||
)=> | ||
{ | ||
// init parameters | ||
let PI2 = Math.PI*2, | ||
sign = v => v>0?1:-1, | ||
startSlide = slide *= 500 * PI2 / zzfxR / zzfxR, | ||
startFrequency = frequency *= (1 + randomness*2*Math.random() - randomness) | ||
* PI2 / zzfxR, | ||
b=[], t=0, tm=0, i=0, j=1, r=0, c=0, s=0, f, length; | ||
let PI2 = Math.PI*2, sign = v => v>0?1:-1, startSlide = slide *= 500 * PI2 / zzfxR / zzfxR, | ||
startFrequency = frequency *= (1 + randomness*2*Math.random() - randomness) * PI2 / zzfxR, | ||
b=[], t=0, tm=0, i=0, j=1, r=0, c=0, s=0, f, length; | ||
@@ -104,7 +105,7 @@ // scale by sample rate | ||
if (j && ++j > pitchJumpTime) // pitch jump | ||
if (j && ++j > pitchJumpTime) // pitch jump | ||
{ | ||
frequency += pitchJump; // apply pitch jump | ||
startFrequency += pitchJump; // also apply to start | ||
j = 0; // reset pitch jump time | ||
frequency += pitchJump; // apply pitch jump | ||
startFrequency += pitchJump; // also apply to start | ||
j = 0; // reset pitch jump time | ||
} | ||
@@ -114,5 +115,5 @@ | ||
{ | ||
frequency = startFrequency; // reset frequency | ||
slide = startSlide; // reset slide | ||
j = j || 1; // reset pitch jump time | ||
frequency = startFrequency; // reset frequency | ||
slide = startSlide; // reset slide | ||
j ||= 1; // reset pitch jump time | ||
} | ||
@@ -119,0 +120,0 @@ } |
@@ -11,6 +11,19 @@ // ZzFX - Zuper Zmall Zound Zynth - Micro Edition | ||
// ZzFXMicro - Zuper Zmall Zound Zynth - v1.1.8 | ||
// ZzFXMicro - Zuper Zmall Zound Zynth - v1.2.0 by Frank Force ~ 880 bytes | ||
zzfxV=.3 // volume | ||
zzfx= // play sound | ||
(p=1,k=.05,b=220,e=0,r=0,t=.1,q=0,D=1,u=0,y=0,v=0,z=0,l=0,E=0,A=0,F=0,c=0,w=1,m=0,B=0)=>{let M=Math,R=44100,d=2*M.PI,G=u*=500*d/R/R,C=b*=(1-k+2*k*M.random(k=[]))*d/R,g=0,H=0,a=0,n=1,I=0,J=0,f=0,x,h;e=R*e+9;m*=R;r*=R;t*=R;c*=R;y*=500*d/R**3;A*=d/R;v*=d/R;z*=R;l=R*l|0;for(h=e+m+r+t+c|0;a<h;k[a++]=f)++J%(100*F|0)||(f=q?1<q?2<q?3<q?M.sin((g%d)**3):M.max(M.min(M.tan(g),1),-1):1-(2*g/d%2+2)%2:1-4*M.abs(M.round(g/d)-g/d):M.sin(g),f=(l?1-B+B*M.sin(d*a/l):1)*(0<f?1:-1)*M.abs(f)**D*p*zzfxV*(a<e?a/e:a<e+m?1-(a-e)/m*(1-w):a<e+m+r?w:a<h-c?(h-a-c)/t*w:0),f=c?f/2+(c>a?0:(a<h-c?1:(h-a)/c)*k[a-c|0]/2):f),x=(b+=u+=y)*M.cos(A*H++),g+=x-x*E*(1-1E9*(M.sin(a)+1)%2),n&&++n>z&&(b+=v,C+=v,n=0),!l||++I%l||(b=C,u=G,n=n||1);p=zzfxX.createBuffer(1,h,R);p.getChannelData(0).set(k);b=zzfxX.createBufferSource();b.buffer=p;b.connect(zzfxX.destination);b.start();return b} | ||
zzfxX=new(window.AudioContext||webkitAudioContext) // audio context | ||
(p=1,k=.05,b=220,e=0,r=0,t=.1,q=0,D=1,u=0,y=0,v=0,z=0,l=0,E=0,A=0,F=0,c=0,w=1,m= | ||
0,B=0,M=Math,R=44100,d=2*M.PI,G=u*=500*d/R/R,C=b*=(1-k+2*k*M.random(k=[]))*d/R,g | ||
=0,H=0,a=0,n=1,I=0,J=0,f=0,x,h)=>{e=R*e+9;m*=R;r*=R;t*=R;c*=R;y*=500*d/R**3;A*=d | ||
/R;v*=d/R;z*=R;l=R*l|0;for(h=e+m+r+t+c|0;a<h;k[a++]=f)++J%(100*F|0)||(f=q?1<q?2< | ||
q?3<q?M.sin((g%d)**3):M.max(M.min(M.tan(g),1),-1):1-(2*g/d%2+2)%2:1-4*M.abs(M. | ||
round(g/d)-g/d):M.sin(g),f=(l?1-B+B*M.sin(d*a/l):1)*(0<f?1:-1)*M.abs(f)**D*zzfxV | ||
*p*(a<e?a/e:a<e+m?1-(a-e)/m*(1-w):a<e+m+r?w:a<h-c?(h-a-c)/t*w:0),f=c?f/2+(c>a?0: | ||
(a<h-c?1:(h-a)/c)*k[a-c|0]/2):f),x=(b+=u+=y)*M.cos(A*H++),g+=x-x*E*(1-1E9*(M.sin | ||
(a)+1)%2),n&&++n>z&&(b+=v,C+=v,n=0),!l||++I%l||(b=C,u=G,n||=1);p=zzfxX. | ||
createBuffer(1,h,R);p.getChannelData(0).set(k);b=zzfxX.createBufferSource();b. | ||
buffer=p;b.connect(zzfxX.destination);b.start();return b};zzfxX=new AudioContext; | ||
// fix compatibility issues with old web audio (optional) | ||
// if this is used, you must remove the zzfxX=new AudioContext line above! | ||
//zzfxX=new(AudioContext||webkitAudioContext);zzfxX.z=zzfxX.createBufferSource;zzfxX.createBufferSource=(s=zzfxX.z())=>(s.start=s.start||s.noteOn,s) |
Sorry, the diff of this file is not supported yet
93763
338
128