Completed
Push — master ( 317dbe...83670a )
by Rafael S.
03:21
created

WaveFileReader.readDs64Chunk_   A

Complexity

Conditions 3

Size

Total Lines 26
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 16
dl 0
loc 26
rs 9.6
c 0
b 0
f 0
cc 3
1
/*
2
 * Copyright (c) 2017-2019 Rafael da Silva Rocha.
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining
5
 * a copy of this software and associated documentation files (the
6
 * "Software"), to deal in the Software without restriction, including
7
 * without limitation the rights to use, copy, modify, merge, publish,
8
 * distribute, sublicense, and/or sell copies of the Software, and to
9
 * permit persons to whom the Software is furnished to do so, subject to
10
 * the following conditions:
11
 *
12
 * The above copyright notice and this permission notice shall be
13
 * included in all copies or substantial portions of the Software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
 *
23
 */
24
25
/**
26
 * @fileoverview The WaveFileReader class.
27
 * @see https://github.com/rochars/wavefile
28
 */
29
30
/** @module wavefile */
31
32
import RIFFFile from './riff-file';
33
import writeString from './write-string';
34
import validateNumChannels from './validate-num-channels'; 
35
import validateSampleRate from './validate-sample-rate';
36
import {unpack} from 'byte-data';
37
38
/**
39
 * A class to read wav files.
40
 */
