Esempio n. 1
0
        public static WavFileHeader openWavFile(string fileName, out Int16[] wavSampleData)
        {
            WavFileHeader hdr = new WavFileHeader();

            wavSampleData = new Int16[] { };
            byte[] wavData;

            try
            {
                wavData = File.ReadAllBytes(fileName);
                if (wavData.Length < 36)
                {
                    hdr.invalidHeaderMessage = "Error : Input file in incompatible format.";
                    return(hdr);
                }
            }
            catch (Exception ex)
            {
                hdr.invalidHeaderMessage = "Error : " + ex.Message;
                return(hdr);
            }

            return(openWavFile(wavData, out wavSampleData));
        }
Esempio n. 2
0
        public static WavFileHeader openWavFile(byte[] inputWavData, out Int16[] wavSampleData)
        {
            WavFileHeader hdr     = new WavFileHeader();
            List <byte>   wavData = inputWavData.ToList();

            wavSampleData = new Int16[] { };

            hdr.chunkID       = wavData.GetRange(0, 4).ToArray();                            // Should be 'RIFF'
            hdr.chunkSize     = BitConverter.ToUInt32(wavData.GetRange(4, 4).ToArray(), 0);
            hdr.waveStr       = wavData.GetRange(8, 4).ToArray();                            // Should be 'WAVE'
            hdr.sc1Id         = wavData.GetRange(12, 4).ToArray();                           // Should be 'fmt '
            hdr.sc1size       = BitConverter.ToUInt32(wavData.GetRange(16, 4).ToArray(), 0); // Should be at least 16
            hdr.audioFormat   = BitConverter.ToUInt16(wavData.GetRange(20, 2).ToArray(), 0); // Should be 1 for PCM
            hdr.chans         = BitConverter.ToUInt16(wavData.GetRange(22, 2).ToArray(), 0); // 1 for mono, 2 for stereo, etc
            hdr.sampleRate    = BitConverter.ToUInt32(wavData.GetRange(24, 4).ToArray(), 0);
            hdr.byteRate      = BitConverter.ToUInt32(wavData.GetRange(28, 4).ToArray(), 0);
            hdr.blockAlign    = BitConverter.ToUInt16(wavData.GetRange(32, 2).ToArray(), 0);
            hdr.bitsPerSample = BitConverter.ToUInt16(wavData.GetRange(34, 2).ToArray(), 0);

            //Validate header
            string chunkID = Encoding.UTF8.GetString(hdr.chunkID, 0, 4);
            string waveStr = Encoding.UTF8.GetString(hdr.waveStr, 0, 4);
            string sc1Id   = Encoding.UTF8.GetString(hdr.sc1Id, 0, 4);

            if (chunkID != "RIFF")
            {
                hdr.invalidHeaderMessage = "Error : Input file in unsupported format : \"RIFF\" block missing.";
            }
            else if (waveStr != "WAVE")
            {
                hdr.invalidHeaderMessage = "Error : Input file in unsupported format : \"WAVE\" block missing.";
            }
            else if (sc1Id != "fmt ")
            {
                hdr.invalidHeaderMessage = "Error : Input file in unsupported format : \"fmt \" block missing.";
            }
            else if (hdr.sc1size < 0x10 || hdr.audioFormat != 1)
            {
                hdr.invalidHeaderMessage = "Input file in unsupported format : file must be uncompressed PCM.";
            }
            else if (hdr.byteRate != hdr.sampleRate * hdr.chans * hdr.bitsPerSample / 8)
            {
                hdr.invalidHeaderMessage = "Byte rate in input file is set incorrectly.";
            }
            else if (hdr.blockAlign != hdr.bitsPerSample * hdr.chans / 8)
            {
                hdr.invalidHeaderMessage = "Block align in input file is set incorrectly.";
            }
            else if (hdr.bitsPerSample != 8 && hdr.bitsPerSample != 16)
            {
                hdr.invalidHeaderMessage = "Error : unsupported amount of bits per sample (8 or 16 are supported)";
            }
            else
            {
                hdr.validHeader = true;
            }

            if (!hdr.validHeader)
            {
                return(hdr);
            }

            if (hdr.chans != 1)
            {
                hdr.invalidHeaderMessage = "Input is multi-channel : Will automatically be converted to mono.";
            }

            //Validate data header
            UInt32 index = 0x24 + hdr.sc1size - 0x10;

            while (true)
            {
                try
                {
                    string subHeaderName = Encoding.UTF8.GetString(wavData.GetRange((int)index, 4).ToArray(), 0, 4);
                    UInt32 subHeaderSize = BitConverter.ToUInt32(wavData.GetRange((int)index + 4, 4).ToArray(), 0);
                    index += 8;

                    if (subHeaderName == "data")
                    {
                        hdr.dataIndex = index;
                        hdr.dataSize  = subHeaderSize;

                        List <Int16> buffer = new List <Int16>();
                        using (MemoryStream ms = new MemoryStream(wavData.GetRange((int)index, (int)subHeaderSize).ToArray()))
                            using (BinaryReader br = new BinaryReader(ms))
                            {
                                try
                                {
                                    while (true)
                                    {
                                        buffer.Add(br.ReadInt16());
                                    }
                                }
                                catch (EndOfStreamException) { }
                            }

                        wavSampleData = buffer.ToArray();
                        break;
                    }

                    index += subHeaderSize;
                }
                catch
                {
                    hdr.validHeader          = false;
                    hdr.invalidHeaderMessage = "End of file reached without finding a correct \"data\" chunk.";
                    return(hdr);
                }
            }

            //Everything is right. Return hdr.
            return(hdr);
        }
