/*************************************************************************/ /* */ /* Language Technologies Institute */ /* Carnegie Mellon University */ /* Copyright (c) 2001 */ /* All Rights Reserved. */ /* */ /* Permission is hereby granted, free of charge, to use and distribute */ /* this software and its documentation without restriction, including */ /* without limitation the rights to use, copy, modify, merge, publish, */ /* distribute, sublicense, and/or sell copies of this work, and to */ /* permit persons to whom this work is furnished to do so, subject to */ /* the following conditions: */ /* 1. The code must retain the above copyright notice, this list of */ /* conditions and the following disclaimer. */ /* 2. Any modifications must be clearly marked as such. */ /* 3. Original authors' names are not deleted. */ /* 4. The authors' names are not used to endorse or promote products */ /* derived from this software without specific prior written */ /* permission. */ /* */ /* CARNEGIE MELLON UNIVERSITY AND THE CONTRIBUTORS TO THIS WORK */ /* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */ /* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */ /* SHALL CARNEGIE MELLON UNIVERSITY NOR THE CONTRIBUTORS BE LIABLE */ /* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */ /* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */ /* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */ /* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */ /* THIS SOFTWARE. */ /* */ /*************************************************************************/ /* Author: Alan W Black (awb@cs.cmu.edu) */ /* Date: June 2001 */ /*************************************************************************/ /* */ /* residuals etc */ /* */ /*************************************************************************/ #include #include #include "cst_wave.h" #include "cst_track.h" #include "cst_sigpr.h" void inv_lpc_filterd(short *sig, float *a, int order, double *res, int size) { int i, j; double r; for (i = 0; i < order; i++) { r = sig[i]; for (j = 1; j < order; j++) /* if (i-j >= 0) */ r -= a[j] * (double)sig[i - j]; res[i] = r; } for (i = order; i < size; i++) { r = sig[i]; for (j = 1; j < order; j++) r -= a[j] * (double)sig[i - j]; res[i] = r; } } cst_wave *find_residual(cst_wave *sig, cst_track *lpc) { cst_wave *res; int i; double *resd; int size,start,end; res = new_wave(); cst_wave_resize(res,sig->num_samples,1); res->sample_rate = sig->sample_rate; resd = cst_alloc(double,sig->num_samples); start = lpc->num_channels; for (i=0; inum_frames; i++) { end = (int)((float)sig->sample_rate * lpc->times[i]); size = end - start; inv_lpc_filterd(&sig->samples[start],lpc->frames[i],lpc->num_channels, &resd[start],size); start = end; } for (i=0; inum_samples; i++) res->samples[i] = resd[i]; cst_free(resd); return res; } void lpc_filterd(short *res, float *a, int order, double *sig, int size) { int i, j; double r; for (i = 0; i < order; i++) { r = res[i]; for (j = 1; j < order; j++) /* if (i-j >= 0) */ r += a[j] * (double)sig[i - j]; sig[i] = r; } for (i = order; i < size; i++) { r = res[i]; for (j = 1; j < order; j++) r += a[j] * (double)sig[i - j]; sig[i] = r; } } cst_wave *reconstruct_wave(cst_wave *res, cst_track *lpc) { cst_wave *sig; int i; double *sigd; int start, end, size; sig = new_wave(); cst_wave_resize(sig,res->num_samples,1); sig->sample_rate = res->sample_rate; sigd = cst_alloc(double,sig->num_samples); start = 0; for (i=0; inum_frames; i++) { end = (int)((float)sig->sample_rate * lpc->times[i]); size = end - start; lpc_filterd(&res->samples[start], lpc->frames[i],lpc->num_channels, &sigd[start],size); start = end; } for (i=0; inum_samples; i++) sig->samples[i] = sigd[i]; cst_free(sigd); return sig; } float lpc_min = -2.709040; float lpc_range = 2.328840+2.709040; void lpc_filterde(unsigned char *resulaw, unsigned short *as, int order, short *sig, int size) { int i, j; float r; float *a; float *sigf; a = cst_alloc(float,order); for (i=1; i= 0) */ r += a[j] * (float)sigf[i - j]; sigf[i] = r; } for (i = order; i < size; i++) { r = cst_ulaw_to_short(resulaw[i]); for (j = 1; j < order; j++) r += a[j] * (float)sigf[i - j]; sigf[i] = r; } for (i=0; inum_samples,1); sig->sample_rate = res->sample_rate; sigd = cst_alloc(short,sig->num_samples); as = cst_alloc(unsigned short,lpc->num_channels); resulaw = cst_alloc(unsigned char, res->num_samples); for (i=0; inum_samples; i++) resulaw[i] = cst_short_to_ulaw(res->samples[i]); start = 0; for (i=0; inum_frames; i++) { end = (int)((float)sig->sample_rate * lpc->times[i]); size = end - start; for (j=1; jnum_channels; j++) as[j] = (((lpc->frames[i][j]-lpc_min)/lpc_range)*65535.0); lpc_filterde(&resulaw[start], as,lpc->num_channels, &sigd[start],size); start = end; } for (i=0; inum_samples; i++) sig->samples[i] = sigd[i]; cst_free(sigd); return sig; } cst_wave *dumdum(cst_wave *res,cst_track *lpc) { cst_lpcres *lpcres; int i,j,s; unsigned short *bbb; int start,end,size; FILE *ofd; lpcres = new_lpcres(); lpcres_resize_frames(lpcres,lpc->num_frames); lpcres->num_channels = lpc->num_channels-1; start = 0; for (i=0; inum_frames; i++) { bbb = cst_alloc(unsigned short,lpc->num_channels-1); for (j=1; jnum_channels; j++) bbb[j-1] = (unsigned short) (((lpc->frames[i][j]-lpc_min)/lpc_range)*65535); lpcres->frames[i] = bbb; end = lpc->times[i]*res->sample_rate; lpcres->times[i] = lpc->times[i]; size = end - start; lpcres->sizes[i] = size; start = end; } lpcres_resize_samples(lpcres,res->num_samples); lpcres->lpc_min = lpc_min; lpcres->lpc_range = lpc_range; lpcres->sample_rate = res->sample_rate; for (i=0; inum_samples; i++) lpcres->residual[i] = cst_short_to_ulaw(res->samples[i]); ofd = fopen("lpc1.lpc","w"); for (s=0,i=0; inum_frames; i++) { fprintf(ofd,"%d %d %d\n",i,lpcres->times[i],lpcres->sizes[i]); for (j=0; j < lpcres->num_channels; j++) fprintf(ofd,"%d ",lpcres->frames[i][j]); fprintf(ofd,"\n"); for (j=0; j < lpcres->sizes[i]; j++,s++) fprintf(ofd,"%d ",lpcres->residual[s]); fprintf(ofd,"\n"); } fclose(ofd); return lpc_resynth(lpcres); } int main(int argc, char **argv) { /* need that cool argument parser */ cst_wave *w,*res,*sig,*w2, *w3; cst_track *lpc; int i; double r; if (argc != 3) { fprintf(stderr,"usage: lpc_test2 LPC WAVEFILE\n"); return 1; } lpc = new_track(); cst_track_load_est(lpc,argv[1]); sig = new_wave(); cst_wave_load_riff(sig,argv[2]); res = find_residual(sig,lpc); w = reconstruct_wave(res,lpc); cst_wave_save_riff(res,"res.wav"); cst_wave_save_riff(w,"new.wav"); w2 = reconstruct_wavee(res,lpc); cst_wave_save_riff(w2,"newe.wav"); w3 = dumdum(res,lpc); cst_wave_save_riff(w3,"newr.wav"); for (r=0.0,i=0; inum_samples; i++) r += ((float)sig->samples[i]-(float)w->samples[i]) * ((float)sig->samples[i]-(float)w->samples[i]); r /= sig->num_samples; printf("orig/new %f\n",sqrt(r)); for (r=0.0,i=0; inum_samples; i++) r += ((float)sig->samples[i]-(float)w2->samples[i]) * ((float)sig->samples[i]-(float)w2->samples[i]); r /= sig->num_samples; printf("orig/newe %f\n",sqrt(r)); for (r=0.0,i=0; inum_samples; i++) r += ((float)sig->samples[i]-(float)w3->samples[i]) * ((float)sig->samples[i]-(float)w3->samples[i]); r /= sig->num_samples; printf("orig/newr %f\n",sqrt(r)); return 0; }