// Based on discord.js' old volume system

const { Transform } = require('stream');

class VolumeTransformer extends Transform {
  constructor(options, { bits = 16, volume = 1 } = {}) {
    super(options);
    this.bits = bits;
    this.bytes = this.bits / 8;
    this.extremum = Math.pow(2, this.bits - 1) - 1;
    this.volume = volume;
    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();

    const transformed = Buffer.alloc(chunk.length);
    const complete = Math.floor(chunk.length / bytes) * bytes;
    let i = 0;
    for (; 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, { volume = 1 } = {}) { super(options, { volume, bits: 16 }); }
  readInt(buffer, index) { return buffer.readInt16LE(index); }
  writeInt(buffer, int, index) { return buffer.writeInt16LE(int, index); }
}

class VolumeTransformer16BE extends VolumeTransformer {
  constructor(options, { volume = 1 } = {}) { super(options, { volume, bits: 16 }); }
  readInt(buffer, index) { return buffer.readInt16BE(index); }
  writeInt(buffer, int, index) { return buffer.writeInt16BE(int, index); }
}

class VolumeTransformer32LE extends VolumeTransformer {
  constructor(options, { volume = 1 } = {}) { super(options, { volume, bits: 32 }); }
  readInt(buffer, index) { return buffer.readInt32LE(index); }
  writeInt(buffer, int, index) { return buffer.writeInt32LE(int, index); }
}

class VolumeTransformer32BE extends VolumeTransformer {
  constructor(options, { volume = 1 } = {}) { super(options, { volume, bits: 32 }); }
  readInt(buffer, index) { return buffer.readInt32BE(index); }
  writeInt(buffer, int, index) { return buffer.writeInt32BE(int, index); }
}

module.exports = {
  VolumeTransformer16LE,
  VolumeTransformer16BE,
  VolumeTransformer32LE,
  VolumeTransformer32BE,
};

@@ -204,24 +204,25 @@
 );%0A    this.
+_
 bits = bits;
@@ -231,16 +231,17 @@
    this.
+_
 bytes = 
@@ -241,24 +241,25 @@
 ytes = this.
+_
 bits / 8;%0A  
@@ -265,16 +265,17 @@
    this.
+_
 extremum
@@ -294,16 +294,17 @@
 2, this.
+_
 bits - 1
@@ -378,16 +378,17 @@
 %0A  %7D%0A%0A  
+_
 readInt(
@@ -418,24 +418,25 @@
  index; %7D%0A  
+_
 writeInt(buf
@@ -663,15 +663,17 @@
 t %7B 
+_
 bytes, 
+_
 extr
@@ -774,16 +774,17 @@
 ength %3C 
+_
 bytes) r
@@ -897,16 +897,17 @@
 ength / 
+_
 bytes) *
@@ -907,16 +907,17 @@
 ytes) * 
+_
 bytes;%0A 
@@ -960,16 +960,17 @@
 e; i += 
+_
 bytes) %7B
@@ -997,16 +997,17 @@
 ath.min(
+_
 extremum
@@ -1018,16 +1018,17 @@
 th.max(-
+_
 extremum
@@ -1059,16 +1059,17 @@
  * this.
+_
 readInt(
@@ -1093,16 +1093,17 @@
    this.
+_
 writeInt
@@ -1807,32 +1807,33 @@
 its: 16 %7D); %7D%0A  
+_
 readInt(buffer, 
@@ -1847,32 +1847,33 @@
 %7B return buffer.
+_
 readInt16LE(inde
@@ -1872,32 +1872,33 @@
 6LE(index); %7D%0A  
+_
 writeInt(buffer,
@@ -1918,32 +1918,33 @@
 %7B return buffer.
+_
 writeInt16LE(int
@@ -2094,32 +2094,33 @@
 its: 16 %7D); %7D%0A  
+_
 readInt(buffer, 
@@ -2138,24 +2138,25 @@
 turn buffer.
+_
 readInt16BE(
@@ -2159,32 +2159,33 @@
 6BE(index); %7D%0A  
+_
 writeInt(buffer,
@@ -2205,32 +2205,33 @@
 %7B return buffer.
+_
 writeInt16BE(int
@@ -2381,32 +2381,33 @@
 its: 32 %7D); %7D%0A  
+_
 readInt(buffer, 
@@ -2421,32 +2421,33 @@
 %7B return buffer.
+_
 readInt32LE(inde
@@ -2446,32 +2446,33 @@
 2LE(index); %7D%0A  
+_
 writeInt(buffer,
@@ -2492,32 +2492,33 @@
 %7B return buffer.
+_
 writeInt32LE(int
@@ -2676,16 +2676,17 @@
 %7D); %7D%0A  
+_
 readInt(
@@ -2716,16 +2716,17 @@
  buffer.
+_
 readInt3
@@ -2741,16 +2741,17 @@
 x); %7D%0A  
+_
 writeInt
@@ -2787,16 +2787,17 @@
  buffer.
+_
 writeInt

Mark private properties and methods in PCMVolume