Passed
Push — master ( 66fc5e...2c9c12 )
by Rafael S.
01:28
created

src/wavefileinterface.js   A

Size

Lines of Code 152

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
nc 1
dl 0
loc 152
rs 10
noi 1

1 Function

Rating   Name   Duplication   Size   Complexity  
A wavefileinterface.js ➔ ??? 0 6 2
1
/*!
2
 * wavefile
3
 * Read & write wave files with 8, 16, 24, 32 PCM, 32 IEEE & 64-bit data.
4
 * Copyright (c) 2017 Rafael da Silva Rocha. MIT License.
5
 * https://github.com/rochars/wavefile
6
 *
7
 */
8
9
const byteData = require("byte-data");
0 ignored issues
show
Unused Code introduced by
The constant byteData seems to be never used. Consider removing it.
Loading history...
10
const bitDepthLib = require("bitdepth");
11
const wavefile = require("../src/wavefile");
12
13
/**
14
 * A wave file.
15
 */
16
class WaveFileInterface extends wavefile.WaveFile {
17
18
    /**
19
     * @param {Uint8Array} bytes The file bytes.
20
     * @param {boolean} enforceFact True if it should throw a error
21
     *      if no "fact" chunk is found.
22
     * @param {boolean} enforceBext True if it should throw a error
23
     *      if no "bext" chunk is found.
24
     */
25
    constructor(bytes, enforceFact=false, enforceBext=false) {
26
        super(enforceFact, enforceBext);
27
        if(bytes) {
28
            this.fromBuffer(bytes);
29
        }
30
    }
31
32
    /**
33
     * Create a WaveFile object based on the arguments passed.
34
     * @param {number} numChannels The number of channels
35
     *     (Ints like 1 for mono, 2 stereo and so on).
36
     * @param {number} sampleRate The sample rate.
37
     *     Integer numbers like 8000, 44100, 48000, 96000, 192000.
38
     * @param {string} bitDepth The audio bit depth.
39
     *     One of "8", "16", "24", "32", "32f", "64".
40
     * @param {!Array<number>} samples Array of samples to be written.
41
     *     Samples must be in the correct range according to the bit depth.
42
     *     Samples of multi-channel data .
43
     */
44
    fromScratch(numChannels, sampleRate, bitDepth, samples, options={}) {
45
        if (!options.container) {
46
            options.container = "RIFF";
47
        }
48
        this.isFromScratch_ = true;
49
        let bytes = parseInt(bitDepth, 10) / 8;
50
        this.chunkSize = 36 + samples.length * bytes;
51
        this.subChunk1Size = 16;
52
        this.byteRate = (numChannels * bytes) * sampleRate;
53
        this.blockAlign = numChannels * bytes;
54
        this.chunkId = options.container;
55
        this.format = "WAVE";
56
        this.subChunk1Id = "fmt ";
57
        this.audioFormat = this.headerFormats_[bitDepth];
58
        this.numChannels = numChannels;
59
        this.sampleRate = sampleRate;
60
        this.bitsPerSample = parseInt(bitDepth, 10);
61
        this.subChunk2Id = "data";
62
        this.subChunk2Size = samples.length * bytes;
63
        this.samples_ = samples;
64
        this.bitDepth_ = bitDepth;
65
    }
66
67
    /**
68
     * Read a wave file from a byte buffer.
69
     * @param {Uint8Array} bytes The buffer.
70
     */
71
    fromBuffer(bytes) {
72
        this.isFromScratch_ = false;
73
        this.readRIFFChunk_(bytes);
74
        this.readWAVEChunk_(bytes);
75
        this.readFmtChunk_(bytes);
76
        this.readFactChunk_(bytes);
77
        this.readBextChunk_(bytes);
78
        this.readDataChunk_(bytes);
79
    }
80
81
    /**
82
     * Turn the WaveFile object into a byte buffer.
83
     * @return {Uint8Array}
84
     */
85
    toBuffer() {
86
        this.checkWriteInput_(this.numChannels, this.sampleRate, this.bitDepth_);
87
        this.samplesToBytes_();
88
        return new Uint8Array(this.createWaveFile_());
89
    }
90
91
    /**
92
     * Turn the file to RIFF.
93
     * All values will be little-endian when writing.
94
     */
95
    toRIFF() {
96
        this.chunkId = "RIFF";
97
    }
98
99
    /**
100
     * Turn the file to RIFX.
101
     * All values but FourCCs will be big-endian when writing.
102
     */
103
    toRIFX() {
104
        this.chunkId = "RIFX";
105
    }
106
107
    /**
108
     * Change the bit depth of the data.
109
     * @param {string} bitDepth The new bit depth of the data.
110
     *      One of "8", "16", "24", "32", "32f", "64"
111
     */
112
    toBitDepth(bitDepth) {
113
        bitDepthLib.toBitDepth(this.samples_, this.bitDepth_, bitDepth);
114
        this.fromScratch(
115
            this.numChannels,
116
            this.sampleRate,
117
            bitDepth,
118
            this.samples_,
119
            {"container": this.chunkId}
120
        );
121
    }
122
123
    /**
124
     * Interleave multi-channel samples.
125
     */
126
    interleave() {
127
        let finalSamples = [];
128
        let i;
129
        let j;
130
        let numChannels = this.samples_[0].length;
131
        for (i = 0; i < numChannels; i++) {
132
            for (j = 0; j < this.samples_.length; j++) {
133
                finalSamples.push(this.samples_[j][i]);
134
            }
135
        }
136
        this.samples_ = finalSamples;
137
    }
138
139
    /**
140
     * De-interleave samples into multiple channels.
141
     */
142
    deInterleave() {
143
        let finalSamples = [];
144
        let i;
145
        for (i = 0; i < this.numChannels; i++) {
146
            finalSamples[i] = [];
147
        }
148
        i = 0;
149
        let j;
150
        while (i < this.samples_.length) {
151
            for (j = 0; j < this.numChannels; j++) {
152
                finalSamples[j].push(this.samples_[i+j]);
153
            }
154
            i += j;
155
        }
156
        this.samples_ = finalSamples;
157
    }
158
}
159
160
module.exports.WaveFile = WaveFileInterface;