Ticket #507: ticket507.patch

File ticket507.patch, 49.3 KB (added by nanang, 17 years ago)

codec source & wrapper

  • pjmedia/include/pjmedia-codec/g722.h

     
     1/* $Id$ */ 
     2/*  
     3 * Copyright (C)2003-2008 Benny Prijono <benny@prijono.org> 
     4 * 
     5 * This program is free software; you can redistribute it and/or modify 
     6 * it under the terms of the GNU General Public License as published by 
     7 * the Free Software Foundation; either version 2 of the License, or 
     8 * (at your option) any later version. 
     9 * 
     10 * This program is distributed in the hope that it will be useful, 
     11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
     12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
     13 * GNU General Public License for more details. 
     14 * 
     15 * You should have received a copy of the GNU General Public License 
     16 * along with this program; if not, write to the Free Software 
     17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  
     18 */ 
     19 
     20#ifndef __PJMEDIA_CODEC_G722_H__ 
     21#define __PJMEDIA_CODEC_G722_H__ 
     22 
     23#include <pjmedia-codec/types.h> 
     24 
     25PJ_DECL(pj_status_t) pjmedia_codec_g722_init(pjmedia_endpt *endpt); 
     26PJ_DECL(pj_status_t) pjmedia_codec_g722_deinit(void); 
     27 
     28#endif /* __PJMEDIA_CODEC_G722_H__ */ 
     29 
  • pjmedia/src/pjmedia-codec/g722.c

     
     1#include <pjmedia-codec/g722.h> 
     2#include <pjmedia/codec.h> 
     3#include <pjmedia/errno.h> 
     4#include <pjmedia/endpoint.h> 
     5#include <pjmedia/plc.h> 
     6#include <pjmedia/port.h> 
     7#include <pjmedia/silencedet.h> 
     8#include <pj/assert.h> 
     9#include <pj/log.h> 
     10#include <pj/pool.h> 
     11#include <pj/string.h> 
     12#include <pj/os.h> 
     13 
     14#if defined(PJMEDIA_HAS_G722_CODEC) && (PJMEDIA_HAS_G722_CODEC != 0) 
     15 
     16#include "g722/g722_enc.h" 
     17#include "g722/g722_dec.h" 
     18 
     19#define THIS_FILE   "g722.c" 
     20 
     21/* Defines */ 
     22#define PTIME                   (20) 
     23#define SAMPLES_PER_FRAME       (16000 * PTIME /1000) 
     24#define FRAME_LEN               (160) 
     25#define PLC_DISABLED            1                
     26 
     27/* Tracing */ 
     28#ifndef PJ_TRACE 
     29#   define PJ_TRACE     0        
     30#endif 
     31 
     32#if PJ_TRACE  
     33#   define TRACE_(expr) PJ_LOG(4,expr) 
     34#else 
     35#   define TRACE_(expr) 
     36#endif 
     37 
     38 
     39/* Prototypes for G722 factory */ 
     40static pj_status_t g722_test_alloc(pjmedia_codec_factory *factory,  
     41                                   const pjmedia_codec_info *id ); 
     42static pj_status_t g722_default_attr(pjmedia_codec_factory *factory,  
     43                                     const pjmedia_codec_info *id,  
     44                                     pjmedia_codec_param *attr ); 
     45static pj_status_t g722_enum_codecs(pjmedia_codec_factory *factory,  
     46                                    unsigned *count,  
     47                                    pjmedia_codec_info codecs[]); 
     48static pj_status_t g722_alloc_codec(pjmedia_codec_factory *factory,  
     49                                    const pjmedia_codec_info *id,  
     50                                    pjmedia_codec **p_codec); 
     51static pj_status_t g722_dealloc_codec(pjmedia_codec_factory *factory,  
     52                                      pjmedia_codec *codec ); 
     53 
     54/* Prototypes for G722 implementation. */ 
     55static pj_status_t  g722_codec_init(pjmedia_codec *codec,  
     56                                    pj_pool_t *pool ); 
     57static pj_status_t  g722_codec_open(pjmedia_codec *codec,  
     58                                    pjmedia_codec_param *attr ); 
     59static pj_status_t  g722_codec_close(pjmedia_codec *codec ); 
     60static pj_status_t  g722_codec_modify(pjmedia_codec *codec,  
     61                                      const pjmedia_codec_param *attr ); 
     62static pj_status_t  g722_codec_parse(pjmedia_codec *codec, 
     63                                     void *pkt, 
     64                                     pj_size_t pkt_size, 
     65                                     const pj_timestamp *ts, 
     66                                     unsigned *frame_cnt, 
     67                                     pjmedia_frame frames[]); 
     68static pj_status_t  g722_codec_encode(pjmedia_codec *codec,  
     69                                      const struct pjmedia_frame *input, 
     70                                      unsigned output_buf_len,  
     71                                      struct pjmedia_frame *output); 
     72static pj_status_t  g722_codec_decode(pjmedia_codec *codec,  
     73                                      const struct pjmedia_frame *input, 
     74                                      unsigned output_buf_len,  
     75                                      struct pjmedia_frame *output); 
     76#if !PLC_DISABLED 
     77static pj_status_t  g722_codec_recover(pjmedia_codec *codec, 
     78                                      unsigned output_buf_len, 
     79                                      struct pjmedia_frame *output); 
     80#endif 
     81 
     82/* Definition for G722 codec operations. */ 
     83static pjmedia_codec_op g722_op =  
     84{ 
     85    &g722_codec_init, 
     86    &g722_codec_open, 
     87    &g722_codec_close, 
     88    &g722_codec_modify, 
     89    &g722_codec_parse, 
     90    &g722_codec_encode, 
     91    &g722_codec_decode, 
     92#if !PLC_DISABLED 
     93    &g722_codec_recover 
     94#else 
     95    NULL 
     96#endif 
     97}; 
     98 
     99/* Definition for G722 codec factory operations. */ 
     100static pjmedia_codec_factory_op g722_factory_op = 
     101{ 
     102    &g722_test_alloc, 
     103    &g722_default_attr, 
     104    &g722_enum_codecs, 
     105    &g722_alloc_codec, 
     106    &g722_dealloc_codec 
     107}; 
     108 
     109/* G722 factory */ 
     110static struct g722_codec_factory 
     111{ 
     112    pjmedia_codec_factory    base; 
     113    pjmedia_endpt           *endpt; 
     114    pj_pool_t               *pool; 
     115    pj_mutex_t              *mutex; 
     116    pjmedia_codec            codec_list; 
     117} g722_codec_factory; 
     118 
     119 
     120/* G722 codec private data. */ 
     121struct g722_data 
     122{ 
     123    g722_enc_t           encoder; 
     124    g722_dec_t           decoder; 
     125    pj_bool_t            plc_enabled; 
     126    pj_bool_t            vad_enabled; 
     127    pjmedia_silence_det *vad; 
     128    pj_timestamp         last_tx; 
     129#if !PLC_DISABLED 
     130    pjmedia_plc         *plc; 
     131#endif 
     132}; 
     133 
     134 
     135 
     136/* 
     137 * Initialize and register G722 codec factory to pjmedia endpoint. 
     138 */ 
     139PJ_DEF(pj_status_t) pjmedia_codec_g722_init( pjmedia_endpt *endpt ) 
     140{ 
     141    pjmedia_codec_mgr *codec_mgr; 
     142    pj_status_t status; 
     143 
     144    if (g722_codec_factory.pool != NULL) 
     145        return PJ_SUCCESS; 
     146 
     147    /* Create G722 codec factory. */ 
     148    g722_codec_factory.base.op = &g722_factory_op; 
     149    g722_codec_factory.base.factory_data = NULL; 
     150    g722_codec_factory.endpt = endpt; 
     151 
     152    g722_codec_factory.pool = pjmedia_endpt_create_pool(endpt, "g722", 1000,  
     153                                                        1000); 
     154    if (!g722_codec_factory.pool) 
     155        return PJ_ENOMEM; 
     156 
     157    pj_list_init(&g722_codec_factory.codec_list); 
     158 
     159    /* Create mutex. */ 
     160    status = pj_mutex_create_simple(g722_codec_factory.pool, "g722",  
     161                                    &g722_codec_factory.mutex); 
     162    if (status != PJ_SUCCESS) 
     163        goto on_error; 
     164 
     165    /* Get the codec manager. */ 
     166    codec_mgr = pjmedia_endpt_get_codec_mgr(endpt); 
     167    if (!codec_mgr) { 
     168        status = PJ_EINVALIDOP; 
     169        goto on_error; 
     170    } 
     171 
     172    /* Register codec factory to endpoint. */ 
     173    status = pjmedia_codec_mgr_register_factory(codec_mgr,  
     174                                                &g722_codec_factory.base); 
     175    if (status != PJ_SUCCESS) 
     176        goto on_error; 
     177 
     178    TRACE_((THIS_FILE, "G722 codec factory initialized")); 
     179     
     180    /* Done. */ 
     181    return PJ_SUCCESS; 
     182 
     183on_error: 
     184    pj_pool_release(g722_codec_factory.pool); 
     185    g722_codec_factory.pool = NULL; 
     186    return status; 
     187} 
     188 
     189/* 
     190 * Unregister G722 codec factory from pjmedia endpoint and deinitialize 
     191 * the G722 codec library. 
     192 */ 
     193PJ_DEF(pj_status_t) pjmedia_codec_g722_deinit(void) 
     194{ 
     195    pjmedia_codec_mgr *codec_mgr; 
     196    pj_status_t status; 
     197 
     198    if (g722_codec_factory.pool == NULL) 
     199        return PJ_SUCCESS; 
     200 
     201    /* Get the codec manager. */ 
     202    codec_mgr = pjmedia_endpt_get_codec_mgr(g722_codec_factory.endpt); 
     203    if (!codec_mgr) { 
     204        pj_pool_release(g722_codec_factory.pool); 
     205        g722_codec_factory.pool = NULL; 
     206        return PJ_EINVALIDOP; 
     207    } 
     208 
     209    /* Unregister G722 codec factory. */ 
     210    status = pjmedia_codec_mgr_unregister_factory(codec_mgr, 
     211                                                  &g722_codec_factory.base); 
     212     
     213    /* Destroy mutex. */ 
     214    pj_mutex_destroy(g722_codec_factory.mutex); 
     215 
     216    /* Destroy pool. */ 
     217    pj_pool_release(g722_codec_factory.pool); 
     218    g722_codec_factory.pool = NULL; 
     219     
     220    TRACE_((THIS_FILE, "G722 codec factory shutdown")); 
     221    return status; 
     222} 
     223 
     224/*  
     225 * Check if factory can allocate the specified codec.  
     226 */ 
     227static pj_status_t g722_test_alloc(pjmedia_codec_factory *factory,  
     228                                   const pjmedia_codec_info *info ) 
     229{ 
     230    PJ_UNUSED_ARG(factory); 
     231 
     232    /* Check payload type. */ 
     233    if (info->pt != PJMEDIA_RTP_PT_G722) 
     234        return PJMEDIA_CODEC_EUNSUP; 
     235 
     236    /* Ignore the rest, since it's static payload type. */ 
     237 
     238    return PJ_SUCCESS; 
     239} 
     240 
     241/* 
     242 * Generate default attribute. 
     243 */ 
     244static pj_status_t g722_default_attr( pjmedia_codec_factory *factory,  
     245                                      const pjmedia_codec_info *id,  
     246                                      pjmedia_codec_param *attr ) 
     247{ 
     248    PJ_UNUSED_ARG(factory); 
     249    PJ_UNUSED_ARG(id); 
     250 
     251    pj_bzero(attr, sizeof(pjmedia_codec_param)); 
     252    attr->info.clock_rate = 16000; 
     253    attr->info.channel_cnt = 1; 
     254    attr->info.avg_bps = 64000; 
     255    attr->info.pcm_bits_per_sample = 16; 
     256    attr->info.frm_ptime = PTIME; 
     257    attr->info.pt = PJMEDIA_RTP_PT_G722; 
     258 
     259    attr->setting.frm_per_pkt = 1; 
     260    attr->setting.vad = 1; 
     261    attr->setting.plc = 0; 
     262 
     263    /* Default all other flag bits disabled. */ 
     264 
     265    return PJ_SUCCESS; 
     266} 
     267 
     268/* 
     269 * Enum codecs supported by this factory (i.e. only G722!). 
     270 */ 
     271static pj_status_t g722_enum_codecs(pjmedia_codec_factory *factory,  
     272                                    unsigned *count,  
     273                                    pjmedia_codec_info codecs[]) 
     274{ 
     275    PJ_UNUSED_ARG(factory); 
     276    PJ_ASSERT_RETURN(codecs && *count > 0, PJ_EINVAL); 
     277 
     278    pj_bzero(&codecs[0], sizeof(pjmedia_codec_info)); 
     279    codecs[0].encoding_name = pj_str("G722"); 
     280    codecs[0].pt = PJMEDIA_RTP_PT_G722; 
     281    codecs[0].type = PJMEDIA_TYPE_AUDIO; 
     282    codecs[0].clock_rate = 16000; 
     283    codecs[0].channel_cnt = 1; 
     284 
     285    *count = 1; 
     286 
     287    return PJ_SUCCESS; 
     288} 
     289 
     290/* 
     291 * Allocate a new G722 codec instance. 
     292 */ 
     293static pj_status_t g722_alloc_codec(pjmedia_codec_factory *factory,  
     294                                    const pjmedia_codec_info *id, 
     295                                    pjmedia_codec **p_codec) 
     296{ 
     297    pjmedia_codec *codec; 
     298    struct g722_data *g722_data; 
     299 
     300    PJ_ASSERT_RETURN(factory && id && p_codec, PJ_EINVAL); 
     301    PJ_ASSERT_RETURN(factory == &g722_codec_factory.base, PJ_EINVAL); 
     302 
     303    pj_mutex_lock(g722_codec_factory.mutex); 
     304 
     305    /* Get free nodes, if any. */ 
     306    if (!pj_list_empty(&g722_codec_factory.codec_list)) { 
     307        codec = g722_codec_factory.codec_list.next; 
     308        pj_list_erase(codec); 
     309    } else { 
     310        pj_status_t status; 
     311 
     312        codec = PJ_POOL_ZALLOC_T(g722_codec_factory.pool, pjmedia_codec); 
     313        PJ_ASSERT_RETURN(codec != NULL, PJ_ENOMEM); 
     314        codec->op = &g722_op; 
     315        codec->factory = factory; 
     316 
     317        g722_data = PJ_POOL_ZALLOC_T(g722_codec_factory.pool, struct g722_data); 
     318        codec->codec_data = g722_data; 
     319 
     320#if !PLC_DISABLED 
     321        /* Create PLC */ 
     322        status = pjmedia_plc_create(g722_codec_factory.pool, 16000,  
     323                                    SAMPLES_PER_FRAME, 0, &g722_data->plc); 
     324        if (status != PJ_SUCCESS) { 
     325            pj_mutex_unlock(g722_codec_factory.mutex); 
     326            return status; 
     327        } 
     328#endif 
     329 
     330        /* Create silence detector */ 
     331        status = pjmedia_silence_det_create(g722_codec_factory.pool, 
     332                                            16000, SAMPLES_PER_FRAME, 
     333                                            &g722_data->vad); 
     334        if (status != PJ_SUCCESS) { 
     335            pj_mutex_unlock(g722_codec_factory.mutex); 
     336            TRACE_((THIS_FILE, "Create silence detector failed (status = %d)",  
     337                               status)); 
     338            return status; 
     339        } 
     340    } 
     341 
     342 
     343    pj_mutex_unlock(g722_codec_factory.mutex); 
     344 
     345    *p_codec = codec; 
     346    return PJ_SUCCESS; 
     347} 
     348 
     349/* 
     350 * Free codec. 
     351 */ 
     352static pj_status_t g722_dealloc_codec(pjmedia_codec_factory *factory,  
     353                                      pjmedia_codec *codec ) 
     354{ 
     355    struct g722_data *g722_data; 
     356    int i; 
     357 
     358    PJ_ASSERT_RETURN(factory && codec, PJ_EINVAL); 
     359    PJ_ASSERT_RETURN(factory == &g722_codec_factory.base, PJ_EINVAL); 
     360 
     361    g722_data = (struct g722_data*) codec->codec_data; 
     362 
     363    /* Close codec, if it's not closed. */ 
     364    g722_codec_close(codec); 
     365 
     366#if !PLC_DISABLED 
     367    /* Clear left samples in the PLC, since codec+plc will be reused 
     368     * next time. 
     369     */ 
     370    for (i=0; i<2; ++i) { 
     371        pj_int16_t frame[SAMPLES_PER_FRAME]; 
     372        pjmedia_zero_samples(frame, PJ_ARRAY_SIZE(frame)); 
     373        pjmedia_plc_save(g722_data->plc, frame); 
     374    } 
     375#else 
     376    PJ_UNUSED_ARG(i); 
     377#endif 
     378 
     379    /* Re-init silence_period */ 
     380    pj_set_timestamp32(&g722_data->last_tx, 0, 0); 
     381 
     382    /* Put in the free list. */ 
     383    pj_mutex_lock(g722_codec_factory.mutex); 
     384    pj_list_push_front(&g722_codec_factory.codec_list, codec); 
     385    pj_mutex_unlock(g722_codec_factory.mutex); 
     386 
     387    return PJ_SUCCESS; 
     388} 
     389 
     390/* 
     391 * Init codec. 
     392 */ 
     393static pj_status_t g722_codec_init(pjmedia_codec *codec,  
     394                                   pj_pool_t *pool ) 
     395{ 
     396    PJ_UNUSED_ARG(codec); 
     397    PJ_UNUSED_ARG(pool); 
     398    return PJ_SUCCESS; 
     399} 
     400 
     401/* 
     402 * Open codec. 
     403 */ 
     404static pj_status_t g722_codec_open(pjmedia_codec *codec,  
     405                                   pjmedia_codec_param *attr ) 
     406{ 
     407    struct g722_data *g722_data = (struct g722_data*) codec->codec_data; 
     408    pj_status_t status; 
     409 
     410    PJ_ASSERT_RETURN(codec && attr, PJ_EINVAL); 
     411    PJ_ASSERT_RETURN(g722_data != NULL, PJ_EINVALIDOP); 
     412 
     413    status = g722_enc_init(&g722_data->encoder); 
     414    if (status != PJ_SUCCESS) { 
     415        TRACE_((THIS_FILE, "g722_enc_init() failed, status=%d", status)); 
     416        pj_mutex_unlock(g722_codec_factory.mutex); 
     417        return PJMEDIA_CODEC_EFAILED; 
     418    } 
     419 
     420    status = g722_dec_init(&g722_data->decoder); 
     421    if (status != PJ_SUCCESS) { 
     422        TRACE_((THIS_FILE, "g722_dec_init() failed, status=%d", status)); 
     423        pj_mutex_unlock(g722_codec_factory.mutex); 
     424        return PJMEDIA_CODEC_EFAILED; 
     425    } 
     426 
     427    g722_data->vad_enabled = (attr->setting.vad != 0); 
     428    g722_data->plc_enabled = (attr->setting.plc != 0); 
     429 
     430    TRACE_((THIS_FILE, "G722 codec opened: vad=%d, plc=%d", 
     431                        g722_data->vad_enabled, g722_data->plc_enabled)); 
     432    return PJ_SUCCESS; 
     433} 
     434 
     435/* 
     436 * Close codec. 
     437 */ 
     438static pj_status_t g722_codec_close( pjmedia_codec *codec ) 
     439{ 
     440    /* The codec, encoder, and decoder will be reused, so there's 
     441     * nothing to do here 
     442     */ 
     443 
     444    PJ_UNUSED_ARG(codec); 
     445     
     446    TRACE_((THIS_FILE, "G722 codec closed")); 
     447    return PJ_SUCCESS; 
     448} 
     449 
     450 
     451/* 
     452 * Modify codec settings. 
     453 */ 
     454static pj_status_t  g722_codec_modify(pjmedia_codec *codec,  
     455                                     const pjmedia_codec_param *attr ) 
     456{ 
     457    struct g722_data *g722_data = (struct g722_data*) codec->codec_data; 
     458 
     459    pj_assert(g722_data != NULL); 
     460 
     461    g722_data->vad_enabled = (attr->setting.vad != 0); 
     462    g722_data->plc_enabled = (attr->setting.plc != 0); 
     463 
     464    TRACE_((THIS_FILE, "G722 codec modified: vad=%d, plc=%d", 
     465                        g722_data->vad_enabled, g722_data->plc_enabled)); 
     466    return PJ_SUCCESS; 
     467} 
     468 
     469 
     470/* 
     471 * Get frames in the packet. 
     472 */ 
     473static pj_status_t  g722_codec_parse(pjmedia_codec *codec, 
     474                                     void *pkt, 
     475                                     pj_size_t pkt_size, 
     476                                     const pj_timestamp *ts, 
     477                                     unsigned *frame_cnt, 
     478                                     pjmedia_frame frames[]) 
     479{ 
     480    unsigned count = 0; 
     481 
     482    PJ_UNUSED_ARG(codec); 
     483 
     484    PJ_ASSERT_RETURN(frame_cnt, PJ_EINVAL); 
     485 
     486    TRACE_((THIS_FILE, "G722 parse(): input len=%d", pkt_size)); 
     487 
     488    while (pkt_size >= FRAME_LEN && count < *frame_cnt) { 
     489        frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO; 
     490        frames[count].buf = pkt; 
     491        frames[count].size = FRAME_LEN; 
     492        frames[count].timestamp.u64 = ts->u64 + count * SAMPLES_PER_FRAME; 
     493 
     494        pkt = ((char*)pkt) + FRAME_LEN; 
     495        pkt_size -= FRAME_LEN; 
     496 
     497        ++count; 
     498    } 
     499 
     500    TRACE_((THIS_FILE, "G722 parse(): got %d frames", count)); 
     501 
     502    *frame_cnt = count; 
     503    return PJ_SUCCESS; 
     504} 
     505 
     506/* 
     507 * Encode frame. 
     508 */ 
     509static pj_status_t g722_codec_encode(pjmedia_codec *codec,  
     510                                     const struct pjmedia_frame *input, 
     511                                     unsigned output_buf_len,  
     512                                     struct pjmedia_frame *output) 
     513{ 
     514    struct g722_data *g722_data = (struct g722_data*) codec->codec_data; 
     515    pj_status_t status; 
     516 
     517    pj_assert(g722_data != NULL); 
     518    PJ_ASSERT_RETURN(input && output, PJ_EINVAL); 
     519 
     520    if (output_buf_len < FRAME_LEN) 
     521        return PJMEDIA_CODEC_EFRMTOOSHORT; 
     522 
     523    PJ_ASSERT_RETURN(input->size/2 == SAMPLES_PER_FRAME,  
     524                     PJMEDIA_CODEC_EPCMFRMINLEN); 
     525 
     526    /* Detect silence */ 
     527    if (g722_data->vad_enabled) { 
     528        pj_bool_t is_silence; 
     529        pj_int32_t silence_duration; 
     530 
     531        silence_duration = pj_timestamp_diff32(&g722_data->last_tx,  
     532                                               &input->timestamp); 
     533 
     534        is_silence = pjmedia_silence_det_detect(g722_data->vad,  
     535                                                (const pj_int16_t*) input->buf, 
     536                                                (input->size >> 1), 
     537                                                NULL); 
     538        if (is_silence && 
     539            PJMEDIA_CODEC_MAX_SILENCE_PERIOD != -1 && 
     540            silence_duration < PJMEDIA_CODEC_MAX_SILENCE_PERIOD)  
     541        { 
     542            output->type = PJMEDIA_FRAME_TYPE_NONE; 
     543            output->buf = NULL; 
     544            output->size = 0; 
     545            output->timestamp = input->timestamp; 
     546            return PJ_SUCCESS; 
     547        } else { 
     548            g722_data->last_tx = input->timestamp; 
     549        } 
     550    } 
     551 
     552    /* Encode to temporary buffer */ 
     553    status = g722_enc_encode(&g722_data->encoder, (pj_int16_t*)input->buf,  
     554                             SAMPLES_PER_FRAME, output->buf, &output->size); 
     555    if (status != PJ_SUCCESS) { 
     556        output->size = 0; 
     557        output->buf = NULL; 
     558        output->type = PJMEDIA_FRAME_TYPE_NONE; 
     559        TRACE_((THIS_FILE, "G722 encode() status: %d", status)); 
     560        return PJMEDIA_CODEC_EFAILED; 
     561    } 
     562 
     563    output->type = PJMEDIA_FRAME_TYPE_AUDIO; 
     564     
     565    TRACE_((THIS_FILE, "G722 encode(): size=%d", output->size)); 
     566    return PJ_SUCCESS; 
     567} 
     568 
     569/* 
     570 * Decode frame. 
     571 */ 
     572static pj_status_t g722_codec_decode(pjmedia_codec *codec,  
     573                                     const struct pjmedia_frame *input, 
     574                                     unsigned output_buf_len,  
     575                                     struct pjmedia_frame *output) 
     576{ 
     577    struct g722_data *g722_data = (struct g722_data*) codec->codec_data; 
     578    pj_status_t status; 
     579 
     580    pj_assert(g722_data != NULL); 
     581    PJ_ASSERT_RETURN(input && output, PJ_EINVAL); 
     582 
     583    TRACE_((THIS_FILE, "G722 decode(): inbuf=%p, insize=%d, outbuf=%p," 
     584                       "outsize=%d", 
     585                       input->buf, input->size, output->buf, output_buf_len)); 
     586     
     587    if (output_buf_len < SAMPLES_PER_FRAME * 2) { 
     588        TRACE_((THIS_FILE, "G722 decode() ERROR: PJMEDIA_CODEC_EPCMTOOSHORT")); 
     589        return PJMEDIA_CODEC_EPCMTOOSHORT; 
     590    } 
     591 
     592    if (input->size != FRAME_LEN) { 
     593        TRACE_((THIS_FILE, "G722 decode() ERROR: PJMEDIA_CODEC_EFRMTOOSHORT")); 
     594        return PJMEDIA_CODEC_EFRMTOOSHORT; 
     595    } 
     596 
     597 
     598    /* Decode */ 
     599    output->size = SAMPLES_PER_FRAME; 
     600    status = g722_dec_decode(&g722_data->decoder, input->buf, input->size, 
     601                             (pj_int16_t*)output->buf, &output->size); 
     602    if (status != PJ_SUCCESS) { 
     603        TRACE_((THIS_FILE, "G722 decode() status: %d", status)); 
     604        return PJMEDIA_CODEC_EFAILED; 
     605    } 
     606 
     607    pj_assert(output->size == SAMPLES_PER_FRAME); 
     608    output->size = SAMPLES_PER_FRAME * 2; 
     609    output->type = PJMEDIA_FRAME_TYPE_AUDIO; 
     610 
     611#if !PLC_DISABLED 
     612    if (g722_data->plc_enabled) 
     613        pjmedia_plc_save(g722_data->plc, output->buf); 
     614#endif 
     615 
     616    TRACE_((THIS_FILE, "G722 decode done")); 
     617    return PJ_SUCCESS; 
     618} 
     619 
     620 
     621#if !PLC_DISABLED 
     622/* 
     623 * Recover lost frame. 
     624 */ 
     625static pj_status_t  g722_codec_recover(pjmedia_codec *codec, 
     626                                       unsigned output_buf_len, 
     627                                       struct pjmedia_frame *output) 
     628{ 
     629    struct g722_data *g722_data = codec->codec_data; 
     630 
     631    PJ_ASSERT_RETURN(g722_data->plc_enabled, PJ_EINVALIDOP); 
     632 
     633    PJ_ASSERT_RETURN(output_buf_len >= SAMPLES_PER_FRAME * 2,  
     634                     PJMEDIA_CODEC_EPCMTOOSHORT); 
     635 
     636    pjmedia_plc_generate(g722_data->plc, output->buf); 
     637 
     638    output->size = SAMPLES_PER_FRAME * 2; 
     639    output->type = PJMEDIA_FRAME_TYPE_AUDIO; 
     640     
     641    return PJ_SUCCESS; 
     642} 
     643#endif 
     644 
     645#endif // PJMEDIA_HAS_G722_CODEC 
     646 No newline at end of file 
  • pjmedia/src/pjmedia-codec/g722/g722_dec.h

     
     1/* $Id$ */ 
     2/*  
     3 * Copyright (C)2003-2008 Benny Prijono <benny@prijono.org> 
     4 * 
     5 * This program is free software; you can redistribute it and/or modify 
     6 * it under the terms of the GNU General Public License as published by 
     7 * the Free Software Foundation; either version 2 of the License, or 
     8 * (at your option) any later version. 
     9 * 
     10 * This program is distributed in the hope that it will be useful, 
     11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
     12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
     13 * GNU General Public License for more details. 
     14 * 
     15 * You should have received a copy of the GNU General Public License 
     16 * along with this program; if not, write to the Free Software 
     17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  
     18 */ 
     19 
     20#ifndef __PJMEDIA_CODEC_G722_DEC_H__ 
     21#define __PJMEDIA_CODEC_G722_DEC_H__ 
     22 
     23#include <pjmedia-codec/types.h> 
     24 
     25/* Decoder state */ 
     26typedef struct g722_dec_t { 
     27    /* PCM low band */ 
     28    int slow; 
     29    int detlow; 
     30    int spl; 
     31    int szl; 
     32    int rlt  [3]; 
     33    int al   [3]; 
     34    int apl  [3]; 
     35    int plt  [3]; 
     36    int dlt  [7]; 
     37    int bl   [7]; 
     38    int bpl  [7]; 
     39    int sgl  [7]; 
     40    int nbl; 
     41 
     42    /* PCM high band*/ 
     43    int shigh; 
     44    int dethigh; 
     45    int sph; 
     46    int szh; 
     47    int rh   [3]; 
     48    int ah   [3]; 
     49    int aph  [3]; 
     50    int ph   [3]; 
     51    int dh   [7]; 
     52    int bh   [7]; 
     53    int bph  [7]; 
     54    int sgh  [7]; 
     55    int nbh; 
     56 
     57    /* QMF signal history */ 
     58    int xd[12]; 
     59    int xs[12]; 
     60} g722_dec_t; 
     61 
     62 
     63PJ_DECL(pj_status_t) g722_dec_init(g722_dec_t *dec); 
     64 
     65PJ_DECL(pj_status_t) g722_dec_decode(g722_dec_t *dec,  
     66                                     void *in,  
     67                                     pj_size_t in_size, 
     68                                     pj_int16_t out[], 
     69                                     pj_size_t *nsamples); 
     70 
     71PJ_DECL(pj_status_t) g722_dec_deinit(g722_dec_t *dec); 
     72 
     73#endif /* __PJMEDIA_CODEC_G722_DEC_H__ */ 
     74 
  • pjmedia/src/pjmedia-codec/g722/g722_enc.c

     
     1#include <pjmedia/errno.h> 
     2#include <pj/assert.h> 
     3#include <pj/pool.h> 
     4 
     5#include "g722_enc.h" 
     6 
     7#if defined(PJMEDIA_HAS_G722_CODEC) && (PJMEDIA_HAS_G722_CODEC != 0) 
     8 
     9#define SATURATE(v, max, min) \ 
     10    if (v>max) v = max; \ 
     11    else if (v<min) v = min 
     12 
     13/* QMF tap coefficients */ 
     14int g722_qmf_coeff[24] = { 
     15     3,     -11,    -11,    53,     12,     -156, 
     16    32,     362,    -210,   -805,   951,    3876, 
     17    3876,   951,    -805,   -210,   362,    32, 
     18    -156,   12,     53,     -11,    -11,    3 
     19}; 
     20 
     21 
     22static int block1l (int xl, int sl, int detl) 
     23{ 
     24    int il ; 
     25 
     26    int i, el, sil, mil, wd, wd1, hdu ; 
     27 
     28    static int q6[32] = { 
     29        0, 35, 72, 110, 150, 190, 233, 276, 323, 
     30        370, 422, 473, 530, 587, 650, 714, 786, 
     31        858, 940, 1023, 1121, 1219, 1339, 1458, 
     32        1612, 1765, 1980, 2195, 2557, 2919, 0, 0 
     33    }; 
     34 
     35    static int iln[32] = { 
     36        0, 63, 62, 31, 30, 29, 28, 27, 26, 25, 
     37        24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 
     38        13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 0  
     39    }; 
     40 
     41    static int ilp[32] = { 
     42        0, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 
     43        51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 
     44        40, 39, 38, 37, 36, 35, 34, 33, 32, 0  
     45    }; 
     46 
     47    /* SUBTRA */ 
     48 
     49    el = xl - sl ; 
     50    SATURATE(el, 32767, -32768); 
     51 
     52    /* QUANTL */ 
     53 
     54    sil = el >> 15 ; 
     55    if (sil == 0 )  wd = el ; 
     56    else wd = 32767 - el & 32767 ; 
     57 
     58    mil = 1 ; 
     59 
     60    for (i = 1; i < 30; i++) { 
     61        hdu = (q6[i] << 3) * detl; 
     62        wd1 = (hdu >> 15) ; 
     63        if (wd >= wd1)  mil = (i + 1) ; 
     64        else break ; 
     65    } 
     66 
     67    if (sil == -1 ) il = iln[mil] ; 
     68    else il = ilp[mil] ; 
     69 
     70    return (il) ; 
     71} 
     72 
     73static int block2l (int il, int detl) 
     74{ 
     75    int dlt; 
     76    int ril, wd2 ; 
     77    static int qm4[16] = { 
     78        0,      -20456, -12896, -8968, 
     79        -6288,  -4240,  -2584,  -1200, 
     80        20456,  12896,  8968,   6288, 
     81        4240,   2584,   1200,   0 
     82    }; 
     83 
     84    /* INVQAL */ 
     85    ril = il >> 2 ; 
     86    wd2 = qm4[ril] ; 
     87    dlt = (detl * wd2) >> 15 ; 
     88 
     89    return (dlt) ; 
     90} 
     91 
     92static int block3l (g722_enc_t *enc, int il) 
     93{ 
     94    int detl; 
     95    int ril, il4, wd, wd1, wd2, wd3, nbpl, depl ; 
     96    static int wl[8] = {-60, -30, 58, 172, 334, 538, 1198, 3042} ; 
     97    static int rl42[16] = {0, 7, 6, 5, 4, 3, 2, 1, 7, 6, 5, 4, 3, 2, 1, 0}; 
     98    static int ilb[32] = { 
     99        2048, 2093, 2139, 2186, 2233, 2282, 2332, 
     100        2383, 2435, 2489, 2543, 2599, 2656, 2714, 
     101        2774, 2834, 2896, 2960, 3025, 3091, 3158, 
     102        3228, 3298, 3371, 3444, 3520, 3597, 3676, 
     103        3756, 3838, 3922, 4008 
     104    }; 
     105 
     106    /* LOGSCL */ 
     107 
     108    ril = il >> 2 ; 
     109    il4 = rl42[ril] ; 
     110     
     111    wd = (enc->nbl * 32512) >> 15 ; 
     112    nbpl = wd + wl[il4] ; 
     113 
     114    if (nbpl <     0) nbpl = 0 ; 
     115    if (nbpl > 18432) nbpl = 18432 ; 
     116 
     117    /* SCALEL */ 
     118 
     119    wd1 =  (nbpl >> 6) & 31 ; 
     120    wd2 = nbpl >> 11 ; 
     121    if ((8 - wd2) < 0)    wd3 = ilb[wd1] << (wd2 - 8) ; 
     122    else   wd3 = ilb[wd1] >> (8 - wd2) ; 
     123    depl = wd3 << 2 ; 
     124 
     125    /* DELAYA */ 
     126    enc->nbl = nbpl ; 
     127 
     128    /* DELAYL */ 
     129    detl = depl ; 
     130 
     131#ifdef DEBUG_VERBOSE 
     132        printf ("BLOCK3L il=%4d, ril=%4d, il4=%4d, nbl=%4d, wd=%4d, nbpl=%4d\n", 
     133                 il, ril, il4, enc->nbl, wd, nbpl) ; 
     134        printf ("wd1=%4d, wd2=%4d, wd3=%4d, depl=%4d, detl=%4d\n", 
     135                wd1, wd2, wd3, depl, detl) ; 
     136#endif 
     137 
     138    return (detl) ; 
     139} 
     140 
     141static int block4l (g722_enc_t *enc, int dl) 
     142{ 
     143    int sl = enc->slow; 
     144    int i ; 
     145    int wd, wd1, wd2, wd3, wd4, wd5 /*, wd6 */; 
     146 
     147    enc->dlt[0] = dl; 
     148     
     149    /* RECONS */ 
     150 
     151    enc->rlt[0] = sl + enc->dlt[0] ; 
     152    SATURATE(enc->rlt[0], 32767, -32768); 
     153 
     154    /* PARREC */ 
     155 
     156    enc->plt[0] = enc->dlt[0] + enc->szl ; 
     157    SATURATE(enc->plt[0], 32767, -32768); 
     158 
     159    /* UPPOL2 */ 
     160 
     161    enc->sgl[0] = enc->plt[0] >> 15 ; 
     162    enc->sgl[1] = enc->plt[1] >> 15 ; 
     163    enc->sgl[2] = enc->plt[2] >> 15 ; 
     164 
     165    wd1 = enc->al[1] << 2; 
     166    SATURATE(wd1, 32767, -32768); 
     167 
     168    if ( enc->sgl[0] == enc->sgl[1] )  wd2 = - wd1 ; 
     169    else  wd2 = wd1 ; 
     170    if ( wd2 > 32767 ) wd2 = 32767; 
     171 
     172    wd2 = wd2 >> 7 ; 
     173 
     174    if ( enc->sgl[0] == enc->sgl[2] )  wd3 = 128 ; 
     175    else  wd3 = - 128 ; 
     176 
     177    wd4 = wd2 + wd3 ; 
     178    wd5 = (enc->al[2] * 32512) >> 15 ; 
     179 
     180    enc->apl[2] = wd4 + wd5 ; 
     181    SATURATE(enc->apl[2], 12288, -12288); 
     182 
     183    /* UPPOL1 */ 
     184 
     185    enc->sgl[0] = enc->plt[0] >> 15 ; 
     186    enc->sgl[1] = enc->plt[1] >> 15 ; 
     187 
     188    if ( enc->sgl[0] == enc->sgl[1] )  wd1 = 192 ; 
     189    else  wd1 = - 192 ; 
     190 
     191    wd2 = (enc->al[1] * 32640) >> 15 ; 
     192 
     193    enc->apl[1] = wd1 + wd2 ; 
     194    SATURATE(enc->apl[1], 32767, -32768); 
     195 
     196    wd3 = (15360 - enc->apl[2]) ; 
     197    SATURATE(wd3, 32767, -32768); 
     198 
     199    if ( enc->apl[1] >  wd3)  enc->apl[1] =  wd3 ; 
     200    if ( enc->apl[1] < -wd3)  enc->apl[1] = -wd3 ; 
     201 
     202    /* UPZERO */ 
     203 
     204    if ( enc->dlt[0] == 0 )  wd1 = 0 ; 
     205    else wd1 = 128 ; 
     206 
     207    enc->sgl[0] = enc->dlt[0] >> 15 ; 
     208 
     209    for ( i = 1; i < 7; i++ ) { 
     210        enc->sgl[i] = enc->dlt[i] >> 15 ; 
     211        if ( enc->sgl[i] == enc->sgl[0] )  wd2 = wd1 ; 
     212        else wd2 = - wd1 ; 
     213        wd3 = (enc->bl[i] * 32640) >> 15 ; 
     214        enc->bpl[i] = wd2 + wd3 ; 
     215        SATURATE(enc->bpl[i], 32767, -32768); 
     216    } 
     217 
     218    /* DELAYA */ 
     219 
     220    for ( i = 6; i > 0; i-- ) { 
     221        enc->dlt[i] = enc->dlt[i-1] ; 
     222        enc->bl[i]  = enc->bpl[i] ; 
     223    } 
     224 
     225    for ( i = 2; i > 0; i-- ) { 
     226        enc->rlt[i] = enc->rlt[i-1] ; 
     227        enc->plt[i] = enc->plt[i-1] ; 
     228        enc->al[i] = enc->apl[i] ; 
     229    } 
     230 
     231    /* FILTEP */ 
     232 
     233    wd1 = enc->rlt[1] + enc->rlt[1]; 
     234    SATURATE(wd1, 32767, -32768); 
     235    wd1 = ( enc->al[1] * wd1 ) >> 15 ; 
     236 
     237    wd2 = enc->rlt[2] + enc->rlt[2]; 
     238    SATURATE(wd2, 32767, -32768); 
     239    wd2 = ( enc->al[2] * wd2 ) >> 15 ; 
     240 
     241    enc->spl = wd1 + wd2 ; 
     242    SATURATE(enc->spl, 32767, -32768); 
     243 
     244    /* FILTEZ */ 
     245 
     246    enc->szl = 0 ; 
     247    for (i=6; i>0; i--) { 
     248        wd = enc->dlt[i] + enc->dlt[i]; 
     249        SATURATE(wd, 32767, -32768); 
     250        enc->szl += (enc->bl[i] * wd) >> 15 ; 
     251        SATURATE(enc->szl, 32767, -32768); 
     252    } 
     253 
     254    /* PREDIC */ 
     255 
     256    sl = enc->spl + enc->szl ; 
     257    SATURATE(sl, 32767, -32768); 
     258 
     259    return (sl) ; 
     260} 
     261 
     262static int block1h (int xh, int sh, int deth) 
     263{ 
     264    int ih ; 
     265 
     266    int eh, sih, mih, wd, wd1, hdu ; 
     267 
     268    static int ihn[3] = { 0, 1, 0 } ; 
     269    static int ihp[3] = { 0, 3, 2 } ; 
     270 
     271    /* SUBTRA */ 
     272 
     273    eh = xh - sh ; 
     274    SATURATE(eh, 32767, -32768); 
     275 
     276    /* QUANTH */ 
     277 
     278    sih = eh >> 15 ; 
     279    if (sih == 0 )  wd = eh ; 
     280    else wd = 32767 - eh & 32767 ; 
     281 
     282    hdu = (564 << 3) * deth; 
     283    wd1 = (hdu >> 15) ; 
     284    if (wd >= wd1)  mih = 2 ; 
     285    else mih = 1 ; 
     286 
     287    if (sih == -1 ) ih = ihn[mih] ; 
     288    else ih = ihp[mih] ; 
     289 
     290    return (ih) ; 
     291} 
     292 
     293static int block2h (int ih, int deth) 
     294{ 
     295    int dh ; 
     296    int wd2 ; 
     297    static int qm2[4] = {-7408, -1616, 7408, 1616}; 
     298     
     299    /* INVQAH */ 
     300 
     301    wd2 = qm2[ih] ; 
     302    dh = (deth * wd2) >> 15 ; 
     303 
     304    return (dh) ; 
     305} 
     306 
     307static int block3h (g722_enc_t *enc, int ih) 
     308{ 
     309    int deth ; 
     310    int ih2, wd, wd1, wd2, wd3, nbph, deph ; 
     311    static int wh[3] = {0, -214, 798} ; 
     312    static int rh2[4] = {2, 1, 2, 1} ; 
     313    static int ilb[32] = { 
     314        2048, 2093, 2139, 2186, 2233, 2282, 2332, 
     315        2383, 2435, 2489, 2543, 2599, 2656, 2714, 
     316        2774, 2834, 2896, 2960, 3025, 3091, 3158, 
     317        3228, 3298, 3371, 3444, 3520, 3597, 3676, 
     318        3756, 3838, 3922, 4008 
     319    }; 
     320 
     321    /* LOGSCH */ 
     322 
     323    ih2 = rh2[ih] ; 
     324    wd = (enc->nbh * 32512) >> 15 ; 
     325    nbph = wd + wh[ih2] ; 
     326 
     327    if (nbph <     0) nbph = 0 ; 
     328    if (nbph > 22528) nbph = 22528 ; 
     329 
     330    /* SCALEH */ 
     331 
     332    wd1 =  (nbph >> 6) & 31 ; 
     333    wd2 = nbph >> 11 ; 
     334    if ((10-wd2) < 0) wd3 = ilb[wd1] << (wd2-10) ; 
     335    else wd3 = ilb[wd1] >> (10-wd2) ; 
     336    deph = wd3 << 2 ; 
     337 
     338    /* DELAYA */ 
     339    enc->nbh = nbph ; 
     340    /* DELAYH */ 
     341    deth = deph ; 
     342 
     343    return (deth) ; 
     344} 
     345 
     346static int block4h (g722_enc_t *enc, int d) 
     347{ 
     348    int sh = enc->shigh; 
     349    int i ; 
     350    int wd, wd1, wd2, wd3, wd4, wd5 /*, wd6 */; 
     351 
     352    enc->dh[0] = d; 
     353 
     354    /* RECONS */ 
     355 
     356    enc->rh[0] = sh + enc->dh[0] ; 
     357    SATURATE(enc->rh[0], 32767, -32768); 
     358 
     359    /* PARREC */ 
     360 
     361    enc->ph[0] = enc->dh[0] + enc->szh ; 
     362    SATURATE(enc->ph[0], 32767, -32768); 
     363 
     364    /* UPPOL2 */ 
     365 
     366    enc->sgh[0] = enc->ph[0] >> 15 ; 
     367    enc->sgh[1] = enc->ph[1] >> 15 ; 
     368    enc->sgh[2] = enc->ph[2] >> 15 ; 
     369 
     370    wd1 = enc->ah[1] << 2; 
     371    SATURATE(wd1, 32767, -32768); 
     372 
     373    if ( enc->sgh[0] == enc->sgh[1] )  wd2 = - wd1 ; 
     374    else  wd2 = wd1 ; 
     375    if ( wd2 > 32767 ) wd2 = 32767; 
     376 
     377    wd2 = wd2 >> 7 ; 
     378 
     379    if ( enc->sgh[0] == enc->sgh[2] )  wd3 = 128 ; 
     380    else  wd3 = - 128 ; 
     381 
     382    wd4 = wd2 + wd3 ; 
     383    wd5 = (enc->ah[2] * 32512) >> 15 ; 
     384 
     385    enc->aph[2] = wd4 + wd5 ; 
     386    SATURATE(enc->aph[2], 12288, -12288); 
     387 
     388    /* UPPOL1 */ 
     389 
     390    enc->sgh[0] = enc->ph[0] >> 15 ; 
     391    enc->sgh[1] = enc->ph[1] >> 15 ; 
     392 
     393    if ( enc->sgh[0] == enc->sgh[1] )  wd1 = 192 ; 
     394    else wd1 = - 192 ; 
     395 
     396    wd2 = (enc->ah[1] * 32640) >> 15 ; 
     397 
     398    enc->aph[1] = wd1 + wd2 ; 
     399    SATURATE(enc->aph[1], 32767, -32768); 
     400 
     401    wd3 = (15360 - enc->aph[2]) ; 
     402    SATURATE(wd3, 32767, -32768); 
     403 
     404    if ( enc->aph[1] >  wd3)  enc->aph[1] =  wd3 ; 
     405    else if ( enc->aph[1] < -wd3)  enc->aph[1] = -wd3 ; 
     406 
     407    /* UPZERO */ 
     408 
     409    if ( enc->dh[0] == 0 )  wd1 = 0 ; 
     410    else wd1 = 128 ; 
     411 
     412    enc->sgh[0] = enc->dh[0] >> 15 ; 
     413 
     414    for ( i = 1; i < 7; i++ ) { 
     415        enc->sgh[i] = enc->dh[i] >> 15 ; 
     416        if ( enc->sgh[i] == enc->sgh[0] )  wd2 = wd1 ; 
     417        else wd2 = - wd1 ; 
     418        wd3 = (enc->bh[i] * 32640) >> 15 ; 
     419        enc->bph[i] = wd2 + wd3 ; 
     420        SATURATE(enc->bph[i], 32767, -32768); 
     421    } 
     422 
     423    /* DELAYA */ 
     424    for ( i = 6; i > 0; i-- ) { 
     425        enc->dh[i] = enc->dh[i-1] ; 
     426        enc->bh[i]  = enc->bph[i] ; 
     427    } 
     428 
     429    for ( i = 2; i > 0; i-- ) { 
     430        enc->rh[i] = enc->rh[i-1] ; 
     431        enc->ph[i] = enc->ph[i-1] ; 
     432        enc->ah[i] = enc->aph[i] ; 
     433    } 
     434 
     435    /* FILTEP */ 
     436 
     437    wd1 = enc->rh[1] + enc->rh[1]; 
     438    SATURATE(wd1, 32767, -32768); 
     439    wd1 = ( enc->ah[1] * wd1 ) >> 15 ; 
     440 
     441    wd2 = enc->rh[2] + enc->rh[2]; 
     442    SATURATE(wd2, 32767, -32768); 
     443    wd2 = ( enc->ah[2] * wd2 ) >> 15 ; 
     444 
     445    enc->sph = wd1 + wd2 ; 
     446    SATURATE(enc->sph, 32767, -32768); 
     447 
     448    /* FILTEZ */ 
     449 
     450    enc->szh = 0 ; 
     451    for (i=6; i>0; i--) { 
     452        wd = enc->dh[i] + enc->dh[i]; 
     453        SATURATE(wd, 32767, -32768); 
     454        enc->szh += (enc->bh[i] * wd) >> 15 ; 
     455        SATURATE(enc->szh, 32767, -32768); 
     456    } 
     457 
     458    /* PREDIC */ 
     459 
     460    sh = enc->sph + enc->szh ; 
     461    SATURATE(sh, 32767, -32768); 
     462 
     463    return (sh) ; 
     464} 
     465 
     466/* PROCESS PCM THROUGH THE QMF FILTER */ 
     467void tx_qmf(g722_enc_t *enc, int pcm1, int pcm2, int *lo, int *hi) 
     468{ 
     469    int sumodd, sumeven; 
     470    int i; 
     471 
     472    pj_memmove(&enc->x[2], enc->x, 22 * sizeof(enc->x[0])); 
     473    enc->x[1] = pcm1;  
     474    enc->x[0] = pcm2; 
     475 
     476    sumodd = 0; 
     477    for (i=1; i<24; i+=2) sumodd += enc->x[i] * g722_qmf_coeff[i]; 
     478 
     479    sumeven = 0; 
     480    for (i=0; i<24; i+=2) sumeven += enc->x[i] * g722_qmf_coeff[i]; 
     481 
     482    *lo  = (sumeven + sumodd) >> 13  ; 
     483    *hi = (sumeven - sumodd) >> 13  ; 
     484 
     485    SATURATE(*lo, 16383, -16384); 
     486    SATURATE(*hi, 16383, -16383); 
     487} 
     488 
     489 
     490PJ_DEF(pj_status_t) g722_enc_init(g722_enc_t *enc) 
     491{ 
     492    PJ_ASSERT_RETURN(enc, PJ_EINVAL); 
     493     
     494    pj_bzero(enc, sizeof(g722_enc_t)); 
     495 
     496    enc->detlow = 32; 
     497    enc->dethigh = 8; 
     498 
     499    return PJ_SUCCESS; 
     500} 
     501 
     502PJ_DEF(pj_status_t) g722_enc_encode( g722_enc_t *enc,  
     503                                     pj_int16_t in[],  
     504                                     pj_size_t nsamples, 
     505                                     void *out, 
     506                                     pj_size_t *out_size) 
     507{ 
     508    unsigned i; 
     509    int xlow, ilow, dlowt; 
     510    int xhigh, ihigh, dhigh; 
     511    pj_uint8_t *out_ = (pj_uint8_t*) out; 
     512 
     513    PJ_ASSERT_RETURN(enc && in && nsamples && out && out_size, PJ_EINVAL); 
     514    PJ_ASSERT_RETURN(nsamples % 2 == 0, PJ_EINVAL); 
     515    PJ_ASSERT_RETURN(*out_size >= (nsamples >> 1), PJ_ETOOSMALL); 
     516     
     517    for(i = 0; i < nsamples; i += 2) { 
     518        tx_qmf(enc, in[i], in[i+1], &xlow, &xhigh); 
     519 
     520        /* low band encoder */ 
     521        ilow = block1l (xlow, enc->slow, enc->detlow) ; 
     522        dlowt = block2l (ilow, enc->detlow) ; 
     523        enc->detlow = block3l (enc, ilow) ; 
     524        enc->slow = block4l (enc, dlowt) ; 
     525 
     526        /* high band encoder */ 
     527        ihigh = block1h (xhigh, enc->shigh, enc->dethigh) ; 
     528        dhigh = block2h (ihigh, enc->dethigh) ; 
     529        enc->dethigh = block3h (enc, ihigh) ; 
     530        enc->shigh = block4h (enc, dhigh) ; 
     531 
     532        /* bits mix low & high adpcm */ 
     533        out_[i/2] = (pj_uint8_t)((ihigh << 6) | ilow); 
     534    } 
     535 
     536    *out_size = nsamples >> 1; 
     537 
     538    return PJ_SUCCESS; 
     539} 
     540 
     541PJ_DEF(pj_status_t) g722_enc_deinit(g722_enc_t *enc) 
     542{ 
     543    pj_bzero(enc, sizeof(g722_enc_t)); 
     544 
     545    return PJ_SUCCESS; 
     546} 
     547 
     548#endif 
  • pjmedia/src/pjmedia-codec/g722/g722_enc.h

     
     1/* $Id$ */ 
     2/*  
     3 * Copyright (C)2003-2008 Benny Prijono <benny@prijono.org> 
     4 * 
     5 * This program is free software; you can redistribute it and/or modify 
     6 * it under the terms of the GNU General Public License as published by 
     7 * the Free Software Foundation; either version 2 of the License, or 
     8 * (at your option) any later version. 
     9 * 
     10 * This program is distributed in the hope that it will be useful, 
     11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
     12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
     13 * GNU General Public License for more details. 
     14 * 
     15 * You should have received a copy of the GNU General Public License 
     16 * along with this program; if not, write to the Free Software 
     17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  
     18 */ 
     19 
     20#ifndef __PJMEDIA_CODEC_G722_ENC_H__ 
     21#define __PJMEDIA_CODEC_G722_ENC_H__ 
     22 
     23#include <pjmedia-codec/types.h> 
     24 
     25/* Encoder state */ 
     26typedef struct g722_enc_t { 
     27    /* PCM low band */ 
     28    int slow; 
     29    int detlow; 
     30    int spl; 
     31    int szl; 
     32    int rlt  [3]; 
     33    int al   [3]; 
     34    int apl  [3]; 
     35    int plt  [3]; 
     36    int dlt  [7]; 
     37    int bl   [7]; 
     38    int bpl  [7]; 
     39    int sgl  [7]; 
     40    int nbl; 
     41 
     42    /* PCM high band*/ 
     43    int shigh; 
     44    int dethigh; 
     45    int sph; 
     46    int szh; 
     47    int rh   [3]; 
     48    int ah   [3]; 
     49    int aph  [3]; 
     50    int ph   [3]; 
     51    int dh   [7]; 
     52    int bh   [7]; 
     53    int bph  [7]; 
     54    int sgh  [7]; 
     55    int nbh; 
     56 
     57    /* QMF signal history */ 
     58    int x[24]; 
     59} g722_enc_t; 
     60 
     61 
     62PJ_DECL(pj_status_t) g722_enc_init(g722_enc_t *enc); 
     63 
     64PJ_DECL(pj_status_t) g722_enc_encode(g722_enc_t *enc,  
     65                                     pj_int16_t in[],  
     66                                     pj_size_t nsamples, 
     67                                     void *out, 
     68                                     pj_size_t *out_size); 
     69 
     70PJ_DECL(pj_status_t) g722_enc_deinit(g722_enc_t *enc); 
     71 
     72#endif /* __PJMEDIA_CODEC_G722_ENC_H__ */ 
     73 
  • pjmedia/src/pjmedia-codec/g722/g722_dec.c

     
     1#include <pjmedia/errno.h> 
     2#include <pj/assert.h> 
     3#include <pj/pool.h> 
     4 
     5#include "g722_dec.h" 
     6 
     7#if defined(PJMEDIA_HAS_G722_CODEC) && (PJMEDIA_HAS_G722_CODEC != 0) 
     8 
     9#define MODE 1 
     10 
     11#define SATURATE(v, max, min) \ 
     12    if (v>max) v = max; \ 
     13    else if (v<min) v = min 
     14 
     15extern int g722_qmf_coeff[24]; 
     16 
     17 
     18static int block2l (int il, int detl) 
     19{ 
     20    int dlt ; 
     21    int ril, wd2 ; 
     22    static int qm4[16] = { 
     23            0, -20456, -12896, -8968, 
     24        -6288,  -4240,  -2584, -1200, 
     25        20456,  12896,   8968,  6288, 
     26         4240,   2584,   1200,     0 
     27    }; 
     28 
     29    /* INVQAL */ 
     30    ril = il >> 2 ; 
     31    wd2 = qm4[ril] ; 
     32    dlt = (detl * wd2) >> 15 ; 
     33 
     34    return (dlt) ; 
     35} 
     36 
     37 
     38static int block3l (g722_dec_t *dec, int il) 
     39{ 
     40    int detl ; 
     41    int ril, il4, wd, wd1, wd2, wd3, nbpl, depl ; 
     42    static int wl[8] = {-60, -30, 58, 172, 334, 538, 1198, 3042}; 
     43    static int rl42[16] = {0, 7, 6, 5, 4, 3, 2, 1, 7, 6, 5, 4, 3, 2, 1, 0}; 
     44    static int ilb[32] = { 
     45        2048, 2093, 2139, 2186, 2233, 2282, 2332, 
     46        2383, 2435, 2489, 2543, 2599, 2656, 2714,  
     47        2774, 2834, 2896, 2960, 3025, 3091, 3158,  
     48        3228, 3298, 3371, 3444, 3520, 3597, 3676, 
     49        3756, 3838, 3922, 4008  
     50    }; 
     51 
     52    /* LOGSCL */ 
     53    ril = il >> 2 ; 
     54    il4 = rl42[ril] ; 
     55    wd = (dec->nbl * 32512) >> 15 ; 
     56    nbpl = wd + wl[il4] ; 
     57 
     58    if (nbpl <     0) nbpl = 0 ; 
     59    if (nbpl > 18432) nbpl = 18432 ; 
     60 
     61    /* SCALEL */ 
     62    wd1 =  (nbpl >> 6) & 31 ; 
     63    wd2 = nbpl >> 11 ; 
     64    if ((8 - wd2) < 0)   wd3 = ilb[wd1] << (wd2 - 8) ; 
     65    else wd3 = ilb[wd1] >> (8 - wd2) ; 
     66    depl = wd3 << 2 ; 
     67 
     68    /* DELAYA */ 
     69    dec->nbl = nbpl ; 
     70    /* DELAYL */ 
     71    detl = depl ; 
     72 
     73    return (detl) ; 
     74} 
     75 
     76 
     77static int block4l (g722_dec_t *dec, int dl) 
     78{ 
     79    int sl = dec->slow ; 
     80    int i ; 
     81    int wd, wd1, wd2, wd3, wd4, wd5/*, wd6 */; 
     82 
     83    dec->dlt[0] = dl; 
     84 
     85    /* RECONS */  
     86    dec->rlt[0] = sl + dec->dlt[0] ; 
     87    SATURATE(dec->rlt[0], 32767, -32768); 
     88 
     89    /* PARREC */ 
     90    dec->plt[0] = dec->dlt[0] + dec->szl ; 
     91    SATURATE(dec->plt[0], 32767, -32768); 
     92 
     93    /* UPPOL2 */ 
     94    dec->sgl[0] = dec->plt[0] >> 15 ; 
     95    dec->sgl[1] = dec->plt[1] >> 15 ; 
     96    dec->sgl[2] = dec->plt[2] >> 15 ; 
     97 
     98    wd1 = dec->al[1] << 2; 
     99    SATURATE(wd1, 32767, -32768); 
     100 
     101    if ( dec->sgl[0] == dec->sgl[1] )  wd2 = - wd1 ; 
     102    else  wd2 = wd1 ; 
     103    if (wd2 > 32767) wd2 = 32767; 
     104    wd2 = wd2 >> 7 ; 
     105 
     106    if ( dec->sgl[0] == dec->sgl[2] )  wd3 = 128 ;  
     107    else  wd3 = - 128 ; 
     108 
     109    wd4 = wd2 + wd3 ; 
     110    wd5 = (dec->al[2] * 32512) >> 15 ; 
     111 
     112    dec->apl[2] = wd4 + wd5 ; 
     113    SATURATE(dec->apl[2], 12288, -12288); 
     114     
     115    /* UPPOL1 */ 
     116    dec->sgl[0] = dec->plt[0] >> 15 ; 
     117    dec->sgl[1] = dec->plt[1] >> 15 ; 
     118 
     119    if ( dec->sgl[0] == dec->sgl[1] )  wd1 = 192 ; 
     120    else  wd1 = - 192 ; 
     121 
     122    wd2 = (dec->al[1] * 32640) >> 15 ; 
     123 
     124    dec->apl[1] = wd1 + wd2 ; 
     125    SATURATE(dec->apl[1], 32767, -32768); 
     126 
     127    wd3 = (15360 - dec->apl[2]) ; 
     128    SATURATE(wd3, 32767, -32768); 
     129    if ( dec->apl[1] >  wd3)  dec->apl[1] =  wd3 ; 
     130    if ( dec->apl[1] < -wd3)  dec->apl[1] = -wd3 ; 
     131 
     132    /* UPZERO */ 
     133    if ( dec->dlt[0] == 0 )  wd1 = 0 ; 
     134    else  wd1 = 128 ; 
     135 
     136    dec->sgl[0] = dec->dlt[0] >> 15 ; 
     137 
     138    for ( i = 1; i < 7; i++ ) { 
     139        dec->sgl[i] = dec->dlt[i] >> 15 ; 
     140        if ( dec->sgl[i] == dec->sgl[0] )  wd2 = wd1 ; 
     141        else  wd2 = - wd1 ; 
     142        wd3 = (dec->bl[i] * 32640) >> 15 ; 
     143        dec->bpl[i] = wd2 + wd3 ; 
     144        SATURATE(dec->bpl[i], 32767, -32768); 
     145    } 
     146 
     147    /* DELAYA */ 
     148    for ( i = 6; i > 0; i-- ) { 
     149        dec->dlt[i] = dec->dlt[i-1] ; 
     150        dec->bl[i]  = dec->bpl[i] ; 
     151    } 
     152 
     153    for ( i = 2; i > 0; i-- ) { 
     154        dec->rlt[i] = dec->rlt[i-1] ; 
     155        dec->plt[i] = dec->plt[i-1] ; 
     156        dec->al[i]  = dec->apl[i] ; 
     157    } 
     158 
     159    /* FILTEP */ 
     160    wd1 = dec->rlt[1] << 1; 
     161    SATURATE(wd1, 32767, -32768); 
     162    wd1 = ( dec->al[1] * wd1 ) >> 15 ; 
     163 
     164    wd2 = dec->rlt[2] << 1; 
     165    SATURATE(wd2, 32767, -32768); 
     166    wd2 = ( dec->al[2] * wd2 ) >> 15 ; 
     167 
     168    dec->spl = wd1 + wd2 ; 
     169    SATURATE(dec->spl, 32767, -32768); 
     170 
     171    /* FILTEZ */ 
     172    dec->szl = 0 ; 
     173    for (i=6; i>0; i--) { 
     174        wd = dec->dlt[i] << 1; 
     175        SATURATE(wd, 32767, -32768); 
     176        dec->szl += (dec->bl[i] * wd) >> 15 ; 
     177        SATURATE(dec->szl, 32767, -32768); 
     178    } 
     179 
     180    /* PREDIC */ 
     181    sl = dec->spl + dec->szl ; 
     182    SATURATE(sl, 32767, -32768); 
     183 
     184    return (sl) ; 
     185} 
     186 
     187static int block5l (int ilr, int sl, int detl, int mode) 
     188{ 
     189    int yl ; 
     190    int ril, dl, wd2 = 0; 
     191    static int qm4[16] = { 
     192            0, -20456, -12896,  -8968, 
     193        -6288,  -4240,  -2584,  -1200, 
     194        20456,  12896,   8968,   6288, 
     195         4240,   2584,   1200,      0 
     196    }; 
     197    static int qm5[32] = { 
     198          -280,   -280, -23352, -17560, 
     199        -14120, -11664,  -9752,  -8184, 
     200         -6864,  -5712,  -4696,  -3784, 
     201         -2960,  -2208,  -1520,   -880, 
     202         23352,  17560,  14120,  11664, 
     203          9752,   8184,   6864,   5712, 
     204          4696,   3784,   2960,   2208, 
     205          1520,    880,    280,   -280 
     206}; 
     207    static int qm6[64] = { 
     208        -136,   -136,   -136,   -136, 
     209        -24808, -21904, -19008, -16704, 
     210        -14984, -13512, -12280, -11192, 
     211        -10232, -9360,  -8576,  -7856, 
     212        -7192,  -6576,  -6000,  -5456, 
     213        -4944,  -4464,  -4008,  -3576, 
     214        -3168,  -2776,  -2400,  -2032, 
     215        -1688,  -1360,  -1040,  -728, 
     216        24808,  21904,  19008,  16704, 
     217        14984,  13512,  12280,  11192, 
     218        10232,  9360,   8576,   7856, 
     219        7192,   6576,   6000,   5456, 
     220        4944,   4464,   4008,   3576, 
     221        3168,   2776,   2400,   2032, 
     222        1688,   1360,   1040,   728, 
     223        432,    136,    -432,   -136 
     224    }; 
     225     
     226    /* INVQBL */ 
     227    if (mode == 1) { 
     228        ril = ilr ; 
     229        wd2 = qm6[ril] ; 
     230    } 
     231 
     232    if (mode == 2) { 
     233        ril = ilr >> 1 ; 
     234        wd2 = qm5[ril] ; 
     235    } 
     236 
     237    if (mode == 3) { 
     238        ril = ilr >> 2 ; 
     239        wd2 = qm4[ril] ; 
     240    } 
     241 
     242    dl = (detl * wd2 ) >> 15 ; 
     243 
     244    /* RECONS */ 
     245    yl = sl + dl ; 
     246    SATURATE(yl, 32767, -32768); 
     247 
     248    return (yl) ; 
     249} 
     250 
     251static int block6l (int yl) 
     252{ 
     253    int rl ; 
     254 
     255    rl = yl ; 
     256    SATURATE(rl, 16383, -16384); 
     257 
     258    return (rl) ; 
     259} 
     260 
     261static int block2h (int ih, int deth) 
     262{ 
     263    int dh ; 
     264    int wd2 ; 
     265    static int qm2[4] = {-7408, -1616, 7408, 1616} ; 
     266     
     267    /* INVQAH */ 
     268    wd2 = qm2[ih] ; 
     269    dh = (deth * wd2) >> 15 ; 
     270 
     271    return (dh) ; 
     272} 
     273 
     274static int block3h (g722_dec_t *dec, int ih) 
     275{ 
     276    int deth ; 
     277    int ih2, wd, wd1, wd2, wd3, nbph, deph ; 
     278    static int wh[3] = {0, -214, 798} ; 
     279    static int rh2[4] = {2, 1, 2, 1} ; 
     280    static int ilb[32] = { 
     281        2048, 2093, 2139, 2186, 2233, 2282, 2332, 
     282        2383, 2435, 2489, 2543, 2599, 2656, 2714,  
     283        2774, 2834, 2896, 2960, 3025, 3091, 3158,  
     284        3228, 3298, 3371, 3444, 3520, 3597, 3676, 
     285        3756, 3838, 3922, 4008 
     286    }; 
     287     
     288    /* LOGSCH */ 
     289    ih2 = rh2[ih] ; 
     290    wd = (dec->nbh * 32512) >> 15 ; 
     291    nbph = wd + wh[ih2] ; 
     292 
     293    if (nbph <     0) nbph = 0 ; 
     294    if (nbph > 22528) nbph = 22528 ; 
     295 
     296 
     297    /* SCALEH */ 
     298    wd1 =  (nbph >> 6) & 31 ; 
     299    wd2 = nbph >> 11 ; 
     300    if ((10 - wd2) < 0) wd3 = ilb[wd1] << (wd2 - 10) ; 
     301    else wd3 = ilb[wd1] >> (10 - wd2) ; 
     302    deph = wd3 << 2 ; 
     303 
     304    /* DELAYA */ 
     305    dec->nbh = nbph ; 
     306     
     307    /* DELAYH */ 
     308    deth = deph ; 
     309 
     310    return (deth) ; 
     311} 
     312 
     313static int block4h (g722_dec_t *dec, int d) 
     314{ 
     315    int sh = dec->shigh; 
     316    int i ; 
     317    int wd, wd1, wd2, wd3, wd4, wd5/*, wd6 */; 
     318    static int sph = 0 ; 
     319    static int szh = 0 ; 
     320    static int rh  [3] = { 0, 0, 0 } ; 
     321    static int ah   [3] = { 0, 0, 0 } ; 
     322    static int aph  [3] = { 0, 0, 0 } ; 
     323    static int ph  [3] = { 0, 0, 0 } ; 
     324    static int dh  [7] = { 0, 0, 0, 0, 0, 0, 0 } ; 
     325    static int bh   [7] = { 0, 0, 0, 0, 0, 0, 0 } ; 
     326    static int bph  [7] = { 0, 0, 0, 0, 0, 0, 0 } ; 
     327    static int sg   [7] = { 0, 0, 0, 0, 0, 0, 0 } ; 
     328 
     329 
     330    dec->dh[0] = d; 
     331 
     332    /* RECONS */  
     333    dec->rh[0] = sh + dec->dh[0] ; 
     334    SATURATE(dec->rh[0], 32767, -32768); 
     335 
     336    /* PARREC */ 
     337    dec->ph[0] = dec->dh[0] + dec->szh ; 
     338    SATURATE(dec->ph[0], 32767, -32768); 
     339 
     340    /* UPPOL2 */ 
     341    dec->sgh[0] = dec->ph[0] >> 15 ; 
     342    dec->sgh[1] = dec->ph[1] >> 15 ; 
     343    dec->sgh[2] = dec->ph[2] >> 15 ; 
     344 
     345    wd1 = dec->ah[1] << 2; 
     346    SATURATE(wd1, 32767, -32768); 
     347 
     348    if ( dec->sgh[0] == dec->sgh[1] )  wd2 = - wd1 ; 
     349    else  wd2 = wd1 ; 
     350    if (wd2 > 32767) wd2 = 32767; 
     351 
     352    wd2 = wd2 >> 7 ; 
     353 
     354    if ( dec->sgh[0] == dec->sgh[2] )  wd3 = 128 ;  
     355    else  wd3 = - 128 ; 
     356 
     357    wd4 = wd2 + wd3 ; 
     358    wd5 = (dec->ah[2] * 32512) >> 15 ; 
     359 
     360    dec->aph[2] = wd4 + wd5 ; 
     361    SATURATE(dec->aph[2], 12288, -12288); 
     362     
     363    /* UPPOL1 */ 
     364    dec->sgh[0] = dec->ph[0] >> 15 ; 
     365    dec->sgh[1] = dec->ph[1] >> 15 ; 
     366 
     367    if ( dec->sgh[0] == dec->sgh[1] )  wd1 = 192 ; 
     368    else  wd1 = - 192 ; 
     369 
     370    wd2 = (dec->ah[1] * 32640) >> 15 ; 
     371 
     372    dec->aph[1] = wd1 + wd2 ; 
     373    SATURATE(dec->aph[1], 32767, -32768); 
     374    //dec->aph[2]? 
     375    //if (aph[2] > 32767) aph[2] = 32767; 
     376    //if (aph[2] < -32768) aph[2] = -32768; 
     377 
     378    wd3 = (15360 - dec->aph[2]) ; 
     379    SATURATE(wd3, 32767, -32768); 
     380    if ( dec->aph[1] >  wd3)  dec->aph[1] =  wd3 ; 
     381    if ( dec->aph[1] < -wd3)  dec->aph[1] = -wd3 ; 
     382 
     383    /* UPZERO */ 
     384    if ( dec->dh[0] == 0 )  wd1 = 0 ; 
     385    if ( dec->dh[0] != 0 )  wd1 = 128 ; 
     386 
     387    dec->sgh[0] = dec->dh[0] >> 15 ; 
     388 
     389    for ( i = 1; i < 7; i++ ) { 
     390        dec->sgh[i] = dec->dh[i] >> 15 ; 
     391        if ( dec->sgh[i] == dec->sgh[0] )  wd2 = wd1 ; 
     392        else wd2 = - wd1 ; 
     393        wd3 = (dec->bh[i] * 32640) >> 15 ; 
     394        dec->bph[i] = wd2 + wd3 ; 
     395    } 
     396  
     397    /* DELAYA */ 
     398    for ( i = 6; i > 0; i-- ) { 
     399        dec->dh[i] = dec->dh[i-1] ; 
     400        dec->bh[i] = dec->bph[i] ; 
     401    } 
     402 
     403    for ( i = 2; i > 0; i-- ) { 
     404        dec->rh[i] = dec->rh[i-1] ; 
     405        dec->ph[i] = dec->ph[i-1] ; 
     406        dec->ah[i] = dec->aph[i] ; 
     407    } 
     408 
     409    /* FILTEP */ 
     410    wd1 = dec->rh[1] << 1 ; 
     411    SATURATE(wd1, 32767, -32768); 
     412    wd1 = ( dec->ah[1] * wd1 ) >> 15 ; 
     413 
     414    wd2 = dec->rh[2] << 1; 
     415    SATURATE(wd2, 32767, -32768); 
     416    wd2 = ( dec->ah[2] * wd2 ) >> 15 ; 
     417 
     418    dec->sph = wd1 + wd2 ; 
     419    SATURATE(dec->sph, 32767, -32768); 
     420 
     421    /* FILTEZ */ 
     422    dec->szh = 0 ; 
     423    for (i=6; i>0; i--) { 
     424        wd = dec->dh[i] << 1; 
     425        SATURATE(wd, 32767, -32768); 
     426        dec->szh += (dec->bh[i] * wd) >> 15 ; 
     427        SATURATE(dec->szh, 32767, -32768); 
     428    } 
     429 
     430    /* PREDIC */ 
     431    sh = dec->sph + dec->szh ; 
     432    SATURATE(sh, 32767, -32768); 
     433 
     434    return (sh) ; 
     435} 
     436 
     437static int block5h (int dh, int sh) 
     438{ 
     439    int rh ; 
     440 
     441    rh = dh + sh; 
     442    SATURATE(rh, 16383, -16384); 
     443 
     444    return (rh) ; 
     445} 
     446 
     447void rx_qmf(g722_dec_t *dec, int rl, int rh, int *xout1, int *xout2) 
     448{ 
     449    int i; 
     450 
     451    pj_memmove(&dec->xd[1], dec->xd, 11*sizeof(dec->xd[0])); 
     452    pj_memmove(&dec->xs[1], dec->xs, 11*sizeof(dec->xs[0])); 
     453 
     454    /* RECA */ 
     455    dec->xd[0] = rl - rh ; 
     456    if (dec->xd[0] > 16383) dec->xd[0] = 16383; 
     457    else if (dec->xd[0] < -16384) dec->xd[0] = -16384; 
     458     
     459    /* RECB */ 
     460    dec->xs[0] = rl + rh ; 
     461    if (dec->xs[0] > 16383) dec->xs[0] = 16383; 
     462    else if (dec->xs[0] < -16384) dec->xs[0] = -16384; 
     463     
     464    /* ACCUMC */ 
     465    *xout1 = 0; 
     466    for (i=0; i<12; ++i) *xout1 += dec->xd[i] * g722_qmf_coeff[2*i]; 
     467    *xout1 = *xout1 >> 12 ; 
     468    if (*xout1 >  16383)  *xout1 =  16383 ; 
     469    else if (*xout1 < -16384)  *xout1 = -16384 ; 
     470     
     471    /* ACCUMD */ 
     472    *xout2 = 0; 
     473    for (i=0; i<12; ++i) *xout2 += dec->xs[i] * g722_qmf_coeff[2*i+1]; 
     474    *xout2  = *xout2  >> 12 ; 
     475    if (*xout2  >  16383)  *xout2  =  16383 ; 
     476    else if (*xout2  < -16384)  *xout2  = -16384 ; 
     477} 
     478 
     479 
     480PJ_DEF(pj_status_t) g722_dec_init(g722_dec_t *dec) 
     481{ 
     482    PJ_ASSERT_RETURN(dec, PJ_EINVAL); 
     483 
     484    pj_bzero(dec, sizeof(g722_dec_t)); 
     485 
     486    dec->detlow = 32; 
     487    dec->dethigh = 8; 
     488 
     489    return PJ_SUCCESS; 
     490} 
     491 
     492PJ_DEF(pj_status_t) g722_dec_decode( g722_dec_t *dec,  
     493                                    void *in,  
     494                                    pj_size_t in_size, 
     495                                    pj_int16_t out[], 
     496                                    pj_size_t *nsamples) 
     497{ 
     498    unsigned i; 
     499    int ilowr, ylow, rlow, dlowt; 
     500    int ihigh, rhigh, dhigh; 
     501    int pcm1, pcm2; 
     502    pj_uint8_t *in_ = (pj_uint8_t*) in; 
     503 
     504    PJ_ASSERT_RETURN(dec && in && in_size && out && nsamples, PJ_EINVAL); 
     505    PJ_ASSERT_RETURN(*nsamples >= (in_size << 1), PJ_ETOOSMALL); 
     506 
     507    for(i = 0; i < in_size; ++i) { 
     508        ilowr = in_[i] & 63; 
     509        ihigh = (in_[i] >> 6) & 3; 
     510 
     511        /* low band decoder */ 
     512        ylow = block5l (ilowr, dec->slow, dec->detlow, MODE) ;   
     513        rlow = block6l (ylow) ; 
     514        dlowt = block2l (ilowr, dec->detlow) ; 
     515        dec->detlow = block3l (dec, ilowr) ; 
     516        dec->slow = block4l (dec, dlowt) ; 
     517        /* rlow <= output low band pcm */ 
     518 
     519        /* high band decoder */ 
     520        dhigh = block2h (ihigh, dec->dethigh) ; 
     521        rhigh = block5h (dhigh, dec->shigh) ; 
     522        dec->dethigh = block3h (dec, ihigh) ; 
     523        dec->shigh = block4h (dec, dhigh) ; 
     524        /* rhigh <= output high band pcm */ 
     525 
     526        rx_qmf(dec, rlow, rhigh, &pcm1, &pcm2); 
     527        out[i*2] = (pj_int16_t)pcm1; 
     528        out[i*2+1] = (pj_int16_t)pcm2; 
     529    } 
     530 
     531    *nsamples = in_size << 1; 
     532 
     533    return PJ_SUCCESS; 
     534} 
     535 
     536PJ_DEF(pj_status_t) g722_dec_deinit(g722_dec_t *dec) 
     537{ 
     538    pj_bzero(dec, sizeof(g722_dec_t)); 
     539 
     540    return PJ_SUCCESS; 
     541} 
     542 
     543#endif