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

📄 polyphas.c

📁 linux下录音程序
💻 C
字号:
/* * July 14, 1998 * Copyright 1998  K. Bradley, Carnegie Mellon University * * This source code is freely redistributable and may be used for * any purpose.  This copyright notice must be maintained.  * Lance Norskog And Sundry Contributors are not responsible for  * the consequences of using this software. *//* * Sound Tools rate change effect file. */#include <math.h>#include <stdio.h>#include <stdlib.h>#include "st.h"typedef struct _list {    int number;    float *data_buffer;    struct _list *next;} List;typedef struct polyphase {  unsigned long	lcmrate;	   /* least common multiple of rates */  unsigned long inskip, outskip;   /* LCM increments for I & O rates */  unsigned long total;  unsigned long intot, outtot;	   /* total samples in terms of LCM rate */  long	lastsamp;  float **filt_array;  float **past_hist;  float *input_buffer;  int *filt_len;  List *l1, *l2;  } *poly_t;/* * Process options *//* Options:     -w <nut / ham>        :  window type   -width <short / long> :  window width                            short = 128 samples			    long  = 1024 samples	  <num>	            num:  explicit number    -cutoff <float>       :  frequency cutoff for base bandwidth.                            Default = 0.95 = 95%*/static int win_type  = 0;static int win_width = 1024;static float cutoff = 0.95;   void poly_getopts(effp, n, argv) eff_t effp;int n;char **argv;{  /* 0: nuttall     1: hamming */  win_type = 0;  /* width:  short = 128             long = 1024 (default) */  win_width = 1024;  /* cutoff:  frequency cutoff of base bandwidth in percentage. */  cutoff = 0.95;  while(n >= 2) {    /* Window type check */    if(!strcmp(argv[0], "-w")) {      if(!strcmp(argv[1], "ham"))	win_type = 1;      if(!strcmp(argv[1], "nut"))	win_type = 0;      argv += 2;      n -= 2;      continue;    }    /* Window width check */    if(!strcmp(argv[0], "-width")) {      if(!strcmp(argv[1], "short"))	win_width = 128;      else if(!strcmp(argv[1], "long"))	win_width = 1024;      else	win_width = atoi(argv[1]);      argv += 2;      n -= 2;      continue;    }    /* Cutoff frequency check */    if(!strcmp(argv[0], "-cutoff")) {      cutoff = atof(argv[1]);      argv += 2;      n -= 2;      continue;    }    fail("Polyphase: unknown argument (%s %s)!", argv[0], argv[1]);  }}/* * Prepare processing. */static int primes[] = {  2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37,  41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89,  97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151,  157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223,  227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281,  283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359,  367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433,  439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503,  509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593,  599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659,  661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743,  751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827,  829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911,  919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997};#define max(x,y) ((x > y) ? x : y)List *prime(number)int number;{    int j;    List *element = NULL;    if(number == 1)      return NULL;    for(j=167;j>= 0;j--) {	if(number % primes[j] == 0) {	    element = (List *) malloc(sizeof(List));	    element->number = primes[j];	    element->data_buffer = NULL;	    element->next = prime(number / primes[j]);	    break;	}    }    if(element == NULL) {	fail("Number %d too large of a prime.\n",number);    }    return element;}List *prime_inv(number)int number;{    int j;    List *element = NULL;    if(number == 1)      return NULL;    for(j=0;j<168;j++) {	if(number % primes[j] == 0) {	    element = (List *) malloc(sizeof(List));	    element->number = primes[j];	    element->data_buffer = NULL;	    element->next = prime_inv(number / primes[j]);	    break;	}    }    if(element == NULL) {	fail("Number %d too large of a prime.\n",number);    }    return element;}#ifndef PI#define PI 3.14159265358979#endif/* Calculate a Nuttall window of a given length.   Buffer must already be allocated to appropriate size.   */void nuttall(buffer, length)float *buffer;int length;{  int j;  double N;  double N1;  if(buffer == NULL || length < 0)    fail("Illegal buffer %p or length %d to nuttall.\n", buffer, length);  /* Initial variable setups. */  N = (double) length - 1.0;  N1 = N / 2.0;  for(j = 0; j < length; j++) {    buffer[j] = 0.36335819 +       0.4891775 * cos(2*PI*1*(j - N1) / N) +      0.1365995 * cos(2*PI*2*(j - N1) / N) +       0.0106411 * cos(2*PI*3*(j - N1) / N);  }}/* Calculate a Hamming window of given length.   Buffer must already be allocated to appropriate size.*/void hamming(buffer, length)float *buffer;int length;{    int j;    if(buffer == NULL || length < 0)      fail("Illegal buffer %p or length %d to hamming.\n",buffer,length);    for(j=0;j<length;j++)       buffer[j] = 0.5 - 0.46 * cos(2*PI*j/(length-1));}/* Calculate the sinc function properly */float sinc(value)float value;{       return(fabs(value) < 1E-50 ? 1.0 : sin(value) / value);}/* Design a low-pass FIR filter using window technique.   Length of filter is in length, cutoff frequency in cutoff.   0 < cutoff <= 1.0 (normalized frequency)   buffer must already be allocated.*/void fir_design(buffer, length, cutoff)float *buffer;int length;float cutoff;{    int j;    float sum;    float *ham_win;    if(buffer == NULL || length < 0 || cutoff < 0 || cutoff > PI)      fail("Illegal buffer %p, length %d, or cutoff %f.\n",buffer,length,cutoff);    /* Design Hamming window:  43 dB cutoff */    ham_win = (float *)malloc(sizeof(float) * length);    /* Use the user-option of window type */    if(win_type == 0)       nuttall(ham_win, length);    else      hamming(ham_win,length);    /* Design filter:  windowed sinc function */    sum = 0.0;    for(j=0;j<length;j++) {	buffer[j] = sinc(PI*cutoff*(j-length/2)) * ham_win[j] / (2*cutoff);	sum += buffer[j];    }    /* Normalize buffer to have gain of 1.0: prevent roundoff error */    for(j=0;j<length;j++)      buffer[j] /= sum;    free((void *) ham_win);}    void poly_start(effp)eff_t effp;{    poly_t rate = (poly_t) effp->priv;    List *t, *t2;    int num_l1, num_l2;    int j,k;    float f_cutoff;    extern long lcm();	    rate->lcmrate = lcm((long)effp->ininfo.rate, (long)effp->outinfo.rate);    /* Cursory check for LCM overflow.       * If both rate are below 65k, there should be no problem.     * 16 bits x 16 bits = 32 bits, which we can handle.     */    rate->inskip = rate->lcmrate / effp->ininfo.rate;    rate->outskip = rate->lcmrate / effp->outinfo.rate;     /* Find the prime factors of inskip and outskip */    rate->l1 = prime(rate->inskip);    /* If we're going up, order things backwards. */    if(effp->ininfo.rate < effp->outinfo.rate)      rate->l2 = prime_inv(rate->outskip);    else      rate->l2 = prime(rate->outskip);        /* Find how many factors there were */    if(rate->l1 == NULL)      num_l1 = 0;    else      for(num_l1=0, t = rate->l1; t != NULL; num_l1++, t=t->next);    if(rate->l2 == NULL)       num_l2 = 0;    else      for(num_l2=0, t = rate->l2; t != NULL; num_l2++, t=t->next);    k = 0;    t = rate->l1;    /* Compact the lists to be less than 10 */    while(k < num_l1 - 1) {	if(t->number * t->next->number < 10) {	    t->number = t->number * t->next->number;	    t2 = t->next;	    t->next = t->next->next;	    t2->next = NULL;	    free((void *) t2);	    num_l1--;	} else {	    k++;	    t = t->next;	}    }    k = 0;    t = rate->l2;    while(k < num_l2 - 1) {	if(t->number * t->next->number < 10) {	    t->number = t->number * t->next->number;	    t2 = t->next;	    t->next = t->next->next;	    t2->next = NULL;	    free((void *) t2);	    num_l2--;	} else {	    k++;	    t = t->next;	}    }    /* l1 and l2 are now lists of the prime factors compacted,       meaning that they're the lists of up/down sampling we need       */    /* Stretch them to be the same length by padding with 1 (no-op) */    if(num_l1 < num_l2) {	t = rate->l1;	if(t == NULL) {	    rate->l1 = (List *)malloc(sizeof(List));	    rate->l1->next = NULL;	    rate->l1->number = 1;	    rate->l1->data_buffer = NULL;	    t = rate->l1;	    num_l1++;	}	while(t->next != NULL)	  t = t->next;	for(k=0;k<num_l2-num_l1;k++) {	    t->next = (List *) malloc(sizeof(List));	    t->next->number = 1;	    t->next->data_buffer = NULL;	    t = t->next;	}	t->next = NULL;	num_l1 = num_l2;    } else {	t = rate->l2;	if(t == NULL) {	    rate->l2 = (List *)malloc(sizeof(List));	    rate->l2->next = NULL;	    rate->l2->number = 1;	    rate->l2->data_buffer = NULL;	    t = rate->l2;	    num_l2++;	}	  	/*	  while(t->next != NULL)	  t = t->next;	  */	for(k=0;k<num_l1-num_l2;k++) {	  t = rate->l2;	  rate->l2 = (List *) malloc(sizeof(List));	  rate->l2->number = 1;	  rate->l2->data_buffer = NULL;	  rate->l2->next = t;	}	/* t->next = NULL; */	num_l2 = num_l1;    }    /* l1 and l2 are now the same size. */    rate->total = num_l1;    report("Poly:  input rate %d, output rate %d.  %d stages.",effp->ininfo.rate, effp->outinfo.rate,num_l1);    report("Poly:  window: %s  size: %d  cutoff: %f.", (win_type == 0) ? ("nut") : ("ham"), win_width, cutoff);    for(k=0, t=rate->l1, t2=rate->l2;k<num_l1;k++,t=t->next,t2=t2->next)      report("Poly:  stage %d:  Up by %d, down by %d.",k+1,t->number,t2->number);    /* We'll have an array of filters and past history */    rate->filt_array = (float **) malloc(sizeof(float *) * num_l1);    rate->past_hist = (float **) malloc(sizeof(float *) * num_l1);    rate->filt_len = (int *) malloc(sizeof(int) * num_l1);    for(k = 0, t = rate->l1, t2 = rate->l2; k < num_l1; k++) {      rate->filt_len[k] = max(2 * 10 * max(t->number,t2->number), win_width);      rate->filt_array[k] = (float *) malloc(sizeof(float) * rate->filt_len[k]);      rate->past_hist[k] = (float *) malloc(sizeof(float) * rate->filt_len[k]);            t->data_buffer = (float *) malloc(sizeof(float) * 1024 * rate->inskip);	      for(j = 0; j < rate->filt_len[k]; j++)	rate->past_hist[k][j] = 0.0;      f_cutoff = (t->number > t2->number) ? 	(float) t->number : (float) t2->number;      fir_design(rate->filt_array[k], rate->filt_len[k]-1, cutoff / f_cutoff);      t = t->next;      t2 = t2->next;    }    rate->input_buffer = (float *) malloc(sizeof(float) * 2048);}/* * Processed signed long samples from ibuf to obuf. * Return number of samples processed. */static float *h;static int M, L, N;void polyphase_init(coef, num_coef, up_rate, down_rate)float *coef;int num_coef;int up_rate;int down_rate;{    h = coef;    M = down_rate;    L = up_rate;    N = num_coef;}    void polyphase(input, output, past, num_samples_input)float *input;float *output;float *past;int num_samples_input;{    int num_output;    int m,n;    float sum;    float inp;    int base;    int h_base;    num_output = num_samples_input * L / M;    for(m=0;m<num_output;m++) {	sum = 0.0;	base = (int) (m*M/L);	h_base = (m*M) % L;	for(n=0;n<N / L;n++) {	    if(base - n < 0)	      inp = past[base - n + N];	    else	      inp = input[base - n];	    sum += h[n*L + h_base] * inp;	}	output[m] = sum * L * 0.95;    }}void poly_flow(effp, ibuf, obuf, isamp, osamp)eff_t effp;long *ibuf, *obuf;int *isamp, *osamp;{  poly_t rate = (poly_t) effp->priv;  float *temp_buf, *temp_buf2;  int j,k;  List *t1, *t2;  int in_size, out_size;  /* Sanity check:  how much can we tolerate? */  in_size = *isamp;  out_size = in_size * rate->inskip / rate->outskip;  if(out_size > *osamp) {    in_size = *osamp * rate->outskip / rate->inskip;    *isamp = in_size;  }    /* Check to see if we're really draining */  if(ibuf != NULL) {    for(k=0;k<*isamp;k++)      rate->input_buffer[k] = (float) (ibuf[k] >> 16);  } else {    for(k=0;k<*isamp;k++)      rate->input_buffer[k] = 0.0;  }          temp_buf = rate->input_buffer;    t1 = rate->l1;  t2 = rate->l2;    for(k=0;k<rate->total;k++,t1=t1->next,t2=t2->next) {        polyphase_init(rate->filt_array[k], rate->filt_len[k], 		   t1->number,t2->number);        out_size = (in_size) * t1->number / t2->number;        temp_buf2 = t1->data_buffer;        polyphase(temp_buf, temp_buf2, rate->past_hist[k], in_size);        for(j = 0; j < rate->filt_len[k]; j++)       rate->past_hist[k][j] = temp_buf[j+in_size - rate->filt_len[k]];        in_size = out_size;        temp_buf = temp_buf2;  }    if(out_size > *osamp)    out_size = *osamp;    *osamp = out_size;  if(ibuf != NULL) {    for(k=0;k < out_size;k++)      obuf[k] = ((int) temp_buf[k]) << 16;  } else {    /* Wait for all-zero samples to come through.       Should happen eventually with all-zero       input */    int found = 0;    for(k=0; k < out_size; k++) {      obuf[k] = ((int) temp_buf[k] << 16);      if(obuf[k] != 0)	found = 1;    }    if(!found)      *osamp = 0;  }}/* * Process tail of input samples. */void poly_drain(effp, obuf, osamp)eff_t effp;long *obuf;long *osamp;{  long in_size = 1024;  /* Call "flow" with NULL input. */  poly_flow(effp, NULL, obuf, &in_size, osamp);}/* * Do anything required when you stop reading samples.   * Don't close input file!  */void poly_stop(effp)eff_t effp;{    List *t, *t2;    poly_t rate = (poly_t) effp->priv;    int k;    /* Free lists */    for(t = rate->l1; t != NULL; ) {	t2 = t->next;	t->next = NULL;	if(t->data_buffer != NULL)	  free((void *) t->data_buffer);	free((void *) t);	t = t2;    }    for(t = rate->l2; t != NULL; ) {	t2 = t->next;	t->next = NULL;	if(t->data_buffer != NULL)	  free((void *) t->data_buffer);	free((void *) t);	t = t2;    }    for(k = 0; k < rate->total;k++) {	free((void *) rate->past_hist[k]);	free((void *) rate->filt_array[k]);    }    free((void *) rate->past_hist);    free((void *) rate->filt_array);    free((void *) rate->filt_len);}

⌨️ 快捷键说明

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