예제 #1
0
        private void ReadSamples(MpegFrame frame)
        {
            // load in all the data for this frame (1152 samples in this case)
            // NB: we flatten these into output order
            for (int ss = 0, idx = 0; ss < SSLIMIT; ss++, idx += SBLIMIT * (_granuleCount - 1))
            {
                for (int sb = 0; sb < SBLIMIT; sb++, idx++)
                {
                    for (int ch = 0; ch < _channels; ch++)
                    {
                        if (ch == 0 || sb < _jsbound)
                        {
                            int[] samples = _samples[ch];
                            int   alloc   = _allocation[ch][sb];
                            if (alloc != 0)
                            {
                                if (alloc < 0)
                                {
                                    // grouping (Layer II only, so we don't have to play with the granule count)
                                    int val    = frame.ReadBits(-alloc);
                                    int levels = (1 << (-alloc / 2 + -alloc % 2 - 1)) + 1;

                                    samples[idx]               = val % levels;
                                    val                       /= levels;
                                    samples[idx + SBLIMIT]     = val % levels;
                                    samples[idx + SBLIMIT * 2] = val / levels;
                                }
                                else
                                {
                                    // non-grouping
                                    for (int gr = 0; gr < _granuleCount; gr++)
                                    {
                                        samples[idx + SBLIMIT * gr] = frame.ReadBits(alloc);
                                    }
                                }
                            }
                            else
                            {
                                // no energy...  zero out the samples
                                for (int gr = 0; gr < _granuleCount; gr++)
                                {
                                    samples[idx + SBLIMIT * gr] = 0;
                                }
                            }
                        }
                        else
                        {
                            int[] samples0 = _samples[0];
                            int[] samples1 = _samples[1];

                            // copy chan 0 to chan 1
                            for (int gr = 0; gr < _granuleCount; gr++)
                            {
                                samples1[idx + SBLIMIT * gr] = samples0[idx + SBLIMIT * gr];
                            }
                        }
                    }
                }
            }
        }
예제 #2
0
        private void ReadAllocation(MpegFrame frame, int[] rateTable)
        {
            var _subBandCount = rateTable.Length;

            if (_jsbound > _subBandCount)
            {
                _jsbound = _subBandCount;
            }

            Array.Clear(_allocation[0], 0, SBLIMIT);
            Array.Clear(_allocation[1], 0, SBLIMIT);

            int sb = 0;

            for (; sb < _jsbound; sb++)
            {
                int[] table = _allocLookupTable[rateTable[sb]];
                int   bits  = table[0];

                for (int ch = 0; ch < _channels; ch++)
                {
                    _allocation[ch][sb] = table[frame.ReadBits(bits) + 1];
                }
            }
            for (; sb < _subBandCount; sb++)
            {
                int[] table = _allocLookupTable[rateTable[sb]];
                _allocation[0][sb] = _allocation[1][sb] = table[frame.ReadBits(table[0]) + 1];
            }
        }
예제 #3
0
        private void ReadScaleFactors(MpegFrame frame)
        {
            for (int sb = 0; sb < SBLIMIT; sb++)
            {
                for (int ch = 0; ch < _channels; ch++)
                {
                    int[][] scalefac = _scalefac[ch];
                    switch (_scfsi[ch][sb])
                    {
                    case 0:
                        // all three
                        scalefac[0][sb] = frame.ReadBits(6);
                        scalefac[1][sb] = frame.ReadBits(6);
                        scalefac[2][sb] = frame.ReadBits(6);
                        break;

                    case 1:
                        // only two (2 = 1)
                        scalefac[0][sb]     =
                            scalefac[1][sb] = frame.ReadBits(6);
                        scalefac[2][sb]     = frame.ReadBits(6);
                        break;

                    case 2:
                        // only one (3 = 2 = 1)
                        scalefac[0][sb]         =
                            scalefac[1][sb]     =
                                scalefac[2][sb] = frame.ReadBits(6);
                        break;

                    case 3:
                        // only two (3 = 2)
                        scalefac[0][sb]     = frame.ReadBits(6);
                        scalefac[1][sb]     =
                            scalefac[2][sb] = frame.ReadBits(6);
                        break;

                    default:
                        // none
                        scalefac[0][sb] = 63;
                        scalefac[1][sb] = 63;
                        scalefac[2][sb] = 63;
                        break;
                    }
                }
            }
        }
