1(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
2exports.FLACDemuxer = require('./src/demuxer');
3exports.FLACDecoder = require('./src/decoder');
4require('./src/ogg');
5
6},{"./src/decoder":2,"./src/demuxer":3,"./src/ogg":4}],2:[function(require,module,exports){
7/*
8 * FLAC.js - Free Lossless Audio Codec decoder in JavaScript
9 * Original C version from FFmpeg (c) 2003 Alex Beregszaszi
10 * JavaScript port by Devon Govett and Jens Nockert of Official.fm Labs
11 *
12 * Licensed under the same terms as the original.  The original
13 * license follows.
14 *
15 * FLAC.js is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU Lesser General Public
17 * License as published by the Free Software Foundation; either
18 * version 2.1 of the License, or (at your option) any later version.
19 *
20 * FLAC.js is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23 * Lesser General Public License for more details.
24 *
25 */
26
27var AV = (window.AV);
28
29var FLACDecoder = AV.Decoder.extend(function() {
30    AV.Decoder.register('flac', this);
31
32    this.prototype.setCookie = function(cookie) {
33        this.cookie = cookie;
34
35        // initialize arrays
36        this.decoded = [];
37        for (var i = 0; i < this.format.channelsPerFrame; i++) {
38            this.decoded[i] = new Int32Array(cookie.maxBlockSize);
39        }
40
41        // for 24 bit lpc frames, this is used to simulate a 64 bit int
42        this.lpc_total = new Int32Array(2);
43    };
44
45    const BLOCK_SIZES = new Int16Array([
46               0,      192, 576 << 0, 576 << 1, 576 << 2, 576 << 3,        0,        0,
47        256 << 0, 256 << 1, 256 << 2, 256 << 3, 256 << 4, 256 << 5, 256 << 6, 256 << 7
48    ]);
49
50    const SAMPLE_RATES = new Int32Array([
51        0, 88200, 176400, 192000,
52        8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000,
53        0, 0, 0, 0
54    ]);
55
56    const SAMPLE_SIZES = new Int8Array([
57        0, 8, 12, 0, 16, 20, 24, 0
58    ]);
59
60    const MAX_CHANNELS = 8,
61          CHMODE_INDEPENDENT = 0,
62          CHMODE_LEFT_SIDE = 8,
63          CHMODE_RIGHT_SIDE = 9,
64          CHMODE_MID_SIDE = 10;
65
66    this.prototype.readChunk = function() {
67        var stream = this.bitstream;
68        if (!stream.available(32))
69            return;
70
71        // frame sync code
72        if ((stream.read(15) & 0x7FFF) !== 0x7FFC)
73            throw new Error('Invalid sync code');
74
75        var isVarSize = stream.read(1),  // variable block size stream code
76            bsCode = stream.read(4),  // block size
77            srCode = stream.read(4),  // sample rate code
78            chMode = stream.read(4),  // channel mode
79            bpsCode = stream.read(3); // bits per sample
80
81        stream.advance(1); // reserved bit
82
83        // channels
84        this.chMode = chMode;
85        var channels;
86
87        if (chMode < MAX_CHANNELS) {
88            channels = chMode + 1;
89            this.chMode = CHMODE_INDEPENDENT;
90        } else if (chMode <= CHMODE_MID_SIDE) {
91            channels = 2;
92        } else {
93            throw new Error('Invalid channel mode');
94        }
95
96        if (channels !== this.format.channelsPerFrame)
97            throw new Error('Switching channel layout mid-stream not supported.');
98
99        // bits per sample
100        if (bpsCode === 3 || bpsCode === 7)
101            throw new Error('Invalid sample size code');
102
103        this.bps = SAMPLE_SIZES[bpsCode];
104        if (this.bps !== this.format.bitsPerChannel)
105            throw new Error('Switching bits per sample mid-stream not supported.');
106
107        // sample number or frame number
108        // see http://www.hydrogenaudio.org/forums/index.php?s=ea7085ffe6d57132c36e6105c0d434c9&showtopic=88390&pid=754269&st=0&#entry754269
109        var ones = 0;
110        while (stream.read(1) === 1)
111            ones++;
112
113        var frame_or_sample_num = stream.read(7 - ones);
114        for (; ones > 1; ones--) {
115            stream.advance(2); // == 2
116            frame_or_sample_num = (frame_or_sample_num << 6) | stream.read(6);
117        }
118
119        // block size
120        if (bsCode === 0)
121            throw new Error('Reserved blocksize code');
122        else if (bsCode === 6)
123            this.blockSize = stream.read(8) + 1;
124        else if (bsCode === 7)
125            this.blockSize = stream.read(16) + 1;
126        else
127            this.blockSize = BLOCK_SIZES[bsCode];
128
129        // sample rate
130        var sampleRate;
131        if (srCode < 12)
132            sampleRate = SAMPLE_RATES[srCode];
133        else if (srCode === 12)
134            sampleRate = stream.read(8) * 1000;
135        else if (srCode === 13)
136            sampleRate = stream.read(16);
137        else if (srCode === 14)
138            sampleRate = stream.read(16) * 10;
139        else
140            throw new Error('Invalid sample rate code');
141
142        stream.advance(8); // skip CRC check
143
144        // subframes
145        for (var i = 0; i < channels; i++)
146            this.decodeSubframe(i);
147
148        stream.align();
149        stream.advance(16); // skip CRC frame footer
150
151        var is32 = this.bps > 16,
152            output = new ArrayBuffer(this.blockSize * channels * (is32 ? 4 : 2)),
153            buf = is32 ? new Int32Array(output) : new Int16Array(output),
154            blockSize = this.blockSize,
155            decoded = this.decoded,
156            j = 0;
157
158        switch (this.chMode) {
159            case CHMODE_INDEPENDENT:
160                for (var k = 0; k < blockSize; k++) {
161                    for (var i = 0; i < channels; i++) {
162                        buf[j++] = decoded[i][k];
163                    }
164                }
165                break;
166
167            case CHMODE_LEFT_SIDE:
168                for (var i = 0; i < blockSize; i++) {
169                    var left = decoded[0][i],
170                        right = decoded[1][i];
171
172                    buf[j++] = left;
173                    buf[j++] = (left - right);
174                }
175                break;
176
177            case CHMODE_RIGHT_SIDE:
178                for (var i = 0; i < blockSize; i++) {
179                    var left = decoded[0][i],
180                        right = decoded[1][i];
181
182                    buf[j++] = (left + right);
183                    buf[j++] = right;
184                }
185                break;
186
187            case CHMODE_MID_SIDE:
188                for (var i = 0; i < blockSize; i++) {
189                    var left = decoded[0][i],
190                        right = decoded[1][i];
191
192                    left -= right >> 1;
193                    buf[j++] = (left + right);
194                    buf[j++] = left;
195                }
196                break;
197        }
198
199        return buf;
200    };
201
202    this.prototype.decodeSubframe = function(channel) {
203        var wasted = 0,
204            stream = this.bitstream,
205            blockSize = this.blockSize,
206            decoded = this.decoded;
207
208        this.curr_bps = this.bps;
209        if (channel === 0) {
210            if (this.chMode === CHMODE_RIGHT_SIDE)
211                this.curr_bps++;
212        } else {
213            if (this.chMode === CHMODE_LEFT_SIDE || this.chMode === CHMODE_MID_SIDE)
214                this.curr_bps++;
215        }
216
217        if (stream.read(1))
218            throw new Error("Invalid subframe padding");
219
220        var type = stream.read(6);
221
222        if (stream.read(1)) {
223            wasted = 1;
224            while (!stream.read(1))
225                wasted++;
226
227            this.curr_bps -= wasted;
228        }
229
230        if (this.curr_bps > 32)
231            throw new Error("decorrelated bit depth > 32 (" + this.curr_bps + ")");
232
233        if (type === 0) {
234            var tmp = stream.read(this.curr_bps, true);
235            for (var i = 0; i < blockSize; i++)
236                decoded[channel][i] = tmp;
237
238        } else if (type === 1) {
239            var bps = this.curr_bps;
240            for (var i = 0; i < blockSize; i++)
241                decoded[channel][i] = stream.read(bps, true);
242
243        } else if ((type >= 8) && (type <= 12)) {
244            this.decode_subframe_fixed(channel, type & ~0x8);
245
246        } else if (type >= 32) {
247            this.decode_subframe_lpc(channel, (type & ~0x20) + 1);
248
249        } else {
250            throw new Error("Invalid coding type");
251        }
252
253        if (wasted) {
254            for (var i = 0; i < blockSize; i++)
255                decoded[channel][i] <<= wasted;
256        }
257    };
258
259    this.prototype.decode_subframe_fixed = function(channel, predictor_order) {
260        var decoded = this.decoded[channel],
261            stream = this.bitstream,
262            bps = this.curr_bps;
263
264        // warm up samples
265        for (var i = 0; i < predictor_order; i++)
266            decoded[i] = stream.read(bps, true);
267
268        this.decode_residuals(channel, predictor_order);
269
270        var a = 0, b = 0, c = 0, d = 0;
271
272        if (predictor_order > 0)
273            a = decoded[predictor_order - 1];
274
275        if (predictor_order > 1)
276            b = a - decoded[predictor_order - 2];
277
278        if (predictor_order > 2)
279            c = b - decoded[predictor_order - 2] + decoded[predictor_order - 3];
280
281        if (predictor_order > 3)
282            d = c - decoded[predictor_order - 2] + 2 * decoded[predictor_order - 3] - decoded[predictor_order - 4];
283
284        switch (predictor_order) {
285            case 0:
286                break;
287
288            case 1:
289            case 2:
290            case 3:
291            case 4:
292                var abcd = new Int32Array([a, b, c, d]),
293                    blockSize = this.blockSize;
294
295                for (var i = predictor_order; i < blockSize; i++) {
296                    abcd[predictor_order - 1] += decoded[i];
297
298                    for (var j = predictor_order - 2; j >= 0; j--) {
299                        abcd[j] += abcd[j + 1];
300                    }
301
302                    decoded[i] = abcd[0];
303                }
304
305                break;
306
307            default:
308                throw new Error("Invalid Predictor Order " + predictor_order);
309        }
310    };
311
312    this.prototype.decode_subframe_lpc = function(channel, predictor_order) {
313        var stream = this.bitstream,
314            decoded = this.decoded[channel],
315            bps = this.curr_bps,
316            blockSize = this.blockSize;
317
318        // warm up samples
319        for (var i = 0; i < predictor_order; i++) {
320            decoded[i] = stream.read(bps, true);
321        }
322
323        var coeff_prec = stream.read(4) + 1;
324        if (coeff_prec === 16)
325            throw new Error("Invalid coefficient precision");
326
327        var qlevel = stream.read(5, true);
328        if (qlevel < 0)
329            throw new Error("Negative qlevel, maybe buggy stream");
330
331        var coeffs = new Int32Array(32);
332        for (var i = 0; i < predictor_order; i++) {
333            coeffs[i] = stream.read(coeff_prec, true);
334        }
335
336        this.decode_residuals(channel, predictor_order);
337
338        if (this.bps <= 16) {
339            for (var i = predictor_order; i < blockSize - 1; i += 2) {
340                var d = decoded[i - predictor_order],
341                    s0 = 0, s1 = 0, c = 0;
342
343                for (var j = predictor_order - 1; j > 0; j--) {
344                    c = coeffs[j];
345                    s0 += c * d;
346                    d = decoded[i - j];
347                    s1 += c * d;
348                }
349
350                c = coeffs[0];
351                s0 += c * d;
352                d = decoded[i] += (s0 >> qlevel);
353                s1 += c * d;
354                decoded[i + 1] += (s1 >> qlevel);
355            }
356
357            if (i < blockSize) {
358                var sum = 0;
359                for (var j = 0; j < predictor_order; j++)
360                    sum += coeffs[j] * decoded[i - j - 1];
361
362                decoded[i] += (sum >> qlevel);
363            }
364        } else {
365            // simulate 64 bit integer using an array of two 32 bit ints
366            var total = this.lpc_total;
367            for (var i = predictor_order; i < blockSize; i++) {
368                // reset total to 0
369                total[0] = 0;
370                total[1] = 0;
371
372                for (j = 0; j < predictor_order; j++) {
373                    // simulate `total += coeffs[j] * decoded[i - j - 1]`
374                    multiply_add(total, coeffs[j], decoded[i - j - 1]);
375                }
376
377                // simulate `decoded[i] += total >> qlevel`
378                // we know that qlevel < 32 since it is a 5 bit field (see above)
379                decoded[i] += (total[0] >>> qlevel) | (total[1] << (32 - qlevel));
380            }
381        }
382    };
383
384    const TWO_PWR_32_DBL = Math.pow(2, 32);
385
386    // performs `total += a * b` on a simulated 64 bit int
387    // total is an Int32Array(2)
388    // a and b are JS numbers (32 bit ints)
389    function multiply_add(total, a, b) {
390        // multiply a * b (we can use normal JS multiplication for this)
391        var r = a * b;
392        var n = r < 0;
393        if (n)
394            r = -r;
395
396        var r_low = (r % TWO_PWR_32_DBL) | 0;
397        var r_high = (r / TWO_PWR_32_DBL) | 0;
398        if (n) {
399            r_low = ~r_low + 1;
400            r_high = ~r_high;
401        }
402
403        // add result to total
404        var a48 = total[1] >>> 16;
405        var a32 = total[1] & 0xFFFF;
406        var a16 = total[0] >>> 16;
407        var a00 = total[0] & 0xFFFF;
408
409        var b48 = r_high >>> 16;
410        var b32 = r_high & 0xFFFF;
411        var b16 = r_low >>> 16;
412        var b00 = r_low & 0xFFFF;
413
414        var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
415        c00 += a00 + b00;
416        c16 += c00 >>> 16;
417        c00 &= 0xFFFF;
418        c16 += a16 + b16;
419        c32 += c16 >>> 16;
420        c16 &= 0xFFFF;
421        c32 += a32 + b32;
422        c48 += c32 >>> 16;
423        c32 &= 0xFFFF;
424        c48 += a48 + b48;
425        c48 &= 0xFFFF;
426
427        // store result back in total
428        total[0] = (c16 << 16) | c00;
429        total[1] = (c48 << 16) | c32;
430    }
431
432    const INT_MAX = 32767;
433
434    this.prototype.decode_residuals = function(channel, predictor_order) {
435        var stream = this.bitstream,
436            method_type = stream.read(2);
437
438        if (method_type > 1)
439            throw new Error('Illegal residual coding method ' + method_type);
440
441        var rice_order = stream.read(4),
442            samples = (this.blockSize >>> rice_order);
443
444        if (predictor_order > samples)
445            throw new Error('Invalid predictor order ' + predictor_order + ' > ' + samples);
446
447        var decoded = this.decoded[channel],
448            sample = predictor_order,
449            i = predictor_order;
450
451        for (var partition = 0; partition < (1 << rice_order); partition++) {
452            var tmp = stream.read(method_type === 0 ? 4 : 5);
453
454            if (tmp === (method_type === 0 ? 15 : 31)) {
455                tmp = stream.read(5);
456                for (; i < samples; i++)
457                    decoded[sample++] = stream.read(tmp, true);
458
459            } else {
460                for (; i < samples; i++)
461                    decoded[sample++] = this.golomb(tmp, INT_MAX, 0);
462            }
463
464            i = 0;
465        }
466    };
467
468    const MIN_CACHE_BITS = 25;
469
470    this.prototype.golomb = function(k, limit, esc_len) {
471        var data = this.bitstream,
472            offset = data.bitPosition,
473            buf = data.peek(32 - offset) << offset,
474            v = 0;
475
476        var log = 31 - clz(buf | 1); // log2(buf)
477
478        if (log - k >= 32 - MIN_CACHE_BITS && 32 - log < limit) {
479            buf >>>= log - k;
480            buf += (30 - log) << k;
481
482            data.advance(32 + k - log);
483            v = buf;
484
485        } else {
486            for (var i = 0; data.read(1) === 0; i++)
487                buf = data.peek(32 - offset) << offset;
488
489            if (i < limit - 1) {
490                if (k)
491                    buf = data.read(k);
492                else
493                    buf = 0;
494
495                v = buf + (i << k);
496
497            } else if (i === limit - 1) {
498                buf = data.read(esc_len);
499                v = buf + 1;
500
501            } else {
502                v = -1;
503            }
504        }
505
506        return (v >> 1) ^ -(v & 1);
507    };
508
509    // Should be in the damned standard library...
510    function clz(input) {
511        var output = 0,
512            curbyte = 0;
513
514        while(true) { // emulate goto in JS using the break statement :D
515            curbyte = input >>> 24;
516            if (curbyte) break;
517            output += 8;
518
519            curbyte = input >>> 16;
520            if (curbyte & 0xff) break;
521            output += 8;
522
523            curbyte = input >>> 8;
524            if (curbyte & 0xff) break;
525            output += 8;
526
527            curbyte = input;
528            if (curbyte & 0xff) break;
529            output += 8;
530
531            return output;
532        }
533
534        if (!(curbyte & 0xf0))
535            output += 4;
536        else
537            curbyte >>>= 4;
538
539        if (curbyte & 0x8)
540            return output;
541
542        if (curbyte & 0x4)
543            return output + 1;
544
545        if (curbyte & 0x2)
546            return output + 2;
547
548        if (curbyte & 0x1)
549            return output + 3;
550
551        // shouldn't get here
552        return output + 4;
553    }
554});
555
556module.exports = FLACDecoder;
557
558},{}],3:[function(require,module,exports){
559/*
560 * FLAC.js - Free Lossless Audio Codec decoder in JavaScript
561 * By Devon Govett and Jens Nockert of Official.fm Labs
562 *
563 * FLAC.js is free software; you can redistribute it and/or
564 * modify it under the terms of the GNU Lesser General Public
565 * License as published by the Free Software Foundation; either
566 * version 2.1 of the License, or (at your option) any later version.
567 *
568 * FLAC.js is distributed in the hope that it will be useful,
569 * but WITHOUT ANY WARRANTY; without even the implied warranty of
570 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
571 * Lesser General Public License for more details.
572 *
573 */
574
575var AV = (window.AV);
576
577var FLACDemuxer = AV.Demuxer.extend(function() {
578    AV.Demuxer.register(this);
579
580    this.probe = function(buffer) {
581        return buffer.peekString(0, 4) === 'fLaC';
582    }
583
584    const STREAMINFO = 0,
585          PADDING = 1,
586          APPLICATION = 2,
587          SEEKTABLE = 3,
588          VORBIS_COMMENT = 4,
589          CUESHEET = 5,
590          PICTURE = 6,
591          INVALID = 127,
592          STREAMINFO_SIZE = 34;
593
594    this.prototype.readChunk = function() {
595        var stream = this.stream;
596
597        if (!this.readHeader && stream.available(4)) {
598            if (stream.readString(4) !== 'fLaC')
599                return this.emit('error', 'Invalid FLAC file.');
600
601            this.readHeader = true;
602        }
603
604        while (stream.available(1) && !this.last) {
605            if (!this.readBlockHeaders) {
606                var tmp = stream.readUInt8();
607                this.last = (tmp & 0x80) === 0x80,
608                this.type = tmp & 0x7F,
609                this.size = stream.readUInt24();
610            }
611
612            if (!this.foundStreamInfo && this.type !== STREAMINFO)
613                return this.emit('error', 'STREAMINFO must be the first block');
614
615            if (!stream.available(this.size))
616                return;
617
618            switch (this.type) {
619                case STREAMINFO:
620                    if (this.foundStreamInfo)
621                        return this.emit('error', 'STREAMINFO can only occur once.');
622
623                    if (this.size !== STREAMINFO_SIZE)
624                        return this.emit('error', 'STREAMINFO size is wrong.');
625
626                    this.foundStreamInfo = true;
627                    var bitstream = new AV.Bitstream(stream);
628
629                    var cookie = {
630                        minBlockSize: bitstream.read(16),
631                        maxBlockSize: bitstream.read(16),
632                        minFrameSize: bitstream.read(24),
633                        maxFrameSize: bitstream.read(24)
634                    };
635
636                    this.format = {
637                        formatID: 'flac',
638                        sampleRate: bitstream.read(20),
639                        channelsPerFrame: bitstream.read(3) + 1,
640                        bitsPerChannel: bitstream.read(5) + 1
641                    };
642
643                    this.emit('format', this.format);
644                    this.emit('cookie', cookie);
645
646                    var sampleCount = bitstream.read(36);
647                    this.emit('duration', sampleCount / this.format.sampleRate * 1000 | 0);
648
649                    stream.advance(16); // skip MD5 hashes
650                    this.readBlockHeaders = false;
651                    break;
652
653                    /*
654                    I am only looking at the least significant 32 bits of sample number and offset data
655                    This is more than sufficient for the longest flac file I have (~50 mins 2-channel 16-bit 44.1k which uses about 7.5% of the UInt32 space for the largest offset)
656                    Can certainly be improved by storing sample numbers and offests as doubles, but would require additional overriding of the searchTimestamp and seek functions (possibly more?)
657                    Also the flac faq suggests it would be possible to find frame lengths and thus create seek points on the fly via decoding but I assume this would be slow
658                    I may look into these thigns though as my project progresses
659                    */
660                    case SEEKTABLE:
661                        for(var s=0; s<this.size/18; s++)
662                        {
663                            if(stream.peekUInt32(0) == 0xFFFFFFFF && stream.peekUInt32(1) == 0xFFFFFFFF)
664                            {
665                                //placeholder, ignore
666                                stream.advance(18);
667                            } else {
668                                if(stream.readUInt32() > 0)
669                                {
670                                    this.emit('error', 'Seek points with sample number >UInt32 not supported');
671                                }
672                                var samplenum = stream.readUInt32();
673                                if(stream.readUInt32() > 0)
674                                {
675                                    this.emit('error', 'Seek points with stream offset >UInt32 not supported');
676                                }
677                                var offset = stream.readUInt32();
678
679                                stream.advance(2);
680
681                                this.addSeekPoint(offset, samplenum);
682                            }
683                        }
684                        break;
685
686                case VORBIS_COMMENT:
687                    // see http://www.xiph.org/vorbis/doc/v-comment.html
688                    this.metadata || (this.metadata = {});
689                    var len = stream.readUInt32(true);
690
691                    this.metadata.vendor = stream.readString(len);
692                    var length = stream.readUInt32(true);
693
694                    for (var i = 0; i < length; i++) {
695                        len = stream.readUInt32(true);
696                        var str = stream.readString(len, 'utf8'),
697                            idx = str.indexOf('=');
698
699                        this.metadata[str.slice(0, idx).toLowerCase()] = str.slice(idx + 1);
700                    }
701
702                    // TODO: standardize field names across formats
703                    break;
704
705                case PICTURE:
706                    var type = stream.readUInt32();
707                    if (type !== 3) { // make sure this is album art (type 3)
708                        stream.advance(this.size - 4);
709                    } else {
710                        var mimeLen = stream.readUInt32(),
711                            mime = stream.readString(mimeLen),
712                            descLen = stream.readUInt32(),
713                            description = stream.readString(descLen),
714                            width = stream.readUInt32(),
715                            height = stream.readUInt32(),
716                            depth = stream.readUInt32(),
717                            colors = stream.readUInt32(),
718                            length = stream.readUInt32(),
719                            picture = stream.readBuffer(length);
720
721                        this.metadata || (this.metadata = {});
722                        this.metadata.coverArt = picture;
723                    }
724
725                    // does anyone want the rest of the info?
726                    break;
727
728                default:
729                    stream.advance(this.size);
730                    this.readBlockHeaders = false;
731            }
732
733            if (this.last && this.metadata)
734                this.emit('metadata', this.metadata);
735        }
736
737        while (stream.available(1) && this.last) {
738            var buffer = stream.readSingleBuffer(stream.remainingBytes());
739            this.emit('data', buffer);
740        }
741    }
742
743});
744
745module.exports = FLACDemuxer;
746
747},{}],4:[function(require,module,exports){
748var AV = (window.AV);
749
750// if ogg.js exists, register a plugin
751try {
752  var OggDemuxer = (window.AV.OggDemuxer);
753} catch (e) {};
754if (!OggDemuxer) return;
755
756OggDemuxer.plugins.push({
757  magic: "\177FLAC",
758
759  init: function() {
760    this.list = new AV.BufferList();
761    this.stream = new AV.Stream(this.list);
762  },
763
764  readHeaders: function(packet) {
765    var stream = this.stream;
766    this.list.append(new AV.Buffer(packet));
767
768    stream.advance(5); // magic
769    if (stream.readUInt8() != 1)
770      throw new Error('Unsupported FLAC version');
771
772    stream.advance(3);
773    if (stream.peekString(0, 4) != 'fLaC')
774      throw new Error('Not flac');
775
776    this.flac = AV.Demuxer.find(stream.peekSingleBuffer(0, stream.remainingBytes()));
777    if (!this.flac)
778      throw new Error('Flac demuxer not found');
779
780    this.flac.prototype.readChunk.call(this);
781    return true;
782  },
783
784  readPacket: function(packet) {
785    this.list.append(new AV.Buffer(packet));
786    this.flac.prototype.readChunk.call(this);
787  }
788});
789
790},{}]},{},[1])
791
792
793//# sourceMappingURL=flac.js.map