⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cvsd.c

📁 linux下录音程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *      CVSD (Continuously Variable Slope Delta modulation) *      conversion routines * *      The CVSD format is described in the MIL Std 188 113, which is *      available from http://bbs.itsi.disa.mil:5580/T3564 * *	Copyright (C) 1996   *      Thomas Sailer (sailer@ife.ee.ethz.ch) (HB9JNX/AE4WA) *      Swiss Federal Institute of Technology, Electronics Lab * *	This program is free software; you can redistribute it and/or modify *	it under the terms of the GNU General Public License as published by *	the Free Software Foundation; either version 2 of the License, or *	(at your option) any later version. * *	This program is distributed in the hope that it will be useful, *	but WITHOUT ANY WARRANTY; without even the implied warranty of *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *	GNU General Public License for more details. * *	You should have received a copy of the GNU General Public License *	along with this program; if not, write to the Free Software *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * * Change History: * * June 1, 1998 - Chris Bagwell (cbagwell@sprynet.com) *   Fixed compile warnings reported by Kjetil Torgrim Homme *   <kjetilho@ifi.uio.no> * * *//* ---------------------------------------------------------------------- */#include <limits.h>#include <math.h>#include <string.h>#include <time.h>#ifndef SEEK_SET#define SEEK_SET 0		/* nasty nasty */#endif /* SEEK_SET */#include "cvsdfilt.h"#include "st.h"#include "libst.h"/* ---------------------------------------------------------------------- */#ifdef NEED_MEMMOVE#define memmove(dest,src,len) (bcopy((src),(dest),(len)))#endif/* ---------------------------------------------------------------------- *//* * private data structures */struct cvsd_common_state {	unsigned overload;	float mla_int;	float mla_tc0;	float mla_tc1;	unsigned phase;	unsigned phase_inc;	float v_min, v_max;};struct cvsd_decode_state {	float output_filter[DEC_FILTERLEN];};struct cvsd_encode_state {	float recon_int;	float input_filter[ENC_FILTERLEN];};struct cvsdpriv {	struct cvsd_common_state com;	union {		struct cvsd_decode_state dec;		struct cvsd_encode_state enc;	} c;	struct {		unsigned shreg;		unsigned mask;		unsigned cnt;	} bit;	unsigned bytes_written;	unsigned cvsd_rate;	char swapbits;};/* ---------------------------------------------------------------------- */float float_conv(fp1, fp2, n)float *fp1;float *fp2;int n;{	float res = 0;	for(; n > 0; n--)		res += (*fp1++) * (*fp2++);	return res;}/* ---------------------------------------------------------------------- *//* * some remarks about the implementation of the CVSD decoder * the principal integrator is integrated into the output filter * to achieve this, the coefficients of the output filter are multiplied * with (1/(1-1/z)) in the initialisation code. * the output filter must have a sharp zero at f=0 (i.e. the sum of the * filter parameters must be zero). This prevents an accumulation of * DC voltage at the principal integration. *//* ---------------------------------------------------------------------- */static void cvsdstartcommon(ft)ft_t ft;{	struct cvsdpriv *p = (struct cvsdpriv *) ft->priv;		/* sanity check */	if (sizeof(struct cvsdpriv) > PRIVSIZE)		fail("struct cvsdpriv is too big (%d); change PRIVSIZE in st.h and recompile sox", sizeof(struct cvsdpriv));	p->cvsd_rate = (ft->info.rate <= 24000) ? 16000 : 32000;	ft->info.rate = 8000;	ft->info.channels = 1;	ft->info.size = WORD; /* make output format default to words */	ft->info.style = SIGN2;	p->swapbits = ft->swap;	ft->swap = 0;	/*	 * initialize the decoder	 */	p->com.overload = 0x5;	p->com.mla_int = 0;	/*	 * timeconst = (1/e)^(200 / SR) = exp(-200/SR)	 * SR is the sampling rate	 */	p->com.mla_tc0 = exp((-200.0)/((float)(p->cvsd_rate)));	/*	 * phase_inc = 32000 / SR	 */	p->com.phase_inc = 32000 / p->cvsd_rate;	/*	 * initialize bit shift register	 */	p->bit.shreg = p->bit.cnt = 0;	p->bit.mask = p->swapbits ? 0x80 : 1;	/*	 * count the bytes written	 */	p->bytes_written = 0;	p->com.v_min = 1;	p->com.v_max = -1;	report("cvsd: bit rate %dbit/s, bits from %s\n", p->cvsd_rate,	       p->swapbits ? "msb to lsb" : "lsb to msb");}/* ---------------------------------------------------------------------- */void cvsdstartread(ft) ft_t ft;{	struct cvsdpriv *p = (struct cvsdpriv *) ft->priv;	float *fp1;	int i;		cvsdstartcommon(ft);	p->com.mla_tc1 = 0.1 * (1 - p->com.mla_tc0);	p->com.phase = 0;	/*	 * initialize the output filter coeffs (i.e. multiply	 * the coeffs with (1/(1-1/z)) to achieve integration	 * this is now done in the filter parameter generation utility	 */	/*	 * zero the filter 	 */	for(fp1 = p->c.dec.output_filter, i = DEC_FILTERLEN; i > 0; i--)		*fp1++ = 0;}/* ---------------------------------------------------------------------- */void cvsdstartwrite(ft) ft_t ft;{	struct cvsdpriv *p = (struct cvsdpriv *) ft->priv;	float *fp1;	int i;	cvsdstartcommon(ft);	p->com.mla_tc1 = 0.1 * (1 - p->com.mla_tc0);	p->com.phase = 4;	/*	 * zero the filter 	 */	for(fp1 = p->c.enc.input_filter, i = ENC_FILTERLEN; i > 0; i--)		*fp1++ = 0;	p->c.enc.recon_int = 0;}/* ---------------------------------------------------------------------- */voidcvsdstopwrite(ft)ft_t ft;{	struct cvsdpriv *p = (struct cvsdpriv *) ft->priv;	if (p->bit.cnt) {		putc(p->bit.shreg, ft->fp);		p->bytes_written++;	}	report("cvsd: min slope %f, max slope %f\n", 	       p->com.v_min, p->com.v_max);	}/* ---------------------------------------------------------------------- */voidcvsdstopread(ft)ft_t ft;{	struct cvsdpriv *p = (struct cvsdpriv *) ft->priv;	report("cvsd: min value %f, max value %f\n", 	       p->com.v_min, p->com.v_max);}/* ---------------------------------------------------------------------- */#undef DEBUG#ifdef DEBUGstatic struct {	FILE *f1;	FILE *f2;	int cnt} dbg = { NULL, NULL, 0 };#endifLONG cvsdread(ft, buf, nsamp) ft_t ft;LONG *buf, nsamp;{	struct cvsdpriv *p = (struct cvsdpriv *) ft->priv;	int done = 0;	float oval;	#ifdef DEBUG	if (!dbg.f1) {		if (!(dbg.f1 = fopen("dbg1", "w")))			fail("debugging");		fprintf(dbg.f1, "\"input\"\n");	}	if (!dbg.f2) {		if (!(dbg.f2 = fopen("dbg2", "w")))			fail("debugging");		fprintf(dbg.f2, "\"recon\"\n");	}#endif	while (done < nsamp) {		if (!p->bit.cnt) {			p->bit.shreg = getc(ft->fp);			if (feof(ft->fp))				return done;			p->bit.cnt = 8;			p->bit.mask = p->swapbits ? 0x80 : 1;		}		/*		 * handle one bit		 */		p->bit.cnt--;		p->com.overload = ((p->com.overload << 1) | 				   (!!(p->bit.shreg & p->bit.mask))) & 7;		if (p->swapbits)			p->bit.mask >>= 1;		else			p->bit.mask <<= 1;		p->com.mla_int *= p->com.mla_tc0;		if ((p->com.overload == 0) || (p->com.overload == 7))			p->com.mla_int += p->com.mla_tc1;		memmove(p->c.dec.output_filter+1, p->c.dec.output_filter,			sizeof(p->c.dec.output_filter)-sizeof(float));		if (p->com.overload & 1)			p->c.dec.output_filter[0] = p->com.mla_int;		else			p->c.dec.output_filter[0] = -p->com.mla_int;		/*		 * check if the next output is due		 */		p->com.phase += p->com.phase_inc;		if (p->com.phase >= 4) {			oval = float_conv(p->c.dec.output_filter, 					  (p->cvsd_rate < 24000) ? 					  dec_filter_16 : dec_filter_32, 					  DEC_FILTERLEN);#ifdef DEBUG			fprintf(dbg.f1, "%f %f\n", (double)dbg.cnt, 				(double)p->com.mla_int);			fprintf(dbg.f2, "%f %f\n", (double)dbg.cnt, 				(double)oval);			dbg.cnt++;#endif					if (oval > p->com.v_max)				p->com.v_max = oval;			if (oval < p->com.v_min)				p->com.v_min = oval;			*buf++ = (oval * ((float)LONG_MAX));			done++;		}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -