国产毛片a精品毛-国产毛片黄片-国产毛片久久国产-国产毛片久久精品-青娱乐极品在线-青娱乐精品

ADPCM壓縮算法介紹

發布時間:2011-6-13 16:06    發布者:絕對好文
關鍵詞: ADPCM , 壓縮算法
作者:xiaojiewen1128

ADPCM(Adaptive Differential Pulse Code Modulation),是一種針對 16bits( 或8bits或者更高) 聲音波形數據的一種有損壓縮算法,它將聲音流中每次采樣的 16bit 數據以 4bit 存儲,所以壓縮比 1:4. 而且壓縮/解壓縮算法非常簡單,所以是一種低空間消耗,高質量高效率聲音獲得的好途徑。保存聲音的數據文件后綴名為 .AUD 的大多用ADPCM 壓縮。

ADPCM 主要是針對連續的波形數據的,保存的是波形的變化情況,以達到描述整個波形的目的,由于它的編碼和解碼的過程卻很簡潔,列在后面,相信大家能夠看懂。

8bits采樣的聲音人耳是可以勉強接受的,而 16bit 采樣的聲音可以算是高音質了。ADPCM 算法卻可以將每次采樣得到的 16bit 數據壓縮到 4bit 。需要注意的是,如果要壓縮/解壓縮得是立體聲信號,采樣時,聲音信號是放在一起的,需要將兩個聲道分別處理。

ADPCM 壓縮過程

首先我們認為聲音信號都是從零開始的,那么需要初始化兩個變量

int index=0,prev_sample=0;

下面的循環將依次處理聲音數據流,注意其中的 getnextsample() 應該得到一個 16bit 的采樣數據,而 outputdata() 可以將計算出來的數據保存起來,程序中用到的 step_table[],index_adjust[] 附在后面:

    int index=0,prev_sample:=0;

    while (還有數據要處理)
    {
      cur_sample=getnextsample();        // 得到當前的采樣數據
      delta=cur_sample-prev_sample;       // 計算出和上一個的增量
      if (delta<0) delta=-delta,sb=8;      // 取絕對值
      else sb = 0 ;               // sb 保存的是符號位
      code = 4*delta / step_table[index];    // 根據 steptable[]得到一個 0-7 的值
      if (code>7) code=7;            // 它描述了聲音強度的變化量
      index += index_adjust[code] ;       // 根據聲音強度調整下次取steptable 的序號
      if (index<0) index=0;           // 便于下次得到更精確的變化量的描述
      else if (index>88) index=88;
      prev_sample=cur_sample;
      outputode(code|sb);            // 加上符號位保存起來
    }

 

ADPCM 解壓縮過程

接壓縮實際是壓縮的一個逆過程,同樣其中的 getnextcode() 應該得到一個編碼,,而 outputsample() 可以將解碼出來的聲音信號保存起來。這段代碼同樣使用了同一個的 setp_table[] 和 index_adjust() 附在后面:

    int index=0,cur_sample=0;

    while (還有數據要處理)
    {
        code=getnextcode();                       // 得到下一個數據
        if ((code & 8) != 0) sb=1 else sb=0;
        code&=7;                            // 將 code 分離為數據和符號
        delta = (step_table[index]*code)/4+step_table[index]/8;     // 后面加的一項是為了減少誤差
        if (sb==1) delta=-delta;
        cur_sample+=delta;                        // 計算出當前的波形數據
        if (cur_sample>32767) output_sample(32767);
        else if (cur_sample<-32768) output_sample(-32768);
        else output_sample(cur_sample);
        index+=index_adjust[code];
        if (index<0) index=0;
        if (index>88) index=88;
     }

附  ADPCM壓縮算法代碼實現

/***********************************************************
Copyright 1992 by Stichting Mathematisch Centrum, Amsterdam, The
Netherlands.

                        All Rights Reserved

Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the names of Stichting Mathematisch
Centrum or CWI not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior permission.

STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

******************************************************************/

/*
** Intel/DVI ADPCM coder/decoder.
**
** The algorithm for this coder was taken from the IMA Compatability Project
** proceedings, Vol 2, Number 2; May 1992.
**
** Version 1.2, 18-Dec-92.
**
** Change log:
** - Fixed a stupid bug, where the delta was computed as
**   stepsize*code/4 in stead of stepsize*(code+0.5)/4.
** - There was an off-by-one error causing it to pick
**   an incorrect delta once in a blue moon.
** - The NODIVMUL define has been removed. Computations are now always done
**   using shifts, adds and subtracts. It turned out that, because the standard
**   is defined using shift/add/subtract, you needed bits of fixup code
**   (because the div/mul simulation using shift/add/sub made some rounding
**   errors that real div/mul don't make) and all together the resultant code
**   ran slower than just using the shifts all the time.
** - Changed some of the variable names to be more meaningful.
*/

#include "adpcm.h"
#include /*DBG*/

#ifndef __STDC__
#define signed
#endif

/* Intel ADPCM step variation table */
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
};
   
void
adpcm_coder(indata, outdata, len, state)
    short indata[];
    char outdata[];
    int len;
    struct adpcm_state *state;
{
    short *inp;   /* Input buffer pointer */
    signed char *outp;  /* output buffer pointer */
    int val;   /* Current input sample value */
    int sign;   /* Current adpcm sign bit */
    int delta;   /* Current adpcm output value */
    int diff;   /* Difference between val and valprev */
    int step;   /* Stepsize */
    int valpred;  /* Predicted output value */
    int vpdiff;   /* Current change to valpred */
    int index;   /* Current step change index */
    int outputbuffer;  /* place to keep previous 4-bit value */
    int bufferstep;  /* toggle between outputbuffer/output */

