From 6201f33d615cf527f8ca1a51068c3047b6621452 Mon Sep 17 00:00:00 2001 From: MindfulMinun Date: Mon, 1 Jun 2020 19:09:22 -0500 Subject: [PATCH] Bitcrushers! Added bit-crusher-sr8, bit-crusher-res, and bit-crusher-both Added a spacer so you can see the waveform better :) --- dist/processors.worklet.js | 2 +- index.html | 30 ++++++++++++++ src/processors.worklet.js | 83 ++++++++++++++++++++++++++++++++++---- 3 files changed, 107 insertions(+), 8 deletions(-) diff --git a/dist/processors.worklet.js b/dist/processors.worklet.js index 8e6f736..7bcc331 100644 --- a/dist/processors.worklet.js +++ b/dist/processors.worklet.js @@ -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;eintegral + + + @@ -163,6 +177,20 @@ isolate-overlap

The opposite of subtract-overlap. You think it'd be simple but I can't get it to work :/

+ +
  • + bit-crusher-sr8 +

    Bitcrusher. Works by taking the average of 8 samples of the input and setting that average as the output for those 8 samples, effectively reducing the sampling rate.

    +
  • +
  • + bit-crusher-res +

    Bitcrusher. Works by reducing the resolution of each sample from a 32-bit float to a 8-bit float.

    +
  • +
  • + bit-crusher-both +

    Bitcrusher. Combines the output of bit-crusher-sr8 and bit-crusher-res.

    +
  • mono

    @@ -176,6 +204,8 @@ • Source code

    + +
    diff --git a/src/processors.worklet.js b/src/processors.worklet.js index 70573b6..4703720 100644 --- a/src/processors.worklet.js +++ b/src/processors.worklet.js @@ -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.