41
export default class WaveFileReader extends RIFFFile {
42
43
  /**
44
   * @param {?Uint8Array=} wavBuffer A wave file buffer.
45
   * @throws {Error} If container is not RIFF, RIFX or RF64.
46
   * @throws {Error} If format is not WAVE.
47
   * @throws {Error} If no 'fmt ' chunk is found.
48
   * @throws {Error} If no 'data' chunk is found.
49
   */
50
  constructor(wavBuffer=null) {
51
    super();
52
    /**
53
     * Audio formats.
54
     * Formats not listed here should be set to 65534,
55
     * the code for WAVE_FORMAT_EXTENSIBLE
56
     * @enum {number}
57
     * @protected
58
     */
59
    this.WAV_AUDIO_FORMATS = {
60
      '4': 17,
61
      '8': 1,
62
      '8a': 6,
63
      '8m': 7,
64
      '16': 1,
65
      '24': 1,
66
      '32': 1,
67
      '32f': 3,
68
      '64': 3
69
    };
70
    /**
71
     * The data of the 'fmt' chunk.
72
     * @type {!Object<string, *>}
73
     */
74
    this.fmt = {
75
      /** @type {string} */
76
      chunkId: '',
77
      /** @type {number} */
78
      chunkSize: 0,
79
      /** @type {number} */
80
      audioFormat: 0,
81
      /** @type {number} */
82
      numChannels: 0,
83
      /** @type {number} */
84
      sampleRate: 0,
85
      /** @type {number} */
86
      byteRate: 0,
87
      /** @type {number} */
88
      blockAlign: 0,
89
      /** @type {number} */
90
      bitsPerSample: 0,
91
      /** @type {number} */
92
      cbSize: 0,
93
      /** @type {number} */
94
      validBitsPerSample: 0,
95
      /** @type {number} */
96
      dwChannelMask: 0,
97
      /**
98
       * 4 32-bit values representing a 128-bit ID
99
       * @type {!Array<number>}
100
       */
101
      subformat: []
102
    };
103
    /**
104
     * The data of the 'fact' chunk.
105
     * @type {!Object<string, *>}
106
     */
107
    this.fact = {
108
      /** @type {string} */
109
      chunkId: '',
110
      /** @type {number} */
111
      chunkSize: 0,
112
      /** @type {number} */
113
      dwSampleLength: 0
114
    };
115
    /**
116
     * The data of the 'cue ' chunk.
117
     * @type {!Object<string, *>}
118
     */
119
    this.cue = {
120
      /** @type {string} */
121
      chunkId: '',
122
      /** @type {number} */
123
      chunkSize: 0,
124
      /** @type {number} */
125
      dwCuePoints: 0,
126
      /** @type {!Array<!Object>} */
127
      points: [],
128
    };
129
    /**
130
     * The data of the 'smpl' chunk.
131
     * @type {!Object<string, *>}
132
     */
133
    this.smpl = {
134
      /** @type {string} */
135
      chunkId: '',
136
      /** @type {number} */
137
      chunkSize: 0,
138
      /** @type {number} */
139
      dwManufacturer: 0,
140
      /** @type {number} */
141
      dwProduct: 0,
142
      /** @type {number} */
143
      dwSamplePeriod: 0,
144
      /** @type {number} */
145
      dwMIDIUnityNote: 0,
146
      /** @type {number} */
147
      dwMIDIPitchFraction: 0,
148
      /** @type {number} */
149
      dwSMPTEFormat: 0,
150
      /** @type {number} */
151
      dwSMPTEOffset: 0,
152
      /** @type {number} */
153
      dwNumSampleLoops: 0,
154
      /** @type {number} */
155
      dwSamplerData: 0,
156
      /** @type {!Array<!Object>} */
157
      loops: []
158
    };
159
    /**
160
     * The data of the 'bext' chunk.
161
     * @type {!Object<string, *>}
162
     */
163
    this.bext = {
164
      /** @type {string} */
165
      chunkId: '',
166
      /** @type {number} */
167
      chunkSize: 0,
168
      /** @type {string} */
169
      description: '', //256
170
      /** @type {string} */
171
      originator: '', //32
172
      /** @type {string} */
173
      originatorReference: '', //32
174
      /** @type {string} */
175
      originationDate: '', //10
176
      /** @type {string} */
177
      originationTime: '', //8
178
      /**
179
       * 2 32-bit values, timeReference high and low
180
       * @type {!Array<number>}
181
       */
182
      timeReference: [0, 0],
183
      /** @type {number} */
184
      version: 0, //WORD
185
      /** @type {string} */
186
      UMID: '', // 64 chars
187
      /** @type {number} */
188
      loudnessValue: 0, //WORD
189
      /** @type {number} */
190
      loudnessRange: 0, //WORD
191
      /** @type {number} */
192
      maxTruePeakLevel: 0, //WORD
193
      /** @type {number} */
194
      maxMomentaryLoudness: 0, //WORD
195
      /** @type {number} */
196
      maxShortTermLoudness: 0, //WORD
197
      /** @type {string} */
198
      reserved: '', //180
199
      /** @type {string} */
200
      codingHistory: '' // string, unlimited
201
    };
202
    /**
203
     * The data of the 'ds64' chunk.
204
     * Used only with RF64 files.
205
     * @type {!Object<string, *>}
206
     */
207
    this.ds64 = {
208
      /** @type {string} */
209
      chunkId: '',
210
      /** @type {number} */
211
      chunkSize: 0,
212
      /** @type {number} */
213
      riffSizeHigh: 0, // DWORD
214
      /** @type {number} */
215
      riffSizeLow: 0, // DWORD
216
      /** @type {number} */
217
      dataSizeHigh: 0, // DWORD
218
      /** @type {number} */
219
      dataSizeLow: 0, // DWORD
220
      /** @type {number} */
221
      originationTime: 0, // DWORD
222
      /** @type {number} */
223
      sampleCountHigh: 0, // DWORD
224
      /** @type {number} */
225
      sampleCountLow: 0 // DWORD
226
      /** @type {number} */
227
      //'tableLength': 0, // DWORD
228
      /** @type {!Array<number>} */
229
      //'table': []
230
    };
231
    /**
232
     * The data of the 'data' chunk.
233
     * @type {!Object<string, *>}
234
     */
235
    this.data = {
236
      /** @type {string} */
237
      chunkId: '',
238
      /** @type {number} */
239
      chunkSize: 0,
240
      /** @type {!Uint8Array} */
241
      samples: new Uint8Array(0)
242
    };
243
    /**
244
     * The data of the 'LIST' chunks.
245
     * Each item in this list look like this:
246
     *  {
247
     *      chunkId: '',
248
     *      chunkSize: 0,
249
     *      format: '',
250
     *      subChunks: []
251
     *   }
252
     * @type {!Array<!Object>}
253
     */
254
    this.LIST = [];
255
    /**
256
     * The data of the 'junk' chunk.
257
     * @type {!Object<string, *>}
258
     */
259
    this.junk = {
260
      /** @type {string} */
261
      chunkId: '',
262
      /** @type {number} */
263
      chunkSize: 0,
264
      /** @type {!Array<number>} */
265
      chunkData: []
266
    };
267
    /**
268
     * The bit depth code according to the samples.
269
     * @type {string}
270
     */
271
    this.bitDepth = '0';
272
    /**
273
     * @type {!Object}
274
     * @protected
275
     */
276
    this.dataType = {};
277
    // Load a file from the buffer if one was passed
278
    // when creating the object
279
    if (wavBuffer) {
280
      this.fromBuffer(wavBuffer);
281
    }
282
  }
283
284
  /**
285
   * Set up the WaveFileParser object from a byte buffer.
286
   * @param {!Uint8Array} wavBuffer The buffer.
287
   * @param {boolean=} samples True if the samples should be loaded.
288
   * @throws {Error} If container is not RIFF, RIFX or RF64.
289
   * @throws {Error} If format is not WAVE.
290
   * @throws {Error} If no 'fmt ' chunk is found.
291
   * @throws {Error} If no 'data' chunk is found.
292
   */
293
  fromBuffer(wavBuffer, samples=true) {
294
    this.clearHeader();
295
    this.head_ = 0;
296
    this.readRIFFChunk(wavBuffer);
297
    if (this.format != 'WAVE') {
298
      throw Error('Could not find the "WAVE" format identifier');
299
    }
300
    this.setSignature(wavBuffer);
301
    this.readDs64Chunk_(wavBuffer);
302
    this.readFmtChunk_(wavBuffer);
303
    this.readFactChunk_(wavBuffer);
304
    this.readBextChunk_(wavBuffer);
305
    this.readCueChunk_(wavBuffer);
306
    this.readSmplChunk_(wavBuffer);
307
    this.readDataChunk_(wavBuffer, samples);
308
    this.readJunkChunk_(wavBuffer);
309
    this.readLISTChunk_(wavBuffer);
310
    this.bitDepthFromFmt_();
311
    this.updateDataType();
312
  }
313
314
  /**
315
   * Reset some attributes of the object.
316
   * @protected
317
   * @ignore
318
   */
319
  clearHeader() {
320
    this.fmt.cbSize = 0;
321
    this.fmt.validBitsPerSample = 0;
322
    this.fact.chunkId = '';
323
    this.ds64.chunkId = '';
324
  }
325
326
  /**
327
   * Update the type definition used to read and write the samples.
328
   * @protected
329
   */
330
  updateDataType() {
331
    this.dataType = {
332
      bits: ((parseInt(this.bitDepth, 10) - 1) | 7) + 1,
333
      fp: this.bitDepth == '32f' || this.bitDepth == '64',
334
      signed: this.bitDepth != '8',
335
      be: this.container == 'RIFX'
336
    };
337
    if (['4', '8a', '8m'].indexOf(this.bitDepth) > -1 ) {
338
      this.dataType.bits = 8;
339
      this.dataType.signed = false;
340
    }
341
  }
342
343
  /**
344
   * Set the string code of the bit depth based on the 'fmt ' chunk.
345
   * @private
346
   */
347
  bitDepthFromFmt_() {
348
    if (this.fmt.audioFormat === 3 && this.fmt.bitsPerSample === 32) {
349
      this.bitDepth = '32f';
350
    } else if (this.fmt.audioFormat === 6) {
351
      this.bitDepth = '8a';
352
    } else if (this.fmt.audioFormat === 7) {
353
      this.bitDepth = '8m';
354
    } else {
355
      this.bitDepth = this.fmt.bitsPerSample.toString();
356
    }
357
  }
358
359
  /**
360
   * Read the 'fmt ' chunk of a wave file.
361
   * @param {!Uint8Array} buffer The wav file buffer.
362
   * @throws {Error} If no 'fmt ' chunk is found.
363
   * @private
364
   */
365
  readFmtChunk_(buffer) {
366
    /** @type {?Object} */
367
    let chunk = this.findChunk('fmt ');
368
    if (chunk) {
369
      this.head_ = chunk.chunkData.start;
370
      this.fmt.chunkId = chunk.chunkId;
371
      this.fmt.chunkSize = chunk.chunkSize;
372
      this.fmt.audioFormat = this.readNumber(buffer, this.uInt16_);
373
      this.fmt.numChannels = this.readNumber(buffer, this.uInt16_);
374
      this.fmt.sampleRate = this.readNumber(buffer, this.uInt32_);
375
      this.fmt.byteRate = this.readNumber(buffer, this.uInt32_);
376
      this.fmt.blockAlign = this.readNumber(buffer, this.uInt16_);
377
      this.fmt.bitsPerSample = this.readNumber(buffer, this.uInt16_);
378
      this.readFmtExtension_(buffer);
379
    } else {
380
      throw Error('Could not find the "fmt " chunk');
381
    }
382
  }
383
384
  /**
385
   * Read the 'fmt ' chunk extension.
386
   * @param {!Uint8Array} buffer The wav file buffer.
387
   * @private
388
   */
389
  readFmtExtension_(buffer) {
390
    if (this.fmt.chunkSize > 16) {
391
      this.fmt.cbSize = this.readNumber(buffer, this.uInt16_);
392
      if (this.fmt.chunkSize > 18) {
393
        this.fmt.validBitsPerSample = this.readNumber(buffer, this.uInt16_);
394
        if (this.fmt.chunkSize > 20) {
395
          this.fmt.dwChannelMask = this.readNumber(buffer, this.uInt32_);
396
          this.fmt.subformat = [
397
            this.readNumber(buffer, this.uInt32_),
398
            this.readNumber(buffer, this.uInt32_),
399
            this.readNumber(buffer, this.uInt32_),
400
            this.readNumber(buffer, this.uInt32_)];
401
        }
402
      }
403
    }
404
  }
405
406
  /**
407
   * Read the 'fact' chunk of a wav file.
408
   * @param {!Uint8Array} buffer The wav file buffer.
409
   * @private
410
   */
411
  readFactChunk_(buffer) {
412
    /** @type {?Object} */
413
    let chunk = this.findChunk('fact');
414
    if (chunk) {
415
      this.head_ = chunk.chunkData.start;
416
      this.fact.chunkId = chunk.chunkId;
417
      this.fact.chunkSize = chunk.chunkSize;
418
      this.fact.dwSampleLength = this.readNumber(buffer, this.uInt32_);
419
    }
420
  }
421
422
  /**
423
   * Read the 'cue ' chunk of a wave file.
424
   * @param {!Uint8Array} buffer The wav file buffer.
425
   * @private
426
   */
427
  readCueChunk_(buffer) {
428
    /** @type {?Object} */
429
    let chunk = this.findChunk('cue ');
430
    if (chunk) {
431
      this.head_ = chunk.chunkData.start;
432
      this.cue.chunkId = chunk.chunkId;
433
      this.cue.chunkSize = chunk.chunkSize;
434
      this.cue.dwCuePoints = this.readNumber(buffer, this.uInt32_);
435
      for (let i = 0; i < this.cue.dwCuePoints; i++) {
436
        this.cue.points.push({
437
          dwName: this.readNumber(buffer, this.uInt32_),
438
          dwPosition: this.readNumber(buffer, this.uInt32_),
439
          fccChunk: this.readString(buffer, 4),
440
          dwChunkStart: this.readNumber(buffer, this.uInt32_),
441
          dwBlockStart: this.readNumber(buffer, this.uInt32_),
442
          dwSampleOffset: this.readNumber(buffer, this.uInt32_),
443
        });
444
      }
445
    }
446
  }
447
448
  /**
449
   * Read the 'smpl' chunk of a wave file.
450
   * @param {!Uint8Array} buffer The wav file buffer.
451
   * @private
452
   */
453
  readSmplChunk_(buffer) {
454
    /** @type {?Object} */
455
    let chunk = this.findChunk('smpl');
456
    if (chunk) {
457
      this.head_ = chunk.chunkData.start;
458
      this.smpl.chunkId = chunk.chunkId;
459
      this.smpl.chunkSize = chunk.chunkSize;
460
      this.smpl.dwManufacturer = this.readNumber(buffer, this.uInt32_);
461
      this.smpl.dwProduct = this.readNumber(buffer, this.uInt32_);
462
      this.smpl.dwSamplePeriod = this.readNumber(buffer, this.uInt32_);
463
      this.smpl.dwMIDIUnityNote = this.readNumber(buffer, this.uInt32_);
464
      this.smpl.dwMIDIPitchFraction = this.readNumber(buffer, this.uInt32_);
465
      this.smpl.dwSMPTEFormat = this.readNumber(buffer, this.uInt32_);
466
      this.smpl.dwSMPTEOffset = this.readNumber(buffer, this.uInt32_);
467
      this.smpl.dwNumSampleLoops = this.readNumber(buffer, this.uInt32_);
468
      this.smpl.dwSamplerData = this.readNumber(buffer, this.uInt32_);
469
      for (let i = 0; i < this.smpl.dwNumSampleLoops; i++) {
470
        this.smpl.loops.push({
471
          dwName: this.readNumber(buffer, this.uInt32_),
472
          dwType: this.readNumber(buffer, this.uInt32_),
473
          dwStart: this.readNumber(buffer, this.uInt32_),
474
          dwEnd: this.readNumber(buffer, this.uInt32_),
475
          dwFraction: this.readNumber(buffer, this.uInt32_),
476
          dwPlayCount: this.readNumber(buffer, this.uInt32_),
477
        });
478
      }
479
    }
480
  }
481
482
  /**
483
   * Read the 'data' chunk of a wave file.
484
   * @param {!Uint8Array} buffer The wav file buffer.
485
   * @param {boolean} samples True if the samples should be loaded.
486
   * @throws {Error} If no 'data' chunk is found.
487
   * @private
488
   */
489
  readDataChunk_(buffer, samples) {
490
    /** @type {?Object} */
491
    let chunk = this.findChunk('data');
492
    if (chunk) {
493
      this.data.chunkId = 'data';
494
      this.data.chunkSize = chunk.chunkSize;
495
      if (samples) {
496
        this.data.samples = buffer.slice(
497
          chunk.chunkData.start,
498
          chunk.chunkData.end);
499
      }
500
    } else {
501
      throw Error('Could not find the "data" chunk');
502
    }
503
  }
504
505
  /**
506
   * Read the 'bext' chunk of a wav file.
507
   * @param {!Uint8Array} buffer The wav file buffer.
508
   * @private
509
   */
510
  readBextChunk_(buffer) {
511
    /** @type {?Object} */
512
    let chunk = this.findChunk('bext');
513
    if (chunk) {
514
      this.head_ = chunk.chunkData.start;
515
      this.bext.chunkId = chunk.chunkId;
516
      this.bext.chunkSize = chunk.chunkSize;
517
      this.bext.description = this.readString(buffer, 256);
518
      this.bext.originator = this.readString(buffer, 32);
519
      this.bext.originatorReference = this.readString(buffer, 32);
520
      this.bext.originationDate = this.readString(buffer, 10);
521
      this.bext.originationTime = this.readString(buffer, 8);
522
      this.bext.timeReference = [
523
        this.readNumber(buffer, this.uInt32_),
524
        this.readNumber(buffer, this.uInt32_)];
525
      this.bext.version = this.readNumber(buffer, this.uInt16_);
526
      this.bext.UMID = this.readString(buffer, 64);
527
      this.bext.loudnessValue = this.readNumber(buffer, this.uInt16_);
528
      this.bext.loudnessRange = this.readNumber(buffer, this.uInt16_);
529
      this.bext.maxTruePeakLevel = this.readNumber(buffer, this.uInt16_);
530
      this.bext.maxMomentaryLoudness = this.readNumber(buffer, this.uInt16_);
531
      this.bext.maxShortTermLoudness = this.readNumber(buffer, this.uInt16_);
532
      this.bext.reserved = this.readString(buffer, 180);
533
      this.bext.codingHistory = this.readString(
534
        buffer, this.bext.chunkSize - 602);
535
    }
536
  }
537
538
  /**
539
   * Read the 'ds64' chunk of a wave file.
540
   * @param {!Uint8Array} buffer The wav file buffer.
541
   * @throws {Error} If no 'ds64' chunk is found and the file is RF64.
542
   * @private
543
   */
544
  readDs64Chunk_(buffer) {
545
    /** @type {?Object} */
546
    let chunk = this.findChunk('ds64');
547
    if (chunk) {
548
      this.head_ = chunk.chunkData.start;
549
      this.ds64.chunkId = chunk.chunkId;
550
      this.ds64.chunkSize = chunk.chunkSize;
551
      this.ds64.riffSizeHigh = this.readNumber(buffer, this.uInt32_);
552
      this.ds64.riffSizeLow = this.readNumber(buffer, this.uInt32_);
553
      this.ds64.dataSizeHigh = this.readNumber(buffer, this.uInt32_);
554
      this.ds64.dataSizeLow = this.readNumber(buffer, this.uInt32_);
555
      this.ds64.originationTime = this.readNumber(buffer, this.uInt32_);
556
      this.ds64.sampleCountHigh = this.readNumber(buffer, this.uInt32_);
557
      this.ds64.sampleCountLow = this.readNumber(buffer, this.uInt32_);
558
      //if (wav.ds64.chunkSize > 28) {
559
      //  wav.ds64.tableLength = unpack(
560
      //    chunkData.slice(28, 32), uInt32_);
561
      //  wav.ds64.table = chunkData.slice(
562
      //     32, 32 + wav.ds64.tableLength);
563
      //}
564
    } else {
565
      if (this.container == 'RF64') {
566
        throw Error('Could not find the "ds64" chunk');
567
      }
568
    }
569
  }
570
571
  /**
572
   * Read the 'LIST' chunks of a wave file.
573
   * @param {!Uint8Array} buffer The wav file buffer.
574
   * @private
575
   */
576
  readLISTChunk_(buffer) {
577
    /** @type {?Object} */
578
    let listChunks = this.findChunk('LIST', true);
579
    if (listChunks !== null) {
580
      for (let j=0; j < listChunks.length; j++) {
581
        /** @type {!Object} */
582
        let subChunk = listChunks[j];
583
        this.LIST.push({
584
          chunkId: subChunk.chunkId,
585
          chunkSize: subChunk.chunkSize,
586
          format: subChunk.format,
587
          subChunks: []});
588
        for (let x=0; x<subChunk.subChunks.length; x++) {
589
          this.readLISTSubChunks_(subChunk.subChunks[x],
590
            subChunk.format, buffer);
591
        }
592
      }
593
    }
594
  }
595
596
  /**
597
   * Read the sub chunks of a 'LIST' chunk.
598
   * @param {!Object} subChunk The 'LIST' subchunks.
599
   * @param {string} format The 'LIST' format, 'adtl' or 'INFO'.
600
   * @param {!Uint8Array} buffer The wav file buffer.
601
   * @private
602
   */
603
  readLISTSubChunks_(subChunk, format, buffer) {
604
    if (format == 'adtl') {
605
      if (['labl', 'note','ltxt'].indexOf(subChunk.chunkId) > -1) {
606
        this.head_ = subChunk.chunkData.start;
607
        /** @type {!Object<string, string|number>} */
608
        let item = {
609
          chunkId: subChunk.chunkId,
610
          chunkSize: subChunk.chunkSize,
611
          dwName: this.readNumber(buffer, this.uInt32_)
612
        };
613
        if (subChunk.chunkId == 'ltxt') {
614
          item.dwSampleLength = this.readNumber(buffer, this.uInt32_);
615
          item.dwPurposeID = this.readNumber(buffer, this.uInt32_);
616
          item.dwCountry = this.readNumber(buffer, this.uInt16_);
617
          item.dwLanguage = this.readNumber(buffer, this.uInt16_);
618
          item.dwDialect = this.readNumber(buffer, this.uInt16_);
619
          item.dwCodePage = this.readNumber(buffer, this.uInt16_);
620
        }
621
        item.value = this.readZSTR(buffer, this.head_);
622
        this.LIST[this.LIST.length - 1].subChunks.push(item);
623
      }
624
    // RIFF INFO tags like ICRD, ISFT, ICMT
625
    } else if(format == 'INFO') {
626
      this.head_ = subChunk.chunkData.start;
627
      this.LIST[this.LIST.length - 1].subChunks.push({
628
        chunkId: subChunk.chunkId,
629
        chunkSize: subChunk.chunkSize,
630
        value: this.readZSTR(buffer, this.head_)
631
      });
632
    }
633
  }
634
635
  /**
636
   * Read the 'junk' chunk of a wave file.
637
   * @param {!Uint8Array} buffer The wav file buffer.
638
   * @private
639
   */
640
  readJunkChunk_(buffer) {
641
    /** @type {?Object} */
642
    let chunk = this.findChunk('junk');
643
    if (chunk) {
644
      this.junk = {
645
        chunkId: chunk.chunkId,
646
        chunkSize: chunk.chunkSize,
647
        chunkData: [].slice.call(buffer.slice(
648
          chunk.chunkData.start,
649
          chunk.chunkData.end))
650
      };
651
    }
652
  }
653
}
654