mirror of
https://github.com/JonnyBro/JaBa.git
synced 2024-12-01 17:44:59 +05:00
120 lines
4.4 KiB
JavaScript
120 lines
4.4 KiB
JavaScript
"use strict";
|
|
// prism's volume transformer with smooth volume support
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.VolumeTransformer = void 0;
|
|
const stream_1 = require("stream");
|
|
class VolumeTransformer extends stream_1.Transform {
|
|
constructor(options = {}) {
|
|
super(options);
|
|
switch (options.type) {
|
|
case "s16le":
|
|
this._readInt = (buffer, index) => buffer.readInt16LE(index);
|
|
this._writeInt = (buffer, int, index) => buffer.writeInt16LE(int, index);
|
|
this._bits = 16;
|
|
break;
|
|
case "s16be":
|
|
this._readInt = (buffer, index) => buffer.readInt16BE(index);
|
|
this._writeInt = (buffer, int, index) => buffer.writeInt16BE(int, index);
|
|
this._bits = 16;
|
|
break;
|
|
case "s32le":
|
|
this._readInt = (buffer, index) => buffer.readInt32LE(index);
|
|
this._writeInt = (buffer, int, index) => buffer.writeInt32LE(int, index);
|
|
this._bits = 32;
|
|
break;
|
|
case "s32be":
|
|
this._readInt = (buffer, index) => buffer.readInt32BE(index);
|
|
this._writeInt = (buffer, int, index) => buffer.writeInt32BE(int, index);
|
|
this._bits = 32;
|
|
break;
|
|
default:
|
|
throw new Error("VolumeTransformer type should be one of s16le, s16be, s32le, s32be");
|
|
}
|
|
this.type = options.type;
|
|
this._bytes = this._bits / 8;
|
|
this._extremum = Math.pow(2, this._bits - 1);
|
|
this.volume = Number.isNaN(options.volume) ? 1 : Number(options.volume);
|
|
if (!Number.isFinite(this.volume))
|
|
this.volume = 1;
|
|
this._targetVolume = this.volume;
|
|
this._chunk = Buffer.alloc(0);
|
|
this._smoothing = options.smoothness || 0;
|
|
}
|
|
_readInt(buffer, index) {
|
|
return index;
|
|
}
|
|
_writeInt(buffer, int, index) {
|
|
return index;
|
|
}
|
|
_applySmoothness() {
|
|
if (this.volume < this._targetVolume) {
|
|
this.volume = this.volume + this._smoothing >= this._targetVolume ? this._targetVolume : this.volume + this._smoothing;
|
|
}
|
|
else if (this.volume > this._targetVolume) {
|
|
this.volume = this.volume - this._smoothing <= this._targetVolume ? this._targetVolume : this.volume - this._smoothing;
|
|
}
|
|
}
|
|
_transform(chunk, encoding, done) {
|
|
if (this.smoothingEnabled() && this.volume !== this._targetVolume)
|
|
this._applySmoothness();
|
|
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();
|
|
const complete = Math.floor(chunk.length / _bytes) * _bytes;
|
|
for (let i = 0; i < complete; i += _bytes) {
|
|
const int = Math.min(_extremum - 1, Math.max(-_extremum, Math.floor(this.volume * this._readInt(chunk, i))));
|
|
this._writeInt(chunk, int, i);
|
|
}
|
|
this._chunk = chunk.slice(complete);
|
|
this.push(chunk.slice(0, complete));
|
|
return done();
|
|
}
|
|
_destroy(err, cb) {
|
|
super._destroy(err, cb);
|
|
this._chunk = null;
|
|
}
|
|
setVolume(volume) {
|
|
if (Number.isNaN(volume))
|
|
volume = 1;
|
|
if (typeof volume !== "number")
|
|
volume = Number(volume);
|
|
if (!Number.isFinite(volume))
|
|
volume = volume < 0 ? 0 : 1;
|
|
this._targetVolume = volume;
|
|
if (this._smoothing <= 0)
|
|
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);
|
|
}
|
|
get smoothness() {
|
|
return this._smoothing;
|
|
}
|
|
setSmoothness(smoothness) {
|
|
this._smoothing = smoothness;
|
|
}
|
|
smoothingEnabled() {
|
|
return Number.isFinite(this._smoothing) && this._smoothing > 0;
|
|
}
|
|
get hasSmoothness() {
|
|
return true;
|
|
}
|
|
static get hasSmoothing() {
|
|
return true;
|
|
}
|
|
}
|
|
exports.VolumeTransformer = VolumeTransformer;
|