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

📄 abfile.c

📁 LPC 2.4kbps codec meeting Federal Standard 1016 CELP implementation
💻 C
字号:
#include <stdio.h>#include <fcntl.h>#include <sys/stat.h>#include <sys/mman.h>#include <math.h>#include <multimedia/libaudio.h>#include "abplay.h"#define	MAX(a, b)	((a) < (b) ? (b) : (a))#define	MIN(a, b)	((a) < (b) ? (a) : (b))#define INFO_SIZE	80	/* Max length of file description string */#define NSMAX		1000	/* Maximum number of segments */#define STEPMAX 	2400	/* Max samples/energy point = 50 ms.*48 KHz */#define SIG_SIZE 	4096	/* Audio output buffer size (>= STEPMAX!) */static struct abfile abf[MAXFILES]; /* One of these for each file */static struct segstate sg;	/* Energy/segmentation state */static struct seg seg[NSMAX];	/* start, end (secs) of each segment */static int nfiles = 0;		/* Number of currently open files *//* * Open a signal file and initialize its abfile header. */abp_open_file(char *file){	int fd, nsamp, nstep, hlen, i, j, n, trans;	caddr_t base;	struct stat st;	struct abfile *f;	char info[INFO_SIZE+1];	float win[STEPMAX];	float erms1, erms2, epeak, *w1, *w2, *rb, *pb, t;	char *ip;	short *bp;	char etbuf[SIG_SIZE];	Audio_hdr default_hdr;	/* Defaults for headerless (spd) files */   /* Open file, get its size, and mmap it */	fd = open(file, O_RDONLY);	if (fd < 0 || fstat(fd, &st) < 0) return Perr(fd, "open", file);	if (!S_ISREG(st.st_mode))	    return Pmsg(fd, "open: not a regular file", file);	base = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0);	if (base < (caddr_t)0) return Perr(fd, "mmap", file);   /* Find first empty file slot */	if (nfiles >= MAXFILES) return Pmsg(fd, "open: too many files", file);	abf[nfiles].id = -1;	for (j=0; j<=nfiles; j++) if (abf[j].id < 0) break;	if (j == nfiles) nfiles += 1;	f = &abf[j];   /* Fill in the misc details */	f->id = j;	f->fd = fd;	f->data = base;	f->dsize = st.st_size;	f->p.scale = 1.0;   /* Get the audio header */  /* Set defaults for files without audio headers - spd files */	default_hdr.sample_rate = 8000;		/* 8 KHz */	default_hdr.samples_per_unit = 1;	/* no blocking */	default_hdr.bytes_per_unit = 2;		/* 16-bit samples */	default_hdr.channels = 1;		/* monophonic */	default_hdr.encoding = AUDIO_ENCODING_LINEAR;	/* linear */	default_hdr.data_size = AUDIO_UNKNOWN_SIZE;	/* fill in later */	if (audio_read_filehdr(fd, &f->h, info, INFO_SIZE) != AUDIO_SUCCESS) {	    lseek(fd, 0L, SEEK_SET);	/* rewind file */	    f->h = default_hdr;		/* not a Sun audio file - fake it */	    info[0] = 0;	}	if (f->h.bytes_per_unit == 0) {	    printf("bogus header - using default 16 bit linear encoding\n");	    f->h = default_hdr;	}	f->hsize = lseek(fd, 0L, SEEK_CUR);	if (f->h.data_size == AUDIO_UNKNOWN_SIZE)	    f->h.data_size = f->dsize - f->hsize;   /* Allocate energy buffers, set up translation to 16 bit linear */	sg.step = .020;				/* Energy step size (20 ms.) */	nsamp = f->h.samples_per_unit * (f->h.data_size/f->h.bytes_per_unit);	nstep = nint(f->h.sample_rate * sg.step);	/* samples per step */	f->esize = (nsamp-1) / nstep + 1;	/* # of energy points */	f->rbuf = (float *)calloc(f->esize, sizeof(*f->rbuf));	f->pbuf = (float *)calloc(f->esize, sizeof(*f->pbuf));	if (f->rbuf==0 || f->pbuf==0) Perr(0, "abtool", "buffer alloc failed");	trans = audio_setup_translate(f->h, default_hdr, 1);	if (trans < 0) return -1;/*	printf("hsize = %d, s/u = %d, b/u = %d, srate = %d\n", f->hsize,	    f->h.samples_per_unit, f->h.bytes_per_unit, f->h.sample_rate);	printf("nsamp = %d, nstep = %d, esize = %d\n", nsamp, nstep, f->esize);*/   /* Calculate the energy tracks */	for (j=0, w2=win; j <= nstep; j++) *w2++ = 1.0 / nstep;	ip = f->data + f->hsize;	n = nstep * f->h.bytes_per_unit;	rb = f->rbuf;	pb = f->pbuf;	erms1 = 0.0;	for (i = 0; i < f->esize-1; i++) {	    erms2 = erms1;	    erms1 = epeak = 0.0;	    w1 = win + nstep;	    w2 = win;	    if (trans == 0)	        bp = (short *)ip;	    else {	        bp = (short *)etbuf;	        j = audio_translate(trans, ip, etbuf, n);	    }	    ip += n;	    for (j = 0; j < nstep; j++) {	        t = *bp++;	        epeak = MAX(epeak, abs(t));	        t = t*t;	        erms1 += t**w1--;	        erms2 += t**w2++;	    }	    *rb++ = 10.*log10((double)MAX(erms2, 1.0));	    *pb++ = 20.*log10((double)MAX(epeak, 1.0));	}	*rb++ = 10.*log10((double)MAX(erms1, 1.0));	*pb++ = 0.0;/*	printf("'%s' opened (%d,%d), len = %d, elen = %d\n",	    file, f->id, nfiles, nsamp, f->esize);	if (info[0] != 0) printf("'%s'\n", info);*/	abp_align(f->id, 0.0, sg.p.taumax);	return f->id;}abp_close_file(int id){	struct abfile *f;	struct audio_status status;	if (id<0 || id>=nfiles || id!=abf[id].id) {	    fprintf(stderr, "close: invalid file (%d)\n", id);	    return -1;	}	abp_get_audio_status(&status);	if (id == status.id && status.state != IDLE) abp_abort_play();	if (id == sg.id) sg.id = -1;	f = &abf[id];	f->id = -1;	munmap(f->data, f->dsize);	free(f->rbuf);	free(f->pbuf);	close(f->fd);	return 0;}struct abfile *abp_get_abfile(int id){	if (id<0 || id>=nfiles || id!=abf[id].id) return (struct abfile *)0;	return &abf[id];}struct segstateabp_get_segstate(){	return sg;}abp_segment(int id, struct segparms parm){	int i, nstart, nend, newseg, npad, ngap;	int nsmax = NSMAX;	sg.id = -1;	sg.nsegs = 0;	if (id<0 || id>=nfiles || id!=abf[id].id)	    return sg.nsegs;	sg.id = id;	sg.p = parm;	sg.elength = abf[id].esize;	sg.segs = seg;	sg.energy = abf[id].rbuf;	nstart = sg.elength;	nend = 0;	newseg = 0;	ngap = nint(.001*sg.p.gap / sg.step);	npad = nint(.001*sg.p.pad / sg.step);	for (i = 0; i < sg.elength; i++) {	    if (sg.energy[i] > (float)sg.p.thresh && i < sg.elength-1) {	        nstart = MIN(nstart, i);	        nend = MAX(nend, i);	        newseg = 1;	    } else if (newseg > 0) {	        if (i >= sg.elength-1 || i > nend+ngap) {	            seg[sg.nsegs].start = sg.step * MAX(nstart-npad, 0);	            seg[sg.nsegs].end = sg.step * MIN(nend+npad, sg.elength);	            sg.nsegs += 1;	            newseg = 0;	            if (sg.nsegs >= nsmax) break;	            nstart = sg.elength;	            nend = 0;	        }	    }	}/*	fprintf(stderr, "segment id=%d, thr=%d, gap=%d, pad=%d, nsegs=%d\n",	    id, sg.p.thresh, ngap, npad, sg.nsegs); */	for (i = 0; i < nfiles; i++)	    abp_align(i, 0.0, sg.p.taumax);	return sg.nsegs;}abp_align(int id2, double tau, double taumax){	int id1, n1, n2, i, m, maxm;	float t, c, *e1, *e2;	double corr();	if (id2<0 || id2>=nfiles || abf[id2].id != id2) return -1;	abf[id2].p.corr = abf[id2].p.delay = 0.0;	id1 = sg.id;	if (id1<0 || id1>=nfiles || abf[id1].id != id1) return -1;	n1 = abf[id1].esize;	n2 = abf[id2].esize;	e1 = abf[id1].rbuf;	e2 = abf[id2].rbuf;	m = nint(tau / sg.step);	if (m != 0) {	    c = corr(n1, n2-m, e1, e2+m);	} else {	    c = corr(n1, n2, e1, e2);	    maxm = nint(taumax / sg.step);	    for (i = 1; i < maxm; i++) {	        if ((t = corr(n1, n2-i, e1, e2+i)) > c) {	            c = t;	            m = i;	        }	        if ((t = corr(n1-i, n2, e1+i, e2)) > c) {	            c = t;	            m = -i;	        }	    }	}	abf[id2].p.delay = m * sg.step;	abf[id2].p.corr = c / sqrt(corr(n1,n1,e1,e1) * corr(n2,n2,e2,e2));/*	fprintf(stderr, "corr(%d, %d) = %6.3f at %6.3f sec\n",	    id1, id2, abf[id2].p.corr, abf[id2].p.delay);   */	return 1;}doublecorr(int n1, int n2, float *e1, float *e2){	int i, n;	double t;	n = MIN(n1, n2);	t = 0.0;	for (i = 0; i < n; i++) t += (*e1++) * (*e2++);	return t;}Perr(int fd, char *s1, char *s2){	if (fd > 0) close(fd);	fprintf(stderr, "%s: ", s1);	perror(s2);	return -1;}Pmsg(int fd, char *s1, char *s2){	if (fd > 0) close(fd);	fprintf(stderr, "%s: %s\n", s1, s2);	return(-1);}

⌨️ 快捷键说明

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