⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ima_adpcm.cpp

📁 Tixys source code, include G.711, G.726, IMA-ADPCM etc.
💻 CPP
字号:
/**
@file

@brief Implementation of the IMA ADPCM audio coding algorithm

For latest source code see http://www.tixy.clara.net/source/

Copyright (C) 2005 J.D.Medhurst (a.k.a. Tixy)

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "common.h"
#include "IMA_ADPCM.h"


static const uint16 IMA_ADPCMStepTable[89] =
	{
		7,	  8,	9,	 10,   11,	 12,   13,	 14,
	   16,	 17,   19,	 21,   23,	 25,   28,	 31,
	   34,	 37,   41,	 45,   50,	 55,   60,	 66,
	   73,	 80,   88,	 97,  107,	118,  130,	143,
	  157,	173,  190,	209,  230,	253,  279,	307,
	  337,	371,  408,	449,  494,	544,  598,	658,
	  724,	796,  876,	963, 1060, 1166, 1282, 1411,
	 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024,
	 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484,
	 7132, 7845, 8630, 9493,10442,11487,12635,13899,
	15289,16818,18500,20350,22385,24623,27086,29794,
	32767
	};


static const int IMA_ADPCMIndexTable[8] =
	{
	-1, -1, -1, -1, 2, 4, 6, 8,
	};


EXPORT void IMA_ADPCM::EncodeInit(int16 sample1,int16 sample2)
	{
	PredictedValue = sample1;
	int delta = sample2-sample1;
	if(delta<0)
		delta = - delta;
	if(delta>32767)
		delta = 32767;
	int stepIndex = 0;
	while(IMA_ADPCMStepTable[stepIndex]<(uint)delta)
		stepIndex++;
	StepIndex = stepIndex;
	}


EXPORT uint IMA_ADPCM::Encode(int16 pcm16)
	{
	int predicedValue = PredictedValue;
	int stepIndex = StepIndex;

	int delta = pcm16-predicedValue;
	uint value;
	if(delta>=0)
		value = 0;
	else
		{
		value = 8;
		delta = -delta;
		}

	int step = IMA_ADPCMStepTable[stepIndex];
	int diff = step>>3;
	if(delta>step)
		{
		value |= 4;
		delta -= step;
		diff += step;
		}
	step >>= 1;
	if(delta>step)
		{
		value |= 2;
		delta -= step;
		diff += step;
		}
	step >>= 1;
	if(delta>step)
		{
		value |= 1;
		diff += step;
		}

	if(value&8)
		predicedValue -= diff;
	else
		predicedValue += diff;
	if(predicedValue<-0x8000)
		predicedValue = -0x8000;
	else if(predicedValue>0x7fff)
		predicedValue = 0x7fff;
	PredictedValue = predicedValue;

	stepIndex += IMA_ADPCMIndexTable[value&7];
	if(stepIndex<0)
		stepIndex = 0;
	else if(stepIndex>88)
		stepIndex = 88;
	StepIndex = stepIndex;

	return value;
	}


EXPORT int IMA_ADPCM::Decode(uint adpcm)
	{
	int stepIndex = StepIndex;
	int step = IMA_ADPCMStepTable[stepIndex];

	stepIndex += IMA_ADPCMIndexTable[adpcm&7];
	if(stepIndex<0)
		stepIndex = 0;
	else if(stepIndex>88)
		stepIndex = 88;
	StepIndex = stepIndex;

	int diff = step>>3;
	if(adpcm&4)
		diff += step;
	if(adpcm&2)
		diff += step>>1;
	if(adpcm&1)
		diff += step>>2;

	int predicedValue = PredictedValue;
	if(adpcm&8)
		predicedValue -= diff;
	else
		predicedValue += diff;
	if(predicedValue<-0x8000)
		predicedValue = -0x8000;
	else if(predicedValue>0x7fff)
		predicedValue = 0x7fff;
	PredictedValue = predicedValue;

	return predicedValue;
	}


EXPORT uint IMA_ADPCM::Encode(uint8* dst, int dstOffset, const int16* src, uint srcSize)
	{
	// use given bit offset
	dst += dstOffset>>3;
	uint bitOffset = dstOffset&4;

	// make sure srcSize represents a whole number of samples
	srcSize &= ~1;

	// calculate end of input buffer
	const int16* end = (const int16*)((const uint8*)src+srcSize);

	while(src<end)
		{
		// encode a pcm value from input buffer
		uint adpcm = Encode(*src++);

		// pick which nibble to write adpcm value to...
		if(!bitOffset)
			*dst = adpcm;		// write adpcm value to low nibble
		else
			{
			uint b = *dst;		// get byte from ouput
			b &= 0x0f;			// clear bits of high nibble
			b |= adpcm<<4;		// or adpcm value into the high nibble
			*dst++ = (uint8)b;	// write value back to output and move on to next byte
			}

		// toggle which nibble in byte to write to next
		bitOffset ^= 4; 		
		}

	// return number bits written to dst
	return srcSize*2;
	}


EXPORT uint IMA_ADPCM::Decode(int16* dst, const uint8* src, int srcOffset, uint srcSize)
	{
	// use given bit offset
	src += srcOffset>>3;

	// calculate pointers to iterate output buffer
	int16* out = dst;
	int16* end = out+(srcSize>>2);

	while(out<end)
		{
		// get byte from src
		uint adpcm = *src; 

		// pick which nibble holds a adpcm value...
		if(srcOffset&4)
			{
			adpcm >>= 4;  // use high nibble of byte
			++src;		  // move on a byte for next sample
			}

		*out++ = Decode(adpcm);  // decode value and store it

		// toggle which nibble in byte to write to next
		srcOffset ^= 4;
		}

	// return number of bytes written to dst
	return (uint)out-(uint)dst;
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -