ADPCM-PCM 的压缩

来源:互联网 发布:下载天猫淘宝网 编辑:程序博客网 时间:2024/05/22 02:26

这里写图片描述
转化后输出的数据分配的空间要算好,上面的byte2的空间在下面转换成NSdata的时候分配的空间多了一倍要进行修改

import “ADPCM.h”

define RATE 8000

define SIZE AFMT_S16_LE

define CHANNELS 2

define FRAME_SIZE 1000

static int indexTable[16] = {
-1, -1, -1, -1, 2, 4, 6, 8,
-1, -1, -1, -1, 2, 4, 6, 8,
};

static int stepsizeTable[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
};

@implementation ADPCM

pragma mark 编码

int adpcm_coder(short *indata, unsigned char *outdata, int len)
{
int val; /* Current input sample value */
unsigned int delta; /* Current adpcm output value */
int diff; /* Difference between val and valprev */
int step; /* Stepsize */
int valpred; /* Predicted output value */
// Current change to valpred
int index ; /* Current step change index */
unsigned int outputbuffer = 0;/* place to keep previous 4-bit value */
int count = 0; /* the number of bytes encoded */
//

// valpred = state->valprev;
// index = (int)state->index;
step = stepsizeTable[index];

valpred = *indata;index = 0;*outdata = (unsigned char)(len/2+4);*(++outdata) = (unsigned char)((len/2+4)>>8);*(++outdata) = (unsigned char)((len/2+4)>>16);*(++outdata) = (unsigned char)((len/2+4)>>24);*(++outdata) = 0x11;*(++outdata) = 0x00;

// *indata = 0xf00f;
*(++outdata)=(unsigned char)(*indata);
// outdata++;
// outdata++;
*(++outdata)=(*indata)>>8;
*(++outdata)=0;
*(++outdata)=0;
// *(++outdata)=3;
// *(++outdata)=4;

while (len > 0 ) {    /* Step 1 - compute difference with previous value */    val = *(++indata);    diff = val - valpred;    if(diff < 0)    {        delta = 8;        diff = (-diff);    }    else    {        delta = 0;    }    /* Step 2 - Divide and clamp */    /* Note:     ** This code *approximately* computes:     **    delta = diff*4/step;     **    vpdiff = (delta+0.5)*step/4;     ** but in shift step bits are dropped. The net result of this is     ** that even if you have fast mul/div hardware you cannot put it to     ** good use since the fixup would be too expensive.     */

// vpdiff = (step >> 3);

    if ( diff >= stepsizeTable[index] ) {        delta = delta|4;        diff -= stepsizeTable[index] - step;

// vpdiff += step;
}
// stepsizeTable[index] >>= 1;
if ( diff >= (stepsizeTable[index] >> 1) ) {
delta = delta|2;
diff -= stepsizeTable[index] - (stepsizeTable[index] >> 1);
// vpdiff += step;
}
// step >>= 2;
if ( diff >= (stepsizeTable[index] >> 2) ) {
delta = delta| 1;
// vpdiff += step;
}

    /* Phil Frisbie combined steps 3 and 4 */    /* Step 3 - Update previous value */    /* Step 4 - Clamp previous value to 16 bits */    diff = 0;    if (delta&4)diff = diff +stepsizeTable[index];    if (delta&2)diff = diff + (stepsizeTable[index] >> 1);    if (delta&1)diff = diff + (stepsizeTable[index] >> 2);    diff = diff + (stepsizeTable[index] >> 3);    if ( (delta&8) !=0  )    {        diff = -diff;

// valpred -= vpdiff;
// if ( valpred < -32768 )
// valpred = -32768;
}
valpred = diff + valpred ;
if ( valpred < -32768 ){
valpred = -32768;
}else{

    if ( valpred > 32767 )    valpred = 32767;    }    /* Step 5 - Assemble value, update index and step values */    index += indexTable[delta];    if ( index < 0 ) index = 0;    else if ( index > 88 ) index = 88;

// step = stepsizeTable[index];

    /* Step 6 - Output value */    outputbuffer = (delta );    /* Step 1 - compute difference with previous value */    /* Step 1 - compute difference with previous value */    val = *(++indata);    diff = val - valpred;    if(diff < 0)    {        delta = 8;        diff = (-diff);    }    else    {        delta = 0;    }    /* Step 2 - Divide and clamp */    /* Note:     ** This code *approximately* computes:     **    delta = diff*4/step;     **    vpdiff = (delta+0.5)*step/4;     ** but in shift step bits are dropped. The net result of this is     ** that even if you have fast mul/div hardware you cannot put it to     ** good use since the fixup would be too expensive.     */    //        vpdiff = (step >> 3);    if ( diff >= stepsizeTable[index] ) {        delta = delta|4;        diff -= stepsizeTable[index] - step;        //            vpdiff += step;    }    //        stepsizeTable[index] >>= 1;    if ( diff >= (stepsizeTable[index] >> 1) ) {        delta = delta|2;        diff -= stepsizeTable[index] - (stepsizeTable[index] >> 1);        //            vpdiff += step;    }    //        step >>= 2;    if ( diff >= (stepsizeTable[index] >> 2) ) {        delta  = delta| 1;        //            vpdiff += step;    }    /* Phil Frisbie combined steps 3 and 4 */    /* Step 3 - Update previous value */    /* Step 4 - Clamp previous value to 16 bits */    diff = 0;    if (delta&4)diff = diff +stepsizeTable[index];    if (delta&2)diff = diff + (stepsizeTable[index] >> 1);    if (delta&1)diff = diff + (stepsizeTable[index] >> 2);    diff = diff + (stepsizeTable[index] >> 3);    if ( (delta&8) !=0  )    {        diff = -diff;        //            valpred -= vpdiff;        //            if ( valpred < -32768 )        //                valpred = -32768;    }    valpred = diff + valpred ;    if ( valpred < -32768 ){        valpred = -32768;    }else{        if ( valpred > 32767 )            valpred = 32767;    }    /* Step 5 - Assemble value, update index and step values */    index += indexTable[delta];    if ( index < 0 ) index = 0;    else if ( index > 88 ) index = 88;    /* Step 6 - Output value */    *(++outdata) = (unsigned char)((delta<<4 )| outputbuffer);    count++;    len -= 2;}

// valpred = (short)valpred;
// index = (char)index;

return count;

}

pragma mark adpcm解码

int adpcm_decoder(unsigned char *indata, short *outdata, int len)
{
unsigned int delta; /* Current adpcm output value */
// int step; /* Stepsize */
int valpred; /* Predicted value */
int vpdiff; /* Current change to valpred */
int index; /* Current step change index */
unsigned char inputbuffer = 0;/* place to keep next 4-bit value */
int count = 0;

//file head*outdata = (*indata)|(*(++indata)<<8);*(++outdata) = (*(++indata))|(*(++indata)<<8);*(++outdata) =(*(++indata))|(*(++indata)<<8);//first sample*(++outdata) = (*(++indata))|(*(++indata)<<8);index=*(++indata);index=*(++indata);valpred = *outdata;index = 0;

// step = stepsizeTable[index];

/* Loop unrolling by Phil Frisbie *//* This assumes there are ALWAYS an even number of samples */while ( len-- > 0 ) {    /* Step 1 - get the delta value */    inputbuffer = *(++indata);    delta = (inputbuffer & 0x0f);    /* Step 2 - Find new index value (for later) */

// index += indexTable[delta];
// if ( index < 0 ) index = 0;
// else if ( index > 88 ) index = 88;

    /* Phil Frisbie combined steps 3, 4, and 5 */    /* Step 3 - Separate sign and magnitude */    /* Step 4 - Compute difference and new predicted value */    /* Step 5 - clamp output value */    /*     ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment     ** in adpcm_coder.     */    vpdiff = 0;    if ( (delta & 4) != 0 ) vpdiff += stepsizeTable[index];    if ( (delta & 2) != 0 ) vpdiff += stepsizeTable[index]>>1;    if ( (delta & 1) != 0 ) vpdiff += stepsizeTable[index]>>2;    vpdiff = vpdiff + (stepsizeTable[index]>>3);    if ( (delta & 8) != 0 )    {        valpred -= vpdiff;                }    if ( valpred < -32768 ){        valpred = -32768;    }else    {

// valpred += vpdiff;
if ( valpred > 32767 )
valpred = 32767;
}

    /* Step 6 - Update step value */

// step = stepsizeTable[index];

    /* Step 7 - Output value */    *(++outdata) = (short)valpred;            index += indexTable[delta];            if ( index < 0 ) index = 0;            else if ( index > 88 ) index = 88;    /* Step 1 - get the delta value */    delta = inputbuffer & 0xf0;    /* Step 2 - Find new index value (for later) */    vpdiff = 0;    if ( (delta & 4) != 0 ) vpdiff += stepsizeTable[index];    if ( (delta & 2) != 0 ) vpdiff += stepsizeTable[index]>>1;    if ( (delta & 1) != 0 ) vpdiff += stepsizeTable[index]>>2;    vpdiff = vpdiff + (stepsizeTable[index]>>3);    if ( (delta & 8) != 0 )    {        valpred -= vpdiff;    }    if ( valpred < -32768 ){        valpred = -32768;    }else    {        //            valpred += vpdiff;        if ( valpred > 32767 )            valpred = 32767;    }    /* Step 6 - Update step value */    //        step = stepsizeTable[index];    /* Step 7 - Output value */

// *(++outdata) = (short)valpred;

    index += indexTable[delta];    if ( index < 0 ) index = 0;    else if ( index > 88 ) index = 88;        /* Step 7 - Output value */    *(++outdata) = (short)valpred;    count += 2;}

// state->valprev = (short)valpred;
// state->index = (char)index;

return count;

}

pragma mark 编码调用方法

  • (void)adpcmCodeWithFilePath:(NSString )inPathString saveFilePath:(NSString )outPathString{

    int fd,mid;
    // int arg;
    // int status;

    // for encode use
    unsigned char inbuf[FRAME_SIZE*4]; // 2 channels , 16bit data , so *4
    short inenc[FRAME_SIZE]; // 1 channel, 16bit data, but short type, so *1
    unsigned char encbuf[FRAME_SIZE/2];

    // for decode use
    // short decbuf[FRAME_SIZE]; // decode restore inenc
    // unsigned char outbuf[FRAME_SIZE*4]; // restore inbuf

    // adpcm
    struct adpcm_state enc_state;

    //获得char路径
    char *inPath = [self getCharPath:inPathString];
    char *outPath = [self getCharPath:outPathString];

    //打开文件

    fd = open(inPath, O_RDWR);

    if (fd < 0)
    {
    perror(“Open /dev/dsp fail”);
    exit(1);
    }

    mid = open(outPath, O_RDWR);

    // encode
    enc_state.valprev = 0;
    enc_state.index = 0;

    while(1)
    {
    // encode
    printf(“encode\n”);
    read(fd, inbuf, sizeof(inbuf));

    for(int i = 0;i < FRAME_SIZE * 4;i += 4){    inenc[i/4] = inbuf[i] + inbuf[i+1]*256;}

// adpcm_coder(inenc, encbuf, FRAME_SIZE, &enc_state);

    // decode

// printf(“decode\n”);
// adpcm_decoder(encbuf, decbuf, FRAME_SIZE/2, &dec_state);
//
// for(int i=0;i < FRAME_SIZE;i++){
// outbuf[i*4] = decbuf[i] & 0xff;
// outbuf[i*4+1] = decbuf[i] >> 8;
// outbuf[i*4+2] = decbuf[i] & 0xff;
// outbuf[i*4+3] = decbuf[i] >> 8;
// }

    write(mid, inenc, sizeof(inenc));}

}

pragma mark 把NSString转变成char

  • (char )getCharPath:(NSString )path {

    NSUInteger pathLenth = [path length];

    char newPath = (char )malloc(sizeof(char)*pathLenth + 1);

    [path getCString:newPath maxLength:pathLenth + 1 encoding:NSUTF8StringEncoding];

    return newPath;
    }

1 0
原创粉丝点击