Chinaunix首页 | 论坛 | 博客
  • 博客访问: 534818
  • 博文数量: 86
  • 博客积分: 1076
  • 博客等级: 准尉
  • 技术积分: 1018
  • 用 户 组: 普通用户
  • 注册时间: 2011-11-02 19:15
文章分类

全部博文(86)

文章存档

2013年(15)

2012年(69)

2011年(2)

分类: LINUX

2012-05-24 12:13:17

     ADPCM(Adaptive Differential Pulse Code Modulation),是一种针对 16bits( 8bits或者更高) 声音波形数据的一种有损压缩算法,它将声音流中每次采样的 16bit 数据以 4bit 存储,所以压缩比 1:4. 而且压缩/解压缩算法非常简单,所以是一种低空间消耗,高质量高效率声音获得的好途径。保存声音的数据文件后缀名为 .AUD 的大多用ADPCM压缩。
     ADPCM主要是针对连续的波形数据的,保存的是波形的变化情况,以达到描述整个波形的目的,由于它的编码和解码的过程却很简洁,列在后面,相信大家能够看懂。
  8bits采样的声音人耳是可以勉强接受的,而 16bit 采样的声音可以算是高音质了。ADPCM算法却可以将每次采样得到的 16bit 数据压缩到 4bit 。需要注意的是,如果要压缩/解压缩得是立体声信号,采样时,声音信号是放在一起的,需要将两个声道分别处理。
     原理性的东西就不介绍过多了,网上有些相关的c代码,但整理的有点乱,下面给出我使用过的ADPCM压缩代码,只针对单声道的pcm数据。
 
1、adpcm.h

  1. struct adpcm_state {
  2.     short valprev; /* Previous output value */
  3.     char index; /* Index into stepsize table */
  4. }__attribute__((packed));

  5. typedef struct adpcm_state adpcm_state_t;

  6. void adpcm_coder(short [], char [], int, struct adpcm_state *);
  7. void adpcm_decoder(char [], short [], int, struct adpcm_state *);

