Ejemplo n.º 1
0
        static int AdpcmImaWavExpandNibble(ref ImaState channel, int nibble)
        {
            int diff = stepTable[channel.stepIndex] >> 3;

            if ((nibble & 0x04) != 0)
            {
                diff += stepTable[channel.stepIndex];
            }
            if ((nibble & 0x02) != 0)
            {
                diff += stepTable[channel.stepIndex] >> 1;
            }
            if ((nibble & 0x01) != 0)
            {
                diff += stepTable[channel.stepIndex] >> 2;
            }
            if ((nibble & 0x08) != 0)
            {
                channel.predictor -= diff;
            }
            else
            {
                channel.predictor += diff;
            }

            if (channel.predictor < -32768)
            {
                channel.predictor = -32768;
            }
            else if (channel.predictor > 32767)
            {
                channel.predictor = 32767;
            }

            channel.stepIndex += indexTable[nibble];

            if (channel.stepIndex < 0)
            {
                channel.stepIndex = 0;
            }
            else if (channel.stepIndex > 88)
            {
                channel.stepIndex = 88;
            }

            return(channel.predictor);
        }
Ejemplo n.º 2
0
        // Convert buffer containing IMA/ADPCM wav data to a 16-bit signed PCM buffer
        internal static byte[] ConvertIma4ToPcm(byte[] buffer, int offset, int count, int channels, int blockAlignment)
        {
            ImaState channel0 = new ImaState();
            ImaState channel1 = new ImaState();

            int sampleCountFullBlock = ((blockAlignment / channels) - 4) / 4 * 8 + 1;
            int sampleCountLastBlock = 0;

            if ((count % blockAlignment) > 0)
            {
                sampleCountLastBlock = (((count % blockAlignment) / channels) - 4) / 4 * 8 + 1;
            }
            int sampleCount  = ((count / blockAlignment) * sampleCountFullBlock) + sampleCountLastBlock;
            var samples      = new byte[sampleCount * sizeof(short) * channels];
            int sampleOffset = 0;

            while (count > 0)
            {
                int blockSize = blockAlignment;
                if (count < blockSize)
                {
                    blockSize = count;
                }
                count -= blockAlignment;

                channel0.predictor  = buffer[offset++];
                channel0.predictor |= buffer[offset++] << 8;
                if ((channel0.predictor & 0x8000) != 0)
                {
                    channel0.predictor -= 0x10000;
                }
                channel0.stepIndex = buffer[offset++];
                if (channel0.stepIndex > 88)
                {
                    channel0.stepIndex = 88;
                }
                offset++;
                int index = sampleOffset * 2;
                samples[index]     = (byte)channel0.predictor;
                samples[index + 1] = (byte)(channel0.predictor >> 8);
                ++sampleOffset;

                if (channels == 2)
                {
                    channel1.predictor  = buffer[offset++];
                    channel1.predictor |= buffer[offset++] << 8;
                    if ((channel1.predictor & 0x8000) != 0)
                    {
                        channel1.predictor -= 0x10000;
                    }
                    channel1.stepIndex = buffer[offset++];
                    if (channel1.stepIndex > 88)
                    {
                        channel1.stepIndex = 88;
                    }
                    offset++;
                    index              = sampleOffset * 2;
                    samples[index]     = (byte)channel1.predictor;
                    samples[index + 1] = (byte)(channel1.predictor >> 8);
                    ++sampleOffset;
                }

                if (channels == 2)
                {
                    for (int nibbles = 2 * (blockSize - 8); nibbles > 0; nibbles -= 16)
                    {
                        for (int i = 0; i < 4; i++)
                        {
                            index = (sampleOffset + i * 4) * 2;
                            int sample = AdpcmImaWavExpandNibble(ref channel0, buffer[offset + i] & 0x0f);
                            samples[index]     = (byte)sample;
                            samples[index + 1] = (byte)(sample >> 8);

                            index              = (sampleOffset + i * 4 + 2) * 2;
                            sample             = AdpcmImaWavExpandNibble(ref channel0, buffer[offset + i] >> 4);
                            samples[index]     = (byte)sample;
                            samples[index + 1] = (byte)(sample >> 8);
                        }
                        offset += 4;

                        for (int i = 0; i < 4; i++)
                        {
                            index = (sampleOffset + i * 4 + 1) * 2;
                            int sample = AdpcmImaWavExpandNibble(ref channel1, buffer[offset + i] & 0x0f);
                            samples[index]     = (byte)sample;
                            samples[index + 1] = (byte)(sample >> 8);

                            index              = (sampleOffset + i * 4 + 3) * 2;
                            sample             = AdpcmImaWavExpandNibble(ref channel1, buffer[offset + i] >> 4);
                            samples[index]     = (byte)sample;
                            samples[index + 1] = (byte)(sample >> 8);
                        }
                        offset       += 4;
                        sampleOffset += 16;
                    }
                }
                else
                {
                    for (int nibbles = 2 * (blockSize - 4); nibbles > 0; nibbles -= 2)
                    {
                        index = (sampleOffset * 2);
                        int b      = buffer[offset];
                        int sample = AdpcmImaWavExpandNibble(ref channel0, b & 0x0f);
                        samples[index]     = (byte)sample;
                        samples[index + 1] = (byte)(sample >> 8);
                        index             += 2;
                        sample             = AdpcmImaWavExpandNibble(ref channel0, b >> 4);
                        samples[index]     = (byte)sample;
                        samples[index + 1] = (byte)(sample >> 8);

                        sampleOffset += 2;
                        ++offset;
                    }
                }
            }

            return(samples);
        }