Bitcrushers!

Added bit-crusher-sr8, bit-crusher-res, and bit-crusher-both
Added a spacer so you can see the waveform better :)
This commit is contained in:
MindfulMinun committed 2020-06-01 19:09:22 -05:00
1 parent bcc2741017
commit 6201f33d61
3 files changed
+107 -8

No files matched your search

+1 -1
View File
@@ -1 +1 @@
!function(e){var r={};function t(o){if(r[o])return r[o].exports;var s=r[o]={i:o,l:!1,exports:{}};return e[o].call(s.exports,s,s.exports,t),s.l=!0,s.exports}t.m=e,t.c=r,t.d=function(e,r,o){t.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:o})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,r){if(1&r&&(e=t(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(t.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var s in e)t.d(o,s,function(r){return e[r]}.bind(null,s));return o},t.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(r,"a",r),r},t.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},t.p="",t(t.s=0)}([function(e,r){const t=Symbol();class o extends AudioWorkletProcessor{process(e,r){const t=e[0],o=r[0];for(let e=0;e<t.length;e++)o[e].set(t[e]);return!0}}registerProcessor("noop",o);class s extends AudioWorkletProcessor{process(e,r){const t=e[0],o=r[0];for(let e=0;e<t.length;e++){for(let r=0;r<t[0].length;r++)o[0][r]+=t[e][r]*(1/t.length);0!==e&&o[e].set(o[0])}return!0}}registerProcessor("mono",s);class n extends AudioWorkletProcessor{constructor(e){super(),this[t]=new Float32Array(e.processorOptions.maxChannels)}process(e,r){const o=e[0],s=r[0];for(let e=0;e<o.length;e++){s[e][0]=this[t][e];for(let r=1;r<o[e].length;r++)s[e][r]=o[e][r]-o[e][r-1];this[t][e]=o[e][o.length-1]}return!0}}registerProcessor("derivative",n);class l extends AudioWorkletProcessor{constructor(e){super(),this[t]=new Float32Array(e.processorOptions.maxChannels)}process(e,r){const o=e[0],s=r[0];for(let e=0;e<o.length;e++){s[e][0]=(this[t][e]+o[e][0])/2;for(let r=1;r<o[e].length;r++)s[e][r]=(o[e][r-1]+o[e][r])/2;this[t][e]=o[e][o.length-1]}return!0}}registerProcessor("integral",l);class c extends AudioWorkletProcessor{process(e,r){const t=e[0],o=r[0];Math.pow(.5,8);for(let e=0;e<t.length;e++)for(let r=0;r<t[e].length;r++)o[e][r]=t[e][r];return!0}}registerProcessor("bit-crusher",c);class u extends AudioWorkletProcessor{process(e,r){const t=e[0],o=r[0];for(let e=0;e<t.length;e++){for(let r=0;r<t[e].length;r++)o[0][r]+=(e%2==0?1:-1)*t[e][r];0!==e&&o[e].set(o[0])}return!0}}registerProcessor("subtract-overlap",u);class i extends AudioWorkletProcessor{process(e,r){const t=e[0],o=r[0];for(let e=0;e<t.length;e++)for(let r=0;r<t[e].length;r++)o[0][r]+=(e%2==0?1:-1)*t[e][r];for(let e=t.length-1;0<=e;e--)for(let r=0;r<t[e].length;r++)o[e][r]=t[e][r]-o[0][r];return!0}}registerProcessor("isolate-overlap",i)}]);
!function(e){var r={};function t(o){if(r[o])return r[o].exports;var s=r[o]={i:o,l:!1,exports:{}};return e[o].call(s.exports,s,s.exports,t),s.l=!0,s.exports}t.m=e,t.c=r,t.d=function(e,r,o){t.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:o})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,r){if(1&r&&(e=t(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(t.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var s in e)t.d(o,s,function(r){return e[r]}.bind(null,s));return o},t.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(r,"a",r),r},t.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},t.p="",t(t.s=0)}([function(e,r){const t=Symbol();class o extends AudioWorkletProcessor{process(e,r){const t=e[0],o=r[0];for(let e=0;e<t.length;e++)o[e].set(t[e]);return!0}}registerProcessor("noop",o);class s extends AudioWorkletProcessor{process(e,r){const t=e[0],o=r[0];for(let e=0;e<t.length;e++){for(let r=0;r<t[0].length;r++)o[0][r]+=t[e][r]*(1/t.length);0!==e&&o[e].set(o[0])}return!0}}registerProcessor("mono",s);class n extends AudioWorkletProcessor{constructor(e){super(),this[t]=new Float32Array(e.processorOptions.maxChannels)}process(e,r){const o=e[0],s=r[0];for(let e=0;e<o.length;e++){s[e][0]=this[t][e];for(let r=1;r<o[e].length;r++)s[e][r]=o[e][r]-o[e][r-1];this[t][e]=o[e][o.length-1]}return!0}}registerProcessor("derivative",n);class l extends AudioWorkletProcessor{constructor(e){super(),this[t]=new Float32Array(e.processorOptions.maxChannels)}process(e,r){const o=e[0],s=r[0];for(let e=0;e<o.length;e++){s[e][0]=(this[t][e]+o[e][0])/2;for(let r=1;r<o[e].length;r++)s[e][r]=(o[e][r-1]+o[e][r])/2;this[t][e]=o[e][o.length-1]}return!0}}registerProcessor("integral",l);class c extends AudioWorkletProcessor{process(e,r){const t=e[0],o=r[0];for(let e=0;e<t.length;e++)for(let r=0;r<t[e].length;r+=8){let s=0;for(let o=0;o<8;o++)s+=t[e][r+o];const n=s/8;for(let t=0;t<8;t++)o[e][r+t]=n}return!0}}registerProcessor("bit-crusher-sr8",c);class u extends AudioWorkletProcessor{process(e,r){const t=e[0],o=r[0];for(let e=0;e<t.length;e++)for(let r=0;r<t[e].length;r++)o[e][r]=Math.round(16*t[e][r])/16;return!0}}registerProcessor("bit-crusher-res",u);class i extends AudioWorkletProcessor{process(e,r){const t=e[0],o=r[0];for(let e=0;e<t.length;e++)for(let r=0;r<t[e].length;r+=8){let s=0;for(let o=0;o<8;o++)s+=Math.round(16*t[e][r])/16;const n=s/8;for(let t=0;t<8;t++)o[e][r+t]=n}return!0}}registerProcessor("bit-crusher-both",i);class f extends AudioWorkletProcessor{process(e,r){const t=e[0],o=r[0];for(let e=0;e<t.length;e++){for(let r=0;r<t[e].length;r++)o[0][r]+=(e%2==0?1:-1)*t[e][r];0!==e&&o[e].set(o[0])}return!0}}registerProcessor("subtract-overlap",f);class a extends AudioWorkletProcessor{process(e,r){const t=e[0],o=r[0];for(let e=0;e<t.length;e++)for(let r=0;r<t[e].length;r++)o[0][r]+=(e%2==0?1:-1)*t[e][r];for(let e=t.length-1;0<=e;e--)for(let r=0;r<t[e].length;r++)o[e][r]=t[e][r]-o[0][r];return!0}}registerProcessor("isolate-overlap",a)}]);
+30
View File
@@ -23,6 +23,7 @@
height: 100%;
margin: 0;
color: white;
background-color: black;
}
body { display: flex; }
a[href] { color: var(--accent); }
@@ -73,6 +74,10 @@
border-color: #448aff;
}
button, select {
backdrop-filter: blur(2px);
}
canvas {
position: fixed;
top: 0; left: 0; bottom: 0; right: 0;
@@ -88,6 +93,12 @@
padding: 1em;
z-index: 1;
}
.spacer {
/* height: 90vh; */
height: 1000px;
height: 90vh;
height: calc(100vh - 6rem);
}
.credits {
text-align: center;
font-style: italic;
@@ -124,6 +135,9 @@
<option value="integral">integral</option>
<option value="subtract-overlap">subtract-overlap</option>
<option value="isolate-overlap" disabled>isolate-overlap</option>
<option value="bit-crusher-sr8">bit-crusher-sr8 (Sample-rate reduction)</option>
<option value="bit-crusher-res">bit-crusher-res (bit-depth reduction)</option>
<option value="bit-crusher-both">bit-crusher-both</option>
<option value="mono">mono</option>
</select>
</label>
@@ -163,6 +177,20 @@
<code>isolate-overlap</code>
<p>The opposite of subtract-overlap. You think it'd be simple but I can't get it to work :/</p>
</li>
<!-- bit-crusher-sr8
bit-crusher-res -->
<li>
<code>bit-crusher-sr8</code>
<p>Bitcrusher. Works by taking the average of 8 samples of the input and setting that average as the output for those 8 samples, effectively <strong>reducing the sampling rate</strong>.</p>
</li>
<li>
<code>bit-crusher-res</code>
<p>Bitcrusher. Works by <strong>reducing the resolution of each sample</strong> from a 32-bit float to a 8-bit float.</p>
</li>
<li>
<code>bit-crusher-both</code>
<p>Bitcrusher. Combines the output of bit-crusher-sr8 and bit-crusher-res.</p>
</li>
<li>
<code>mono</code>
<p>
@@ -176,6 +204,8 @@
•
<a href="https://github.com/MindfulMinun/d-flat">Source code</a>
</p>
<div class="spacer"></div>
</div>
<input id="file" type="file" hidden>
+76 -7
View File
@@ -102,8 +102,10 @@ class IntegralProcessor extends AudioWorkletProcessor {
}
registerProcessor('integral', IntegralProcessor)
class BitCrusher extends AudioWorkletProcessor {
/**
* Sample-rate reduction
*/
class BitCrusher_Sr8 extends AudioWorkletProcessor {
/**
* @param {Float32Array[][]} inputs
* @param {Float32Array[][]} outputs
@@ -112,20 +114,87 @@ class BitCrusher extends AudioWorkletProcessor {
const input = inputs[0]
const output = outputs[0]
let phase = 1
const step = 2 * Math.pow(.5, 8)
const chunkSize = 1 << 3
for (let channel = 0; channel < input.length; channel++) {
for (let sample = 0; sample < input[channel].length; sample++) {
output[channel][sample] = input[channel][sample]
for (let sample = 0; sample < input[channel].length; sample += chunkSize) {
// Take the average of a few samples
let sum = 0
for (let i = 0; i < chunkSize; i++) {
sum += input[channel][sample + i]
}
const avg = sum / chunkSize
// Set the output to the average, effectively reducing the sampling rate
for (let i = 0; i < chunkSize; i++) {
output[channel][sample + i] = avg
}
}
}
return true
}
}
registerProcessor('bit-crusher', BitCrusher)
registerProcessor('bit-crusher-sr8', BitCrusher_Sr8)
/**
* Resolution reduction
*/
class BitCrusher_Res extends AudioWorkletProcessor {
/**
* @param {Float32Array[][]} inputs
* @param {Float32Array[][]} outputs
*/
process(inputs, outputs) {
const input = inputs[0]
const output = outputs[0]
const res = 16
// Resolution reduction
for (let channel = 0; channel < input.length; channel++) {
for (let sample = 0; sample < input[channel].length; sample++) {
output[channel][sample] = Math.round(input[channel][sample] * res) / res
}
}
return true
}
}
registerProcessor('bit-crusher-res', BitCrusher_Res)
class BitCrusher_Both extends AudioWorkletProcessor {
/**
* @param {Float32Array[][]} inputs
* @param {Float32Array[][]} outputs
*/
process(inputs, outputs) {
const input = inputs[0]
const output = outputs[0]
const chunkSize = 1 << 3
const res = 16
for (let channel = 0; channel < input.length; channel++) {
for (let sample = 0; sample < input[channel].length; sample += chunkSize) {
// Take the average of a few samples
let sum = 0
for (let i = 0; i < chunkSize; i++) {
sum += Math.round(input[channel][sample] * res) / res
}
const avg = sum / chunkSize
// Set the output to the average, effectively reducing the sampling rate
for (let i = 0; i < chunkSize; i++) {
output[channel][sample + i] = avg
}
}
}
return true
}
}
registerProcessor('bit-crusher-both', BitCrusher_Both)
/**
* Inverts the amplitude of every even-numbered channel and merges them to mono.