2、adpcm.c

 
  1. #include "adpcm.h"
  2. #include <stdio.h>

  3. /* Intel ADPCM step variation table */
  4. static int indexTable[16] = {
  5.     -1, -1, -1, -1, 2, 4, 6, 8,
  6.     -1, -1, -1, -1, 2, 4, 6, 8,
  7. };

  8. static int stepsizeTable[89] = {
  9.     7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
  10.     19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
  11.     50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
  12.     130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
  13.     337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
  14.     876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
  15.     2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
  16.     5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
  17.     15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
  18. };
  19.     
  20. void adpcm_coder(short indata[], char outdata[], int len, adpcm_state_t *state)
  21. {
  22.     short *inp;            /* Input buffer pointer */
  23.     signed char *outp;    /* output buffer pointer */
  24.     int val;            /* Current input sample value */
  25.     int sign;            /* Current adpcm sign bit */
  26.     int delta;            /* Current adpcm output value */
  27.     int diff;            /* Difference between val and valprev */
  28.     int step;            /* Stepsize */
  29.     int valpred;        /* Predicted output value */
  30.     int vpdiff;            /* Current change to valpred */
  31.     int index;            /* Current step change index */
  32.     int outputbuffer;    /* place to keep previous 4-bit value */
  33.     int bufferstep;        /* toggle between outputbuffer/output */

  34.     outp = (signed char *)outdata;
  35.     inp = indata;

  36.     valpred = state->valprev;
  37.     index = state->index;
  38.     step = stepsizeTable[index];
  39.     
  40.     bufferstep = 1;
  41.     len /= 2;
  42.     
  43.     for ( ; len > 0 ; len-- ) {
  44.     val = *inp++;

  45.     /* Step 1 - compute difference with previous value */
  46.     diff = val - valpred;
  47.     sign = (diff < 0) ? 8 : 0;
  48.     if ( sign ) diff = (-diff);

  49.     /* Step 2 - Divide and clamp */
  50.     /* Note:
  51.     ** This code *approximately* computes:
  52.     ** delta = diff*4/step;
  53.     ** vpdiff = (delta+0.5)*step/4;
  54.     ** but in shift step bits are dropped. The net result of this is
  55.     ** that even if you have fast mul/div hardware you cannot put it to
  56.     ** good use since the fixup would be too expensive.
  57.     */
  58.     delta = 0;
  59.     vpdiff = (step >> 3);
  60.     
  61.     if ( diff >= step ) {
  62.      delta = 4;
  63.      diff -= step;
  64.      vpdiff += step;
  65.     }
  66.     step >>= 1;
  67.     if ( diff >= step ) {
  68.      delta |= 2;
  69.      diff -= step;
  70.      vpdiff += step;
  71.     }
  72.     step >>= 1;
  73.     if ( diff >= step ) {
  74.      delta |= 1;
  75.      vpdiff += step;
  76.     }

  77.     /* Step 3 - Update previous value */
  78.     if ( sign )
  79.      valpred -= vpdiff;
  80.     else
  81.      valpred += vpdiff;

  82.     /* Step 4 - Clamp previous value to 16 bits */
  83.     if ( valpred > 32767 )
  84.      valpred = 32767;
  85.     else if ( valpred < -32768 )
  86.      valpred = -32768;

  87.     /* Step 5 - Assemble value, update index and step values */
  88.     delta |= sign;
  89.     
  90.     index += indexTable[delta];
  91.     if ( index < 0 ) index = 0;
  92.     if ( index > 88 ) index = 88;
  93.     step = stepsizeTable[index];

  94.     /* Step 6 - Output value */
  95.     if ( bufferstep ) {
  96.      outputbuffer = (delta << 4) & 0xf0;
  97.     } else {
  98.      *outp++ = (delta & 0x0f) | outputbuffer;
  99.     }
  100.     bufferstep = !bufferstep;
  101.     }

  102.     /* Output last step, if needed */
  103.     if ( !bufferstep )
  104.       *outp++ = outputbuffer;
  105.     
  106.     state->valprev = valpred;
  107.     state->index = index;
  108. }

  109. void adpcm_decoder(char indata[], short outdata[], int len, adpcm_state_t *state)
  110. {
  111.     signed char *inp;    /* Input buffer pointer */
  112.     short *outp;        /* output buffer pointer */
  113.     int sign;            /* Current adpcm sign bit */
  114.     int delta;            /* Current adpcm output value */
  115.     int step;            /* Stepsize */
  116.     int valpred;        /* Predicted value */
  117.     int vpdiff;            /* Current change to valpred */
  118.     int index;            /* Current step change index */
  119.     int inputbuffer;    /* place to keep next 4-bit value */
  120.     int bufferstep;        /* toggle between inputbuffer/input */

  121.     outp = outdata;
  122.     inp = (signed char *)indata;

  123.     valpred = state->valprev;
  124.     index = state->index;
  125.     step = stepsizeTable[index];

  126.     bufferstep = 0;
  127.     len *= 2;            /* !!!! verify important TODO (FIX ME) JGF*/
  128.     
  129.     for ( ; len > 0 ; len-- ) {
  130.     
  131.     /* Step 1 - get the delta value */
  132.     if ( bufferstep ) {
  133.      delta = inputbuffer & 0xf;
  134.     } else {
  135.      inputbuffer = *inp++;
  136.      delta = (inputbuffer >> 4) & 0xf;
  137.     }
  138.     bufferstep = !bufferstep;

  139.     /* Step 2 - Find new index value (for later) */
  140.     index += indexTable[delta];
  141.     if ( index < 0 ) index = 0;
  142.     if ( index > 88 ) index = 88;

  143.     /* Step 3 - Separate sign and magnitude */
  144.     sign = delta & 8;
  145.     delta = delta & 7;

  146.     /* Step 4 - Compute difference and new predicted value */
  147.     /*
  148.     ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
  149.     ** in adpcm_coder.
  150.     */
  151.     vpdiff = step >> 3;
  152.     if ( delta & 4 ) vpdiff += step;
  153.     if ( delta & 2 ) vpdiff += step>>1;
  154.     if ( delta & 1 ) vpdiff += step>>2;

  155.     if ( sign )
  156.      valpred -= vpdiff;
  157.     else
  158.      valpred += vpdiff;

  159.     /* Step 5 - clamp output value */
  160.     if ( valpred > 32767 )
  161.      valpred = 32767;
  162.     else if ( valpred < -32768 )
  163.      valpred = -32768;

  164.     /* Step 6 - Update step value */
  165.     step = stepsizeTable[index];

  166.     /* Step 7 - Output value */
  167.     *outp++ = valpred;
  168.     }

  169.     state->valprev = valpred;
  170.     state->index = index;
  171. }


 
阅读(2500) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~