Ejemplo n.º 1
0
        public static int GetChannels(byte[] identifier, out ChannelAssignment channelAssignment)
        {
            #region channels

            int val = identifier[3] >> 4; //cc: unsigned
            int channels;
            if ((val & 8) != 0)
            {
                channels = 2;
                if ((val & 7) > 2 || (val & 7) < 0)
                {
                    throw new InvalidOperationException("Invalid ChannelAssignment");
                    //return false;
                }
                channelAssignment = (ChannelAssignment)((val & 7) + 1);
            }
            else
            {
                channels          = val + 1;
                channelAssignment = ChannelAssignment.Independent;
            }
            return(channels);

            #endregion channels
        }
Ejemplo n.º 2
0
 public static int GetChannels(Node node, out ChannelAssignment channelAssignment)
 {
     if (node == null)
     {
         throw new ArgumentNullException(nameof(node));
     }
     return(GetChannels(node.Identifier, out channelAssignment));
 }
Ejemplo n.º 3
0
        private unsafe int ReadSubFrames()
        {
            List <FlacSubFrameBase> subFrames = new List <FlacSubFrameBase>();

            //alocateOutput
            var data = AllocOuputMemory();

            _data = data;

            byte[] buffer = new byte[0x20000];
            if ((_streamInfo.MaxFrameSize * Header.Channels * Header.BitsPerSample * 2 >> 3) > buffer.Length)
            {
                buffer = new byte[(_streamInfo.MaxFrameSize * Header.Channels * Header.BitsPerSample * 2 >> 3) - FlacConstant.FrameHeaderSize];
            }

            int read = _stream.Read(buffer, 0, (int)Math.Min(buffer.Length, _stream.Length - _stream.Position));

            fixed(byte *ptrBuffer = buffer)
            {
                FlacBitReader     reader            = new FlacBitReader(ptrBuffer, 0);
                ChannelAssignment channelAssignment = Header.ChannelAssignment;

                for (int c = 0; c < Header.Channels; c++)
                {
                    int bps = Header.BitsPerSample;
                    if (Header.ChannelAssignment == ChannelAssignment.MidSide || Header.ChannelAssignment == ChannelAssignment.LeftSide)
                    {
                        bps += c;
                    }
                    else if (Header.ChannelAssignment == ChannelAssignment.RightSide)
                    {
                        bps += 1 - c;
                    }

                    var subframe = FlacSubFrameBase.GetSubFrame(reader, data[c], Header, bps);

                    subFrames.Add(subframe);
                }

                reader.Flush();
                CRC16 = (ushort)reader.ReadBits(16);

                _stream.Position -= read - reader.Position;

                SamplesToBytes(_data);

                return(reader.Position);
            }
        }
