📄 ima_adpcm.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 + -