00001 /* 00002 * SpanDSP - a series of DSP components for telephony 00003 * 00004 * dc_restore.h - General telephony routines to restore the zero D.C. 00005 * level to audio which has a D.C. bias. 00006 * 00007 * Written by Steve Underwood <steveu@coppice.org> 00008 * 00009 * Copyright (C) 2001 Steve Underwood 00010 * 00011 * All rights reserved. 00012 * 00013 * This program is free software; you can redistribute it and/or modify 00014 * it under the terms of the GNU General Public License version 2, as 00015 * published by the Free Software Foundation. 00016 * 00017 * This program is distributed in the hope that it will be useful, 00018 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00019 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00020 * GNU General Public License for more details. 00021 * 00022 * You should have received a copy of the GNU General Public License 00023 * along with this program; if not, write to the Free Software 00024 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00025 * 00026 * $Id: dc_restore.h,v 1.19 2008/03/03 15:29:40 steveu Exp $ 00027 */ 00028 00029 /*! \file */ 00030 00031 #if !defined(_SPANDSP_DC_RESTORE_H_) 00032 #define _SPANDSP_DC_RESTORE_H_ 00033 00034 /*! \page dc_restore_page Removing DC bias from a signal 00035 00036 \section dc_restore_page_sec_1 What does it do? 00037 00038 Telecoms signals often contain considerable DC, but DC upsets a lot of signal 00039 processing functions. Placing a zero DC restorer at the front of the processing 00040 chain can often simplify the downstream processing. 00041 00042 \section dc_restore_page_sec_2 How does it work? 00043 00044 The DC restorer uses a leaky integrator to provide a long-ish term estimate of 00045 the DC bias in the signal. A 32 bit estimate is used for the 16 bit audio, so 00046 the noise introduced by the estimation can be keep in the lower bits, and the 16 00047 bit DC value, which is subtracted from the signal, is fairly clean. The 00048 following code fragment shows the algorithm used. dc_bias is a 32 bit integer, 00049 while the sample and the resulting clean_sample are 16 bit integers. 00050 00051 dc_bias += ((((int32_t) sample << 15) - dc_bias) >> 14); 00052 clean_sample = sample - (dc_bias >> 15); 00053 */ 00054 00055 /*! 00056 Zero DC restoration descriptor. This defines the working state for a single 00057 instance of DC content filter. 00058 */ 00059 typedef struct 00060 { 00061 int32_t state; 00062 } dc_restore_state_t; 00063 00064 #if defined(__cplusplus) 00065 extern "C" 00066 { 00067 #endif 00068 00069 static __inline__ void dc_restore_init(dc_restore_state_t *dc) 00070 { 00071 dc->state = 0; 00072 } 00073 /*- End of function --------------------------------------------------------*/ 00074 00075 static __inline__ int16_t dc_restore(dc_restore_state_t *dc, int16_t sample) 00076 { 00077 dc->state += ((((int32_t) sample << 15) - dc->state) >> 14); 00078 return (int16_t) (sample - (dc->state >> 15)); 00079 } 00080 /*- End of function --------------------------------------------------------*/ 00081 00082 static __inline__ int16_t dc_restore_estimate(dc_restore_state_t *dc) 00083 { 00084 return (int16_t) (dc->state >> 15); 00085 } 00086 /*- End of function --------------------------------------------------------*/ 00087 00088 #ifdef _MSC_VER 00089 __inline float rintf(float flt) 00090 { 00091 _asm 00092 { fld flt 00093 frndint 00094 } 00095 } 00096 /*- End of function --------------------------------------------------------*/ 00097 00098 __inline double rint(double dbl) 00099 { 00100 __asm 00101 { 00102 fld dbl 00103 frndint 00104 } 00105 } 00106 /*- End of function --------------------------------------------------------*/ 00107 00108 __inline long lrintf(float flt) 00109 { 00110 long retval; 00111 00112 _asm 00113 { fld flt 00114 fistp retval 00115 } 00116 return retval; 00117 } 00118 /*- End of function --------------------------------------------------------*/ 00119 #endif 00120 00121 static __inline__ int16_t saturate(int32_t amp) 00122 { 00123 int16_t amp16; 00124 00125 /* Hopefully this is optimised for the common case - not clipping */ 00126 amp16 = (int16_t) amp; 00127 if (amp == amp16) 00128 return amp16; 00129 if (amp > INT16_MAX) 00130 return INT16_MAX; 00131 return INT16_MIN; 00132 } 00133 /*- End of function --------------------------------------------------------*/ 00134 00135 static __inline__ int16_t fsaturatef(float famp) 00136 { 00137 if (famp > 32767.0) 00138 return INT16_MAX; 00139 if (famp < -32768.0) 00140 return INT16_MIN; 00141 return (int16_t) rintf(famp); 00142 } 00143 /*- End of function --------------------------------------------------------*/ 00144 00145 static __inline__ int16_t fsaturate(double damp) 00146 { 00147 if (damp > 32767.0) 00148 return INT16_MAX; 00149 if (damp < -32768.0) 00150 return INT16_MIN; 00151 return (int16_t) rint(damp); 00152 } 00153 /*- End of function --------------------------------------------------------*/ 00154 00155 #if defined(__cplusplus) 00156 } 00157 #endif 00158 00159 #endif 00160 /*- End of file ------------------------------------------------------------*/