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

📄 isdn_audio.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		s->a = 0;		s->d = 5;		s->word = 0;		s->nleft = 0;		s->nbits = nbits;	}	return s;}dtmf_state *isdn_audio_dtmf_init(dtmf_state * s){	if (!s)		s = (dtmf_state *) kmalloc(sizeof(dtmf_state), GFP_ATOMIC);	if (s) {		s->idx = 0;		s->last = ' ';	}	return s;}/* * Decompression of adpcm data to a/u-law * */intisdn_audio_adpcm2xlaw(adpcm_state * s, int fmt, unsigned char *in,		      unsigned char *out, int len){	int a = s->a;	int d = s->d;	int nbits = s->nbits;	int olen = 0;	while (len) {		int e = isdn_audio_get_bits(s, &in, &len);		int sign;		if (nbits == 4 && e == 0)			d = 4;		sign = (e >> (nbits - 1)) ? -1 : 1;		e &= bitmask[nbits - 1];		a += sign * ((e << 1) + 1) * d >> 1;		if (d & 1)			a++;		if (fmt)			*out++ = isdn_audio_ulaw_to_alaw[					 isdn_audio_linear2ulaw(a << 2)];		else			*out++ = isdn_audio_linear2ulaw(a << 2);		olen++;		d = (d * Mx[nbits - 2][e] + 0x2000) >> 14;		if (d < 5)			d = 5;	}	s->a = a;	s->d = d;	return olen;}intisdn_audio_2adpcm_flush(adpcm_state * s, unsigned char *out){	int olen = 0;	if (s->nleft)		isdn_audio_put_bits(0, 8 - s->nleft, s, &out, &olen);	return olen;}intisdn_audio_xlaw2adpcm(adpcm_state * s, int fmt, unsigned char *in,		      unsigned char *out, int len){	int a = s->a;	int d = s->d;	int nbits = s->nbits;	int olen = 0;	while (len--) {		int e = 0,		 nmax = 1 << (nbits - 1);		int sign,		 delta;		if (fmt)			delta = (isdn_audio_alaw_to_s16[*in++] >> 2) - a;		else			delta = (isdn_audio_ulaw_to_s16[*in++] >> 2) - a;		if (delta < 0) {			e = nmax;			delta = -delta;		}		while (--nmax && delta > d) {			delta -= d;			e++;		}		if (nbits == 4 && ((e & 0x0f) == 0))			e = 8;		isdn_audio_put_bits(e, nbits, s, &out, &olen);		sign = (e >> (nbits - 1)) ? -1 : 1;		e &= bitmask[nbits - 1];		a += sign * ((e << 1) + 1) * d >> 1;		if (d & 1)			a++;		d = (d * Mx[nbits - 2][e] + 0x2000) >> 14;		if (d < 5)			d = 5;	}	s->a = a;	s->d = d;	return olen;}/* * Goertzel algorithm. * See http://ptolemy.eecs.berkeley.edu/~pino/Ptolemy/papers/96/dtmf_ict/ * for more info. * Result is stored into an sk_buff and queued up for later * evaluation. */static voidisdn_audio_goertzel(int *sample, modem_info * info){	int sk,	 sk1,	 sk2;	int k,	 n;	struct sk_buff *skb;	int *result;	skb = dev_alloc_skb(sizeof(int) * NCOEFF);	if (!skb) {		printk(KERN_WARNING		  "isdn_audio: Could not alloc DTMF result for ttyI%d\n",		       info->line);		return;	}	result = (int *) skb_put(skb, sizeof(int) * NCOEFF);	for (k = 0; k < NCOEFF; k++) {		sk = sk1 = sk2 = 0;		for (n = 0; n < DTMF_NPOINTS; n++) {			sk = sample[n] + ((cos2pik[k] * sk1) >> 15) - sk2;			sk2 = sk1;			sk1 = sk;		}		result[k] =		    ((sk * sk) >> AMP_BITS) -		    ((((cos2pik[k] * sk) >> 15) * sk2) >> AMP_BITS) +		    ((sk2 * sk2) >> AMP_BITS);	}	skb_queue_tail(&info->dtmf_queue, skb);	isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);}voidisdn_audio_eval_dtmf(modem_info * info){	struct sk_buff *skb;	int *result;	dtmf_state *s;	int silence;	int i;	int di;	int ch;	unsigned long flags;	int grp[2];	char what;	char *p;	while ((skb = skb_dequeue(&info->dtmf_queue))) {		result = (int *) skb->data;		s = info->dtmf_state;		grp[LOGRP] = grp[HIGRP] = -2;		silence = 0;		for (i = 0; i < 8; i++) {			if ((result[dtmf_tones[i].k] > DTMF_TRESH) &&			    (result[dtmf_tones[i].k2] < H2_TRESH))				grp[dtmf_tones[i].grp] = (grp[dtmf_tones[i].grp] == -2) ? i : -1;			else if ((result[dtmf_tones[i].k] < SILENCE_TRESH) &&			      (result[dtmf_tones[i].k2] < SILENCE_TRESH))				silence++;		}		if (silence == 8)			what = ' ';		else {			if ((grp[LOGRP] >= 0) && (grp[HIGRP] >= 0)) {				what = dtmf_matrix[grp[LOGRP]][grp[HIGRP] - 4];				if (s->last != ' ' && s->last != '.')					s->last = what;	/* min. 1 non-DTMF between DTMF */			} else				what = '.';		}		if ((what != s->last) && (what != ' ') && (what != '.')) {			printk(KERN_DEBUG "dtmf: tt='%c'\n", what);			p = skb->data;			*p++ = 0x10;			*p = what;			skb_trim(skb, 2);			if (skb_headroom(skb) < sizeof(isdn_audio_skb)) {				printk(KERN_WARNING				       "isdn_audio: insufficient skb_headroom, dropping\n");				kfree_skb(skb);				return;			}			ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;			ISDN_AUDIO_SKB_LOCK(skb) = 0;			save_flags(flags);			cli();			di = info->isdn_driver;			ch = info->isdn_channel;			__skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);			dev->drv[di]->rcvcount[ch] += 2;			restore_flags(flags);			/* Schedule dequeuing */			if ((dev->modempoll) && (info->rcvsched))				isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);			wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);		} else			kfree_skb(skb);		s->last = what;	}}/* * Decode DTMF tones, queue result in separate sk_buf for * later examination. * Parameters: *   s    = pointer to state-struct. *   buf  = input audio data *   len  = size of audio data. *   fmt  = audio data format (0 = ulaw, 1 = alaw) */voidisdn_audio_calc_dtmf(modem_info * info, unsigned char *buf, int len, int fmt){	dtmf_state *s = info->dtmf_state;	int i;	int c;	while (len) {		c = MIN(len, (DTMF_NPOINTS - s->idx));		if (c <= 0)			break;		for (i = 0; i < c; i++) {			if (fmt)				s->buf[s->idx++] =				    isdn_audio_alaw_to_s16[*buf++] >> (15 - AMP_BITS);			else				s->buf[s->idx++] =				    isdn_audio_ulaw_to_s16[*buf++] >> (15 - AMP_BITS);		}		if (s->idx == DTMF_NPOINTS) {			isdn_audio_goertzel(s->buf, info);			s->idx = 0;		}		len -= c;	}}silence_state *isdn_audio_silence_init(silence_state * s){	if (!s)		s = (silence_state *) kmalloc(sizeof(silence_state), GFP_ATOMIC);	if (s) {		s->idx = 0;		s->state = 0;	}	return s;}voidisdn_audio_calc_silence(modem_info * info, unsigned char *buf, int len, int fmt){	silence_state *s = info->silence_state;	int i;	signed char c;	if (!info->emu.vpar[1]) return;	for (i = 0; i < len; i++) {		if (fmt)		    c = isdn_audio_alaw_to_ulaw[*buf++];			else		    c = *buf++;		if (c > 0) c -= 128;		c = abs(c);		if (c > (info->emu.vpar[1] * 4)) { 			s->idx = 0;			s->state = 1; 		} else {			if (s->idx < 210000) s->idx++; 		}	}}voidisdn_audio_put_dle_code(modem_info * info, u_char code){	struct sk_buff *skb;	unsigned long flags;	int di;	int ch;	char *p;	skb = dev_alloc_skb(2);	if (!skb) {		printk(KERN_WARNING		  "isdn_audio: Could not alloc skb for ttyI%d\n",		       info->line);		return;	}	p = (char *) skb_put(skb, 2);	p[0] = 0x10;	p[1] = code;	if (skb_headroom(skb) < sizeof(isdn_audio_skb)) {		printk(KERN_WARNING		       "isdn_audio: insufficient skb_headroom, dropping\n");		kfree_skb(skb);		return;	}	ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;	ISDN_AUDIO_SKB_LOCK(skb) = 0;	save_flags(flags);	cli();	di = info->isdn_driver;	ch = info->isdn_channel;	__skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);	dev->drv[di]->rcvcount[ch] += 2;	restore_flags(flags);	/* Schedule dequeuing */	if ((dev->modempoll) && (info->rcvsched))		isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);	wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);}voidisdn_audio_eval_silence(modem_info * info){	silence_state *s = info->silence_state;	char what;	what = ' ';	if (s->idx > (info->emu.vpar[2] * 800)) { 		s->idx = 0;		if (!s->state) {	/* silence from beginning of rec */ 			what = 's';		} else {			what = 'q';		}	}		if ((what == 's') || (what == 'q')) {			printk(KERN_DEBUG "ttyI%d: %s\n", info->line,				(what=='s') ? "silence":"quiet");			isdn_audio_put_dle_code(info, what);		} }

⌨️ 快捷键说明

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