예제 #4
0
        public bool AddBits(MpegFrame frame, int overlap)
        {
            int originalEnd = _end;

            int slots = GetSlots(frame);

            while (--slots >= 0)
            {
                int tmp = frame.ReadBits(8);
                if (tmp == -1)
                {
                    ThrowFrameNotEnoughBytes();
                }

                _buf[++_end] = (byte)tmp;
                if (_end == BufferSize - 1)
                {
                    _end = -1;
                }
            }

            _bitsLeft = 8;
            if (originalEnd == -1)
            {
                // it's either the start of the stream or we've reset...
                // only return true if overlap says this frame is enough
                return(overlap == 0);
            }
            else
            {
                // it's not the start of the stream so calculate _start based on whether we have enough bytes left

                // if we have enough bytes, reset start to match overlap
                if ((originalEnd + 1 - _start + BufferSize) % BufferSize >= overlap)
                {
                    _start = (originalEnd + 1 - overlap + BufferSize) % BufferSize;
                    return(true);
                }
                // otherwise, just set start to match the start of the frame (we probably skipped a frame)
                else
                {
                    _start = originalEnd;
                    return(false);
                }
            }
        }
예제 #5
0
        private static int GetSlots(MpegFrame frame)
        {
            int cnt = frame.FrameLength - 4;

            if (frame.HasCrc)
            {
                cnt -= 2;
            }

            if (frame.Version == MpegVersion.Version1 && frame.ChannelMode != MpegChannelMode.Mono)
            {
                return(cnt - 32);
            }
            if (frame.Version > MpegVersion.Version1 && frame.ChannelMode == MpegChannelMode.Mono)
            {
                return(cnt - 9);
            }
            return(cnt - 17);
        }
예제 #6
0
        // this just reads the channel mode and set a few flags
        private void InitFrame(MpegFrame frame)
        {
            switch (frame.ChannelMode)
            {
            case MpegChannelMode.Mono:
                _channels = 1;
                _jsbound  = SBLIMIT;
                break;

            case MpegChannelMode.JointStereo:
                _channels = 2;
                _jsbound  = frame.ChannelModeExtension * 4 + 4;
                break;

            default:
                _channels = 2;
                _jsbound  = SBLIMIT;
                break;
            }
        }
예제 #7
0
        public override int DecodeFrame(MpegFrame frame, Span <float> ch0, Span <float> ch1)
        {
            InitFrame(frame);

            int[] rateTable = GetRateTable(frame);
            ReadAllocation(frame, rateTable);

            for (int i = 0; i < _scfsi[0].Length; i++)
            {
                // Since Layer II has to know which subbands have energy,
                // we use the "Layer I valid" selection to mark that energy is present.
                // That way Layer I doesn't have to do anything else.
                _scfsi[0][i] = _allocation[0][i] != 0 ? 2 : -1;
                _scfsi[1][i] = _allocation[1][i] != 0 ? 2 : -1;
            }
            ReadScaleFactorSelection(frame, _scfsi, _channels);

            ReadScaleFactors(frame);

            ReadSamples(frame);

            return(DecodeSamples(ch0, ch1));
        }
예제 #8
0
        internal MpegFrame NextFrame()
        {
            // if _current is null, we've returned the last frame already
            var frame = _current;

            if (frame != null)
            {
                if (_canSeek)
                {
                    frame.SaveBuffer();
                    DiscardThrough(frame.Offset + frame.FrameLength, false);
                }

                if (frame == _last && !_endFound)
                {
                    do
                    {
                        FindNextFrame();
                    } while (frame == _last && !_endFound);
                }

                _current = frame.Next;

                if (!_canSeek)
                {
                    // if we're in a forward-only stream, don't bother keeping the frames that have already been processed
                    lock (_frameLock)
                    {
                        var temp = _first;
                        _first    = temp.Next;
                        temp.Next = null;
                    }
                }
            }
            return(frame);
        }