Esempio n. 3
0
        public static byte[] encodeBrr(WavFileHeader hdr, Int16[] samples, BrrEncoderOptions options)
        {
            List <byte> output = new List <byte>();

            byte   loopFlag    = 0x00;
            UInt16 loopStart   = 0;
            uint   newLoopsize = 0;

            if (options.loopAddress >= 0)
            {
                loopFlag  = 0x02; // 0x02 if loop flag is active.
                loopStart = Convert.ToUInt16(options.loopAddress);
            }

            // Optional truncation of input sample
            UInt32 samplesLength = hdr.dataSize / hdr.blockAlign; // FIXME comprobar qué es esto ¿no se puede utilizar samples.Length?

            // Adjust amplitude in function of amount of channels
            samples = adjustAmplitudeOfWavSamples(samples, samplesLength, hdr.chans, hdr.bitsPerSample, options);

            // Apply resampling if needed
            applyResampling(ref samples, ref samplesLength, ref newLoopsize, hdr.sampleRate, loopStart, options);

            // Apply trebble boost filter (gussian lowpass compensation) if requested by user
            if (options.trebleBoost)
            {
                samples = trebleBoostFilter(samples, samplesLength);
            }

            //Add zeroes at the beginning if the Amount of PCM samples isn't a multiple of 16
            int zeroesToAdd = samples.Length % 16;

            if (zeroesToAdd != 0)
            {
                samples = Enumerable.Repeat((Int16)0, zeroesToAdd).Concat(samples).ToArray();
            }

            //Begin the actual BRR encoding

            //Initialization needed if any of the first 16 samples isn't zero
            bool needsInitialBrrBlock = false;

            if (samples.Length >= 16)
            {
                for (int i = 0; i < 16 && !needsInitialBrrBlock; ++i)
                {
                    needsInitialBrrBlock |= samples[i] != 0;
                }
            }
            else
            {
                needsInitialBrrBlock = true;
            }

            if (needsInitialBrrBlock)
            {
                output = new List <byte>()
                {
                    loopFlag, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
                }
            }
            ;

            //Encode BRR

            //Set the truncate size
            if (options.truncateLen != 0 && output.Count > 0)
            {
                options.truncateLen -= 16;
            }

            if (options.truncateLen != 0 && (options.truncateLen != samplesLength))
            {
                samplesLength = options.truncateLen;
            }

            Int16 p1 = 0;
            Int16 p2 = 0;
            BrrEncoderStatistics statistics = new BrrEncoderStatistics();

            for (int n = 0; n < samplesLength; n += 16)
            {
                byte[] brrChunk = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

                //Encode BRR block, tell the encoder if we're at loop point (if loop is enabled), and if we're at end point
                bool isLoopPoint = options.fixLoopEn && (n == (samplesLength - newLoopsize));
                bool isEndPoint  = n == samplesLength - 16;

                Int16[] samplesToCheck = samples.Skip(n).ToArray();
                if (samplesToCheck.Length < 16)
                {
                    samplesToCheck = samplesToCheck.Concat(new Int16[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }).ToArray();
                }

                ADPCMBlockMash(samples.Skip(n).ToArray(), isLoopPoint, isEndPoint, options, statistics, ref p1, ref p2, ref brrChunk);

                //Set the loop flag if needed
                brrChunk[0] |= loopFlag;
                output.AddRange(brrChunk);
            }

            //HACKME recover this
            //    if(fix_loop_en)
            //    {
            //        unsigned int k = samples_length - (initial_block ? new_loopsize - 16 : new_loopsize);
            //        printf("Position of the loop within the BRR sample : %u samples = %u BRR blocks.\n", k, k/16);
            //    }

            //    for(int i=0; i<4; i++)
            //        if (FIRstats[i]>0) printf("Filter %u used on %u blocks.\n", i, FIRstats[i]);

            return(output.ToArray());
        }