    outp = (signed char *)outdata;
    inp = indata;

    valpred = state->valprev;
    index = state->index;
    step = stepsizeTable[index];
   
    bufferstep = 1;

    for ( ; len > 0 ; len-- ) {
val = *inp++;

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

/* 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.
*/
delta = 0;
vpdiff = (step >> 3);

if ( diff >= step ) {
     delta = 4;
     diff -= step;
     vpdiff += step;
}
step >>= 1;
if ( diff >= step  ) {
     delta |= 2;
     diff -= step;
     vpdiff += step;
}
step >>= 1;
if ( diff >= step ) {
     delta |= 1;
     vpdiff += step;
}

/* Step 3 - Update previous value */
if ( sign )
   valpred -= vpdiff;
else
   valpred += vpdiff;

/* Step 4 - Clamp previous value to 16 bits */
if ( valpred > 32767 )
   valpred = 32767;
else if ( valpred < -32768 )
   valpred = -32768;

/* Step 5 - Assemble value, update index and step values */
delta |= sign;

index += indexTable[delta];
if ( index < 0 ) index = 0;
if ( index > 88 ) index = 88;
step = stepsizeTable[index];

/* Step 6 - Output value */
if ( bufferstep ) {
     outputbuffer = (delta << 4) & 0xf0;
} else {
     *outp++ = (delta & 0x0f) | outputbuffer;
}
bufferstep = !bufferstep;
    }

    /* Output last step, if needed */
    if ( !bufferstep )
      *outp++ = outputbuffer;
   
    state->valprev = valpred;
    state->index = index;
}

void
adpcm_decoder(indata, outdata, len, state)
    char indata[];
    short outdata[];
    int len;
    struct adpcm_state *state;
{
    signed char *inp;  /* Input buffer pointer */
    short *outp;  /* output buffer pointer */
    int sign;   /* Current adpcm sign bit */
    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 */
    int inputbuffer;  /* place to keep next 4-bit value */
    int bufferstep;  /* toggle between inputbuffer/input */

    outp = outdata;
    inp = (signed char *)indata;

    valpred = state->valprev;
    index = state->index;
    step = stepsizeTable[index];

    bufferstep = 0;
   
    for ( ; len > 0 ; len-- ) {

/* Step 1 - get the delta value */
if ( bufferstep ) {
     delta = inputbuffer & 0xf;
} else {
     inputbuffer = *inp++;
     delta = (inputbuffer >> 4) & 0xf;
}
bufferstep = !bufferstep;

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

/* Step 3 - Separate sign and magnitude */
sign = delta & 8;
delta = delta & 7;

/* Step 4 - Compute difference and new predicted value */
/*
** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
** in adpcm_coder.
*/
vpdiff = step >> 3;
if ( delta & 4 ) vpdiff += step;
if ( delta & 2 ) vpdiff += step>>1;
if ( delta & 1 ) vpdiff += step>>2;

if ( sign )
   valpred -= vpdiff;
else
   valpred += vpdiff;

/* Step 5 - clamp output value */
if ( valpred > 32767 )
   valpred = 32767;
else if ( valpred < -32768 )
   valpred = -32768;

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

/* Step 7 - Output value */
*outp++ = valpred;
    }

    state->valprev = valpred;
    state->index = index;
}
本文地址:http://m.qingdxww.cn/thread-68438-1-1.html     【打印本頁】

本站部分文章為轉載或網友發布,目的在于傳遞和分享信息,并不代表本網贊同其觀點和對其真實性負責;文章版權歸原作者及原出處所有,如涉及作品內容、版權和其它問題,我們將根據著作權人的要求,第一時間更正或刪除。
您需要登錄后才可以發表評論 登錄 | 立即注冊

廠商推薦

  • Microchip視頻專區
  • 使用SAM-IoT Wx v2開發板演示AWS IoT Core應用程序
  • 使用Harmony3加速TCP/IP應用的開發培訓教程
  • 集成高級模擬外設的PIC18F-Q71家族介紹培訓教程
  • 探索PIC16F13145 MCU系列——快速概覽
  • 貿澤電子(Mouser)專區

相關視頻

關于我們  -  服務條款  -  使用指南  -  站點地圖  -  友情鏈接  -  聯系我們
電子工程網 © 版權所有   京ICP備16069177號 | 京公網安備11010502021702
快速回復 返回頂部 返回列表
主站蜘蛛池模板: 日韩人妻无码精品久久中文字幕| 深夜国产成人福利在线观看女同 | 国产 亚洲 中文字幕 在线| 护士WC女子撒尿| 日韩视频中文在线一区| 影音先锋电影资源av| 亚洲综合图片区| 日韩欧美不卡视频| 亚洲一区精品在线| 在线国产视频| 迈开腿让我看下你的小草莓声音| 色四房播播| 青青青国产在线观看| 四虎影在线永久免费观看| 亚洲视频三级| 伊人啪啪| 20岁αsrian男同志免费| 国产最新地址| 在线视频 亚洲| 青草免费在线观看| 色偷偷五月天| www.伊人网| 天堂网久久| 亚洲a级片| 天堂tv亚洲tv日本tv不卡| 深夜福利网址| 办公室激情在线观看| 国产免国产免费| 伊人亚洲综合青草青草久热| 亚洲精品aaa揭晓| 天天干天天操天天操| 四虎精品视频| 亚洲精品一区二区三区在线播放 | 日韩一级视频| 亚洲热视频| 久久精品AV一区二区无码| 亚洲电影第1页| 青青青激情视频在线最新 | 偷拍 拍自 欧美色区| 四虎永久免费影院| 香蕉免费一级视频在线观看|