예제 #9
0
        FrameBase FindNextFrame()
        {
            // if we've found the end, don't bother looking for anything else
            if (_endFound)
            {
                return(null);
            }

            var freeFrame      = _lastFree;
            var lastFrameStart = _readOffset;

            lock (_frameLock)
            {
                // read 3 bytes
                var syncBuf = new byte[4];
                try
                {
                    if (Read(_readOffset, syncBuf, 0, 4) == 4)
                    {
                        // now loop until a frame is found
                        do
                        {
                            var sync = (uint)(syncBuf[0] << 24 | syncBuf[1] << 16 | syncBuf[2] << 8 | syncBuf[3]);

                            lastFrameStart = _readOffset;

                            // try ID3 first (for v2 frames)
                            if (_id3Frame == null)
                            {
                                var f = ID3Frame.TrySync(sync);
                                if (f != null)
                                {
                                    if (f.Validate(_readOffset, this))
                                    {
                                        if (!_canSeek)
                                        {
                                            f.SaveBuffer();
                                        }

                                        _readOffset += f.Length;
                                        DiscardThrough(_readOffset, true);

                                        return(_id3Frame = f);
                                    }
                                }
                            }

                            // now look for a RIFF header
                            if (_first == null && _riffHeaderFrame == null)
                            {
                                var f = RiffHeaderFrame.TrySync(sync);
                                if (f != null)
                                {
                                    if (f.Validate(_readOffset, this))
                                    {
                                        _readOffset += f.Length;
                                        DiscardThrough(_readOffset, true);

                                        return(_riffHeaderFrame = f);
                                    }
                                }
                            }

                            // finally, just try for an MPEG frame
                            var frame = MpegFrame.TrySync(sync);
                            if (frame != null)
                            {
                                if (frame.Validate(_readOffset, this) &&
                                    !(freeFrame != null &&
                                      (frame.Layer != freeFrame.Layer ||
                                       frame.Version != freeFrame.Version ||
                                       frame.SampleRate != freeFrame.SampleRate ||
                                       frame.BitRateIndex > 0
                                      )
                                      )
                                    )
                                {
                                    if (!_canSeek)
                                    {
                                        frame.SaveBuffer();
                                        DiscardThrough(_readOffset + frame.FrameLength, true);
                                    }

                                    _readOffset += frame.FrameLength;

                                    if (_first == null)
                                    {
                                        if (_vbrInfo == null && (_vbrInfo = frame.ParseVBR()) != null)
                                        {
                                            return(FindNextFrame());
                                        }
                                        else
                                        {
                                            frame.Number = 0;
                                            _first       = _last = frame;
                                        }
                                    }
                                    else
                                    {
                                        if (frame.SampleCount != _first.SampleCount)
                                        {
                                            _mixedFrameSize = true;
                                        }

                                        frame.SampleOffset = _last.SampleCount + _last.SampleOffset;
                                        frame.Number       = _last.Number + 1;
                                        _last = (_last.Next = frame);
                                    }

                                    if (frame.BitRateIndex == 0)
                                    {
                                        _lastFree = frame;
                                    }

                                    return(frame);
                                }
                            }

                            // if we've read MPEG frames and can't figure out what frame type we have, try looking for a new ID3 tag
                            if (_last != null)
                            {
                                var f = ID3Frame.TrySync(sync);
                                if (f != null)
                                {
                                    if (f.Validate(_readOffset, this))
                                    {
                                        if (!_canSeek)
                                        {
                                            f.SaveBuffer();
                                        }

                                        // if it's a v1 tag, go ahead and parse it
                                        if (f.Version == 1)
                                        {
                                            _id3v1Frame = f;
                                        }
                                        else
                                        {
                                            // grrr...  the ID3 2.4 spec says tags can be anywhere in the file and that later tags can override earlier ones...  boo
                                            _id3Frame.Merge(f);
                                        }

                                        _readOffset += f.Length;
                                        DiscardThrough(_readOffset, true);

                                        return(f);
                                    }
                                }
                            }

                            // well, we didn't find anything, so rinse and repeat with the next byte
                            ++_readOffset;
                            if (_first == null || !_canSeek)
                            {
                                DiscardThrough(_readOffset, true);
                            }
                            Buffer.BlockCopy(syncBuf, 1, syncBuf, 0, 3);
                        } while (Read(_readOffset + 3, syncBuf, 3, 1) == 1);
                    }

                    // move the "end of frame" marker for the last free format frame (in case we have one)
                    // this is because we don't include the last four bytes otherwise
                    lastFrameStart += 4;

                    _endFound = true;
                    return(null);
                }
                finally
                {
                    if (freeFrame != null)
                    {
                        freeFrame.Length = (int)(lastFrameStart - freeFrame.Offset);

                        if (!_canSeek)
                        {
                            // gotta finish filling the buffer!!
                            throw new InvalidOperationException("Free frames cannot be read properly from forward-only streams!");
                        }

                        // if _lastFree hasn't changed (we got a non-MPEG frame), clear it out
                        if (_lastFree == freeFrame)
                        {
                            _lastFree = null;
                        }
                    }
                }
            }
        }
        FrameBase FindNextFrame()
        {
            // if we've found the end, don't bother looking for anything else
            if (_endFound) return null;

            var freeFrame = _lastFree;
            var lastFrameStart = _readOffset;

            lock (_frameLock)
            {
                // read 3 bytes
                var syncBuf = new byte[4];
                try
                {
                    if (Read(_readOffset, syncBuf, 0, 4) == 4)
                    {
                        // now loop until a frame is found
                        do
                        {
                            var sync = (uint)(syncBuf[0] << 24 | syncBuf[1] << 16 | syncBuf[2] << 8 | syncBuf[3]);

                            lastFrameStart = _readOffset;

                            // try ID3 first (for v2 frames)
                            if (_id3Frame == null)
                            {
                                var f = ID3Frame.TrySync(sync);
                                if (f != null)
                                {
                                    if (f.Validate(_readOffset, this))
                                    {
                                        if (!_canSeek) f.SaveBuffer();

                                        _readOffset += f.Length;
                                        DiscardThrough(_readOffset, true);

                                        return _id3Frame = f;
                                    }
                                }
                            }

                            // now look for a RIFF header
                            if (_first == null && _riffHeaderFrame == null)
                            {
                                var f = RiffHeaderFrame.TrySync(sync);
                                if (f != null)
                                {
                                    if (f.Validate(_readOffset, this))
                                    {
                                        _readOffset += f.Length;
                                        DiscardThrough(_readOffset, true);

                                        return _riffHeaderFrame = f;
                                    }
                                }
                            }

                            // finally, just try for an MPEG frame
                            var frame = MpegFrame.TrySync(sync);
                            if (frame != null)
                            {
                                if (frame.Validate(_readOffset, this)
                                   && !(freeFrame != null
                                       && (frame.Layer != freeFrame.Layer
                                          || frame.Version != freeFrame.Version
                                          || frame.SampleRate != freeFrame.SampleRate
                                          || frame.BitRateIndex > 0
                                          )
                                       )
                                   )
                                {
                                    if (!_canSeek)
                                    {
                                        frame.SaveBuffer();
                                        DiscardThrough(_readOffset + frame.FrameLength, true);
                                    }

                                    _readOffset += frame.FrameLength;

                                    if (_first == null)
                                    {
                                        if (_vbrInfo == null && (_vbrInfo = frame.ParseVBR()) != null)
                                        {
                                            return FindNextFrame();
                                        }
                                        else
                                        {
                                            frame.Number = 0;
                                            _first = _last = frame;
                                        }
                                    }
                                    else
                                    {
                                        if (frame.SampleCount != _first.SampleCount)
                                        {
                                            _mixedFrameSize = true;
                                        }

                                        frame.SampleOffset = _last.SampleCount + _last.SampleOffset;
                                        frame.Number = _last.Number + 1;
                                        _last = (_last.Next = frame);
                                    }

                                    if (frame.BitRateIndex == 0)
                                    {
                                        _lastFree = frame;
                                    }

                                    return frame;
                                }
                            }

                            // if we've read MPEG frames and can't figure out what frame type we have, try looking for a new ID3 tag
                            if (_last != null)
                            {
                                var f = ID3Frame.TrySync(sync);
                                if (f != null)
                                {
                                    if (f.Validate(_readOffset, this))
                                    {
                                        if (!_canSeek) f.SaveBuffer();

                                        // if it's a v1 tag, go ahead and parse it
                                        if (f.Version == 1)
                                        {
                                            _id3v1Frame = f;
                                        }
                                        else
                                        {
                                            // grrr...  the ID3 2.4 spec says tags can be anywhere in the file and that later tags can override earlier ones...  boo
                                            _id3Frame.Merge(f);
                                        }

                                        _readOffset += f.Length;
                                        DiscardThrough(_readOffset, true);

                                        return f;
                                    }
                                }
                            }

                            // well, we didn't find anything, so rinse and repeat with the next byte
                            ++_readOffset;
                            if (_first == null || !_canSeek) DiscardThrough(_readOffset, true);
                            Buffer.BlockCopy(syncBuf, 1, syncBuf, 0, 3);
                        } while (Read(_readOffset + 3, syncBuf, 3, 1) == 1);
                    }

                    // move the "end of frame" marker for the last free format frame (in case we have one)
                    // this is because we don't include the last four bytes otherwise
                    lastFrameStart += 4;

                    _endFound = true;
                    return null;
                }
                finally
                {
                    if (freeFrame != null)
                    {
                        freeFrame.Length = (int)(lastFrameStart - freeFrame.Offset);

                        if (!_canSeek)
                        {
                            // gotta finish filling the buffer!!
                            throw new InvalidOperationException("Free frames cannot be read properly from forward-only streams!");
                        }

                        // if _lastFree hasn't changed (we got a non-MPEG frame), clear it out
                        if (_lastFree == freeFrame)
                        {
                            _lastFree = null;
                        }
                    }
                }
            }
        }