Ejemplo n.º 4
0
        internal void ParseHeader(Stream stream, StreamInfo streamInfo)
        {
            ushort buffer;
            int b; //to check EOS

            int additionalBlockSize = 0; //number of additional bytes at the end of the header that represent its length

            int sampleRateBytes = 0; //number of additional bytes at the end of the header that store the sample rate
            int sampleRateMultiplicator = 1; //scale of the stored sample rate

            buffer = Org.Nflac.Flac.Util.StreamReader.ReadUShort(stream);

            byte[] rawHeader = new byte[16];
            byte headerLen = 2;

            rawHeader[0] = (byte)(buffer >> 8);
            rawHeader[1] = (byte)(buffer & 0xff);

            if ((buffer & 0xfff8) != 0xfff8)
            {
                throw new LostSynchronizationException();
                //TODO: desync
            }
            else
            {
                //Console.WriteLine("SYNC: " + (stream.Position-2));
            }

            if ((buffer & 0x4) != 0)
            {
                throw new MalformedFileException("Reserved bit at the header");
            }

            variableLength = (buffer & 0x1) == 0x1;

            byte size;

            buffer = Org.Nflac.Flac.Util.StreamReader.ReadUShort(stream);

            rawHeader[headerLen++] = (byte)(buffer >> 8);
            rawHeader[headerLen++] = (byte)(buffer & 0xff);

            size = (byte)((buffer & 0xF000) >> 12); //higher 4 bits

            if (size == 0x0)
            {
                //reserved block-size
                throw new MalformedFileException("Reserved blocksize detected");
            }
            else if (size == 0x1)
            {
                blocksize = 192;
            }
            else if ((size > 0x1) && (size < 0x6))
            {
                blocksize = (ulong)(576 << (size - 2));
            }
            else if (size == 0x6)
            {
                additionalBlockSize = 1; //get additional byte from the end of the header
            }
            else if (size == 0x7)
            {
                additionalBlockSize = 2; //get 2 bytes from the end of the header
            }
            else if ((size > 0x7) && (size < 0x11))
            {
                blocksize = (ulong)(256 << (size - 8));
            }
            else
            {
                //TODO: handle reserved blocksize value
                throw new MalformedFileException("Reserved blocksize value detected");
            }

            byte rateCoded;

            rateCoded = (byte)((buffer & 0x0F00) >> 8); //next 4 bits

            switch (rateCoded)
            {
                case 0:
                    //get from STREAMINFO
                    break;
                case 1:
                    sampleRate = 88200;
                    break;
                case 2:
                    sampleRate = 176400;
                    break;
                case 3:
                    sampleRate = 192000;
                    break;
                case 4:
                    sampleRate = 8000;
                    break;
                case 5:
                    sampleRate = 16000;
                    break;
                case 6:
                    sampleRate = 22050;
                    break;
                case 7:
                    sampleRate = 24000;
                    break;
                case 8:
                    sampleRate = 32000;
                    break;
                case 9:
                    sampleRate = 44100;
                    break;
                case 10:
                    sampleRate = 48000;
                    break;
                case 11:
                    sampleRate = 96000;
                    break;
                case 12:
                    sampleRate = 0;
                    sampleRateBytes = 1;
                    sampleRateMultiplicator = 1000;
                    break;
                case 13:
                    sampleRate = 0;
                    sampleRateBytes = 2;
                    sampleRateMultiplicator = 1;
                    break;
                case 14:
                    sampleRate = 0;
                    sampleRateBytes = 2;
                    sampleRateMultiplicator = 10;
                    break;
                case 15:
                    throw new MalformedFileException("Reserved sample rate value");
                //handle reserved sample rate value
            }

            byte channelSetupCoded;

            channelSetupCoded = (byte)((buffer & 0x00F0) >> 4); //next 4 bits

            if (channelSetupCoded < 8)
            {
                if ((channelSetupCoded == 6) || (channelSetupCoded == 7))
                {
                    //some specific code for 7- and 8- channel music might be needed (those do not have appropriate channel assignment in the standard)
                }

                channels = (byte)(channelSetupCoded + 1);
                channelSetup = (ChannelAssignment)channelSetupCoded;
            }
            else if ((channelSetupCoded > 7) && (channelSetupCoded < 11))
            {
                //stereo
                channels = 2;
                channelSetup = (ChannelAssignment)channelSetupCoded;
            }
            else
            {
                throw new MalformedFileException("Reserved channel assignment used");
                //TODO: handle reserved channel assignment values
            }

            byte sampleSizeCoded;

            sampleSizeCoded = (byte)((buffer & 0x000E) >> 1); //next 3 bits

            switch (sampleSizeCoded)
            {
                case 0:
                    //get from STREAMINFO
                    break;
                case 1:
                    sampleSize = 8;
                    break;
                case 2:
                    sampleSize = 12;
                    break;
                case 3:
                    throw new MalformedFileException("Reserved sample size");
                case 4:
                    sampleSize = 16;
                    break;
                case 5:
                    sampleSize = 20;
                    break;
                case 6:
                    sampleSize = 24;
                    break;
                case 7:
                    //reserved value 2 handling
                    throw new MalformedFileException("Reserved sample size detected");

            }

            byte mandatoryField2;

            mandatoryField2 = (byte)(buffer & 0x0001); //last 1 bit

            if (mandatoryField2 != 0)
            {
                //TODO: handle mandatory value 2 violation
                throw new MalformedFileException("Mandatory value violated");

            }

            //handle UTF-8-like number
            frameNumber = ReadUTF8Number(stream, rawHeader, ref headerLen);

            //handle additional bytes for blocksize
            for (int i = 0; i < additionalBlockSize; i++)
            {
                blocksize = (ulong)(blocksize << 8);
                buffer = (ushort)stream.ReadByte();
                rawHeader[headerLen++] = (byte)buffer;
                blocksize |= buffer;
            }

            if (!variableLength)
            {
                if (frameNumber * streamInfo.MaximumBlockSize + blocksize > streamInfo.TotalSamples)
                {
                    blocksize = (streamInfo.TotalSamples - frameNumber * streamInfo.MaximumBlockSize);
                }

                /* f*****g ugly hack, but spec gives no better way to detect the last frame */
                if (blocksize != streamInfo.MaximumBlockSize)
                {
                    firstSampleNumber = frameNumber * streamInfo.MaximumBlockSize;
                }
                else
                {
                    firstSampleNumber = frameNumber * blocksize;
                }

                lastSampleNumber = firstSampleNumber + blocksize - 1;
            }
            else
            {
                firstSampleNumber = frameNumber;
                lastSampleNumber = firstSampleNumber + blocksize - 1;
            }

            if (frameNumber == 32)
            {
                //debug breakpoint
            }

            //handle additional sample rate

            for (int i = 0; i < sampleRateBytes; i++)
            {
                sampleRate = (ulong)(sampleRate << 8);

                b = stream.ReadByte();

                if (b == -1)
                {
                    throw new UnexpectedEndOfStreamException();
                }

                buffer = (ushort)b;
                rawHeader[headerLen++] = (byte)buffer;
                sampleRate |= buffer;
            }

            sampleRate *= (ulong)sampleRateMultiplicator;

            b = stream.ReadByte();

            if (b == -1)
            {
                throw new UnexpectedEndOfStreamException();
            }

            headerCRC = (byte)b;

            headerVal = new byte[headerLen];

            for (int i = 0; i < headerLen; i++)
            {
                headerVal[i] = rawHeader[i];
            }

            if (headerCRC != CRC8.Instance.Checksum(headerVal))
            {
                //CRC-8 failed
                //Console.WriteLine(frameNumber + " CRC-8 failed");
                throw new MalformedFileException("Frame header checksum validation failed");
            }
            else
            {
                //Console.WriteLine(frameNumber + " CRC-8 passed");
            }
        }