forked from Supositware/Haha-Yes
114 lines
3.2 KiB
JavaScript
114 lines
3.2 KiB
JavaScript
|
// Based on discord.js' old volume system
|
||
|
|
||
|
const { Transform } = require('stream');
|
||
|
const loader = require('../util/loader');
|
||
|
|
||
|
const krypton = loader.require([['krypton']]).fn;
|
||
|
class VolumeTransformer extends Transform {
|
||
|
constructor(options = {}) {
|
||
|
super(options);
|
||
|
this._bits = options.bits;
|
||
|
this._bytes = this._bits / 8;
|
||
|
this._extremum = Math.pow(2, this._bits - 1) - 1;
|
||
|
this.volume = options.volume || 1;
|
||
|
this._chunk = Buffer.alloc(0);
|
||
|
}
|
||
|
|
||
|
_readInt(buffer, index) { return index; }
|
||
|
_writeInt(buffer, int, index) { return index; }
|
||
|
|
||
|
_transform(chunk, encoding, done) {
|
||
|
// If the volume is 1, act like a passthrough stream
|
||
|
if (this.volume === 1) {
|
||
|
this.push(chunk);
|
||
|
return done();
|
||
|
}
|
||
|
|
||
|
const { _bytes, _extremum } = this;
|
||
|
|
||
|
chunk = this._chunk = Buffer.concat([this._chunk, chunk]);
|
||
|
if (chunk.length < _bytes) return done();
|
||
|
|
||
|
let transformed;
|
||
|
let complete;
|
||
|
|
||
|
if (krypton && krypton.pcm.simd && this._krypton) {
|
||
|
if (chunk.length < 64) return done();
|
||
|
transformed = this._krypton(chunk.slice(0, chunk.length - (chunk.length % 64)), this.volume);
|
||
|
complete = transformed.length;
|
||
|
} else {
|
||
|
transformed = Buffer.alloc(chunk.length);
|
||
|
complete = Math.floor(chunk.length / _bytes) * _bytes;
|
||
|
|
||
|
for (let i = 0; i < complete; i += _bytes) {
|
||
|
const int = Math.min(_extremum, Math.max(-_extremum, Math.floor(this.volume * this._readInt(chunk, i))));
|
||
|
this._writeInt(transformed, int, i);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this._chunk = chunk.slice(complete);
|
||
|
this.push(transformed);
|
||
|
return done();
|
||
|
}
|
||
|
|
||
|
_destroy(err, cb) {
|
||
|
super._destroy(err, cb);
|
||
|
this._chunk = null;
|
||
|
}
|
||
|
|
||
|
setVolume(volume) {
|
||
|
this.volume = volume;
|
||
|
}
|
||
|
|
||
|
setVolumeDecibels(db) {
|
||
|
this.setVolume(Math.pow(10, db / 20));
|
||
|
}
|
||
|
|
||
|
setVolumeLogarithmic(value) {
|
||
|
this.setVolume(Math.pow(value, 1.660964));
|
||
|
}
|
||
|
|
||
|
get volumeDecibels() {
|
||
|
return Math.log10(this._volume) * 20;
|
||
|
}
|
||
|
|
||
|
get volumeLogarithmic() {
|
||
|
return Math.pow(this._volume, 1 / 1.660964);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class VolumeTransformer16LE extends VolumeTransformer {
|
||
|
constructor(options) { super({ ...options, bits: 16 }); }
|
||
|
_readInt(buffer, index) { return buffer.readInt16LE(index); }
|
||
|
_writeInt(buffer, int, index) { return buffer.writeInt16LE(int, index); }
|
||
|
|
||
|
_krypton(buffer, volume) {
|
||
|
return krypton.do(krypton.pcm.volume16(buffer, volume)).run(false);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class VolumeTransformer16BE extends VolumeTransformer {
|
||
|
constructor(options) { super({ ...options, bits: 16 }); }
|
||
|
_readInt(buffer, index) { return buffer.readInt16BE(index); }
|
||
|
_writeInt(buffer, int, index) { return buffer.writeInt16BE(int, index); }
|
||
|
}
|
||
|
|
||
|
class VolumeTransformer32LE extends VolumeTransformer {
|
||
|
constructor(options) { super({ ...options, bits: 32 }); }
|
||
|
_readInt(buffer, index) { return buffer.readInt32LE(index); }
|
||
|
_writeInt(buffer, int, index) { return buffer.writeInt32LE(int, index); }
|
||
|
}
|
||
|
|
||
|
class VolumeTransformer32BE extends VolumeTransformer {
|
||
|
constructor(options) { super({ ...options, bits: 32 }); }
|
||
|
_readInt(buffer, index) { return buffer.readInt32BE(index); }
|
||
|
_writeInt(buffer, int, index) { return buffer.writeInt32BE(int, index); }
|
||
|
}
|
||
|
|
||
|
module.exports = {
|
||
|
VolumeTransformer16LE,
|
||
|
VolumeTransformer16BE,
|
||
|
VolumeTransformer32LE,
|
||
|
VolumeTransformer32BE,
|
||
|
};
|