예제 #11
0
 public abstract int DecodeFrame(MpegFrame frame, Span <float> ch0, Span <float> ch1);
예제 #12
0
 static internal bool GetCRC(MpegFrame frame, ref uint crc)
 {
     return LayerIIDecoderBase.GetCRC(frame, _rateTable, _allocLookupTable, false, ref crc);
 }
예제 #13
0
 static internal bool GetCRC(MpegFrame frame, ref uint crc)
 {
     var cnt = frame.GetSideDataSize();
     while (--cnt >= 0)
     {
         MpegFrame.UpdateCRC(frame.ReadBits(8), 8, ref crc);
     }
     return true;
 }
예제 #14
0
 static internal bool GetCRC(MpegFrame frame, ref uint crc)
 {
     return(LayerIIDecoderBase.GetCRC(frame, _rateTable, _allocLookupTable, false, ref crc));
 }
예제 #15
0
 static internal bool GetCRC(MpegFrame frame, ref uint crc)
 {
     return LayerIIDecoderBase.GetCRC(frame, SelectTable(frame), _allocLookupTable, true, ref crc);
 }
예제 #16
0
        protected static bool GetCRC(
            MpegFrame frame, int[] rateTable, int[][] allocLookupTable, bool readScfsiBits, ref uint crc)
        {
            // ugh...  we basically have to re-implement the allocation logic here.

            // keep up with how many active subbands we need to read selection info for
            var scfsiBits = 0;

            // only read as many subbands as we actually need; pay attention to the intensity stereo subbands
            var subbandCount = rateTable.Length;
            var jsbound      = subbandCount;

            if (frame.ChannelMode == MpegChannelMode.JointStereo)
            {
                jsbound = frame.ChannelModeExtension * 4 + 4;
            }

            // read the full stereo subbands
            var channels = frame.ChannelMode == MpegChannelMode.Mono ? 1 : 2;
            var sb       = 0;

            for (; sb < jsbound; sb++)
            {
                var bits = allocLookupTable[rateTable[sb]][0];
                for (int ch = 0; ch < channels; ch++)
                {
                    var alloc = frame.ReadBits(bits);
                    if (alloc > 0)
                    {
                        scfsiBits += 2;
                    }

                    MpegFrame.UpdateCRC(alloc, bits, ref crc);
                }
            }

            // read the intensity stereo subbands
            for (; sb < subbandCount; sb++)
            {
                var bits = allocLookupTable[rateTable[sb]][0];

                var alloc = frame.ReadBits(bits);
                if (alloc > 0)
                {
                    scfsiBits += channels * 2;
                }

                MpegFrame.UpdateCRC(alloc, bits, ref crc);
            }

            // finally, read the scalefac selection bits
            if (readScfsiBits)
            {
                while (scfsiBits >= 2)
                {
                    MpegFrame.UpdateCRC(frame.ReadBits(2), 2, ref crc);
                    scfsiBits -= 2;
                }
            }

            return(true);
        }
예제 #17
0
 protected abstract int[] GetRateTable(MpegFrame frame);
        internal MpegFrame NextFrame()
        {
            // if _current is null, we've returned the last frame already
            var frame = _current;
            if (frame != null)
            {
                if (_canSeek)
                {
                    frame.SaveBuffer();
                    DiscardThrough(frame.Offset + frame.FrameLength, false);
                }

                if (frame == _last && !_endFound)
                {
                    do
                    {
                        FindNextFrame();
                    } while (frame == _last && !_endFound);
                }

                _current = frame.Next;

                if (!_canSeek)
                {
                    // if we're in a forward-only stream, don't bother keeping the frames that have already been processed
                    lock (_frameLock)
                    {
                        var temp = _first;
                        _first = temp.Next;
                        temp.Next = null;
                    }
                }
            }
            return frame;
        }
예제 #19
0
 protected abstract void ReadScaleFactorSelection(MpegFrame frame, int[][] scfsi, int channels);