コード例 #1
0
ファイル: Adpcm.cs プロジェクト: perivar/FindSimilarCore
        private static short AdpcmMsExpandNibble(ref adpcmMsChannel channel, byte nibble)
        {
            // Get a signed number out of the nibble. We need to retain the
            // original nibble value for when we access AdaptionTable[].
            sbyte signedNibble = (sbyte)nibble;

            if ((signedNibble & 0x8) == 0x8)
            {
                signedNibble -= 0x10;
            }

            // Calculate new sample
            int predictor = (channel.Sample1 * channel.Coeff1 +
                             channel.Sample2 * channel.Coeff2) / 256 +
                            signedNibble * channel.Delta;

            // Clamp result to 16-bit, -32768 - 32767
            predictor = Clamp(predictor, short.MinValue, short.MaxValue);

            // Shuffle samples, get new delta
            channel.Sample2 = channel.Sample1;
            channel.Sample1 = (short)predictor;

            channel.Delta = (short)((MSAdaptationTable[nibble] * channel.Delta) / 256);

            // Saturate the delta to a lower bound of 16
            if (channel.Delta < 16)
            {
                channel.Delta = 16;
            }
            return((short)predictor);
        }
コード例 #2
0
ファイル: Adpcm.cs プロジェクト: perivar/FindSimilarCore
        private static void DecodeAdpcmMs(Decoder decoder, BinaryReader reader, BinaryWriter writer)
        {
            // https://wiki.multimedia.cx/index.php/Microsoft_ADPCM
            // see also https://github.com/DeltaEngine/DeltaEngine/blob/master/Multimedia/OpenAL/Helpers/MsAdpcmConverter.cs

            DecoderState state = decoder.State;

            adpcmMsChannel[] channel        = new adpcmMsChannel[2];
            byte             blockPredictor = 0;

            // determine total number of samples in this block
            // the initial 2 samples from the block preamble are sent directly to the output.
            // therefore, deduct 2 from the samples per block to calculate the remaining samples
            int totalSamples = (state.SamplesPerBlock - 2) * decoder.AudioFormat.Channels;

            if (totalSamples < 2)
            {
                return;
            }

            bool isStereo = decoder.AudioFormat.Channels == 2 ? true : false;

            //  read predicates and deltas
            blockPredictor    = reader.ReadByte();
            blockPredictor    = (byte)Clamp(blockPredictor, 0, 6);
            channel[0].Coeff1 = (short)MSAdaptationCoeff1[blockPredictor];
            channel[0].Coeff2 = (short)MSAdaptationCoeff2[blockPredictor];

            if (isStereo)
            {
                blockPredictor    = reader.ReadByte();
                blockPredictor    = (byte)Clamp(blockPredictor, 0, 6);
                channel[1].Coeff1 = (short)MSAdaptationCoeff1[blockPredictor];
                channel[1].Coeff2 = (short)MSAdaptationCoeff2[blockPredictor];
            }
            channel[0].Delta = reader.ReadInt16();
            if (isStereo)
            {
                channel[1].Delta = reader.ReadInt16();
            }

            //  read first samples and write them to result
            channel[0].Sample1 = reader.ReadInt16();
            if (isStereo)
            {
                channel[1].Sample1 = reader.ReadInt16();
            }

            channel[0].Sample2 = reader.ReadInt16();
            if (isStereo)
            {
                channel[1].Sample2 = reader.ReadInt16();
            }

            // output the samples
            if (isStereo)
            {
                writer.Write(channel[0].Sample2);
                writer.Write(channel[1].Sample2);
                writer.Write(channel[0].Sample1);
                writer.Write(channel[1].Sample1);
            }
            else
            {
                writer.Write(channel[0].Sample2);
                writer.Write(channel[0].Sample1);
            }

            // decode the rest of the samples
            for (int index = 0; index < totalSamples; index += 2)
            {
                try
                {
                    byte nibble = reader.ReadByte();
                    writer.Write(AdpcmMsExpandNibble(ref channel[0], (byte)(nibble >> 4)));
                    writer.Write(AdpcmMsExpandNibble(ref channel[isStereo ? 1 : 0], (byte)(nibble & 0x0f)));
                }
                catch (System.IO.EndOfStreamException)
                {
                    Log.Verbose("DecodeAdpcmMs: Reached end of stream - returning.");
                    break;
                }
            }
        }