ref: 71b37b7c4f39520902a0e61e31a44f74c36d8598
dir: /test/ding.c/
/* ding.c -- program to generate testpatterns for DSP code. Copyright (C) 1999 Stanley J. Brooks <stabro@megsinet.net> 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <string.h> // for open,read,write: #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <unistd.h> #include <math.h> #include <stdio.h> #include <stdlib.h> #define FLOAT double #ifndef LSAMPL # define SAMPL short # define MAXSAMPL 0x7fff # define MINSAMPL -0x7fff #else # define SAMPL long # define MAXSAMPL 0x7fffffff # define MINSAMPL -0x7fffffff #endif struct _Env { int r; /* rise */ int m; /* middle */ int f; /* fall */ int e; /* end */ FLOAT v; /* volume */ FLOAT d; /* decay */ } Env = {0,0,0,0,0.5,1.0}; static void Usage(void)__attribute__((noreturn)); static void Usage(void) { fprintf(stderr, "Usage: ./ding [options] [<in-file>] <out-file>\n"); fprintf(stderr, " Options:\n"); fprintf(stderr, " [-v <vol>] float, volume, 1.00 is max\n"); fprintf(stderr, " [-f <freq>] float, frequency = freq*nyquist_rate\n"); fprintf(stderr, " [-d <decay>] float, per-sample decay factor\n"); fprintf(stderr, " [-o <n>] int, zero-pad samples before tone\n"); fprintf(stderr, " [-e <n>] int, length in samples of tone\n"); fprintf(stderr, " [-p <n>] int, zero-pad samples after tone\n"); exit(-1); } static int ReadN(int fd, SAMPL *v, int n) { int r,m; static SAMPL frag=0; static int fraglen=0; char *q; q=(char*)v; if (fraglen) memcpy(q, (char*)&frag, fraglen); m = n*sizeof(SAMPL) - fraglen; q += fraglen; if (fd>=0) { do { r = read(fd, q, m); }while(r==-1 && errno==EINTR); if (r==-1) { perror("Error reading fd1"); exit(-1); } }else{ bzero(q,m); r = m; } r += fraglen; fraglen = r%sizeof(SAMPL); if (fraglen) memcpy((char*)&frag, (char*)v, fraglen); return (r/sizeof(SAMPL)); } #define BSIZ 0x10000 int main(int argct, char **argv) { int optc; int fd1,fd2; char *fnam1,*fnam2; int len, st; SAMPL *ibuff,max,min; int poflo,moflo; FLOAT Vol0=1; FLOAT Freq=0; /* of nyquist */ int Pad=0; double x=1,y=0; double thx=1,thy=0; static inline void a_init(double frq) { if (0<frq && frq<1) { x = 1; y = 0; } else { x = 0; y = 1; } thx = cos(frq*M_PI); thy = sin(frq*M_PI); } static inline void a_post(int k) { double x1; x1 = x*thx - y*thy; y = x*thy + y*thx; x = x1; /* update (x,y) for next tic */ if (!(k&0x0f)) { /* norm correction each 16 samples */ x1 = 1/sqrt(x*x+y*y); x *= x1; y *= x1; } } /* rise/fall function, monotonic [0,1] -> [1-0] */ static inline const double a(double s) { return 0.5*(1 + cos(M_PI * s)); } static double env(struct _Env *Env, int k) { double u = 0; //if (k >= Env->r && k < Env->e) { if (k<Env->m) { u = Env->v * a((double)(Env->m-k)/(Env->m-Env->r)); }else if (k<Env->f) { u = Env->v; }else{ u = Env->v * a((double)(k-Env->f)/(Env->e-Env->f)); } //} return u; } /* Parse the options */ while ((optc = getopt(argct, argv, "d:o:e:t:p:f:v:h")) != -1) { char *p; switch(optc) { case 'd': Env.d = strtod(optarg,&p); if (p==optarg || *p) { fprintf(stderr,"option -%c expects float value (%s)\n", optc, optarg); Usage(); } break; case 'f': Freq = strtod(optarg,&p); if (p==optarg || *p) { fprintf(stderr,"option -%c expects float value (%s)\n", optc, optarg); Usage(); } break; case 'e': p = optarg; Env.f = strtol(p,&p,10); if (*p++ == ':') { Env.m = Env.e = Env.f; Env.f = strtol(p,&p,10); } if (*p++ == ':') { Env.e = strtol(p,&p,10); } if (*p || Env.f<=0 || Env.m<0 || Env.e<0) { fprintf(stderr,"option -%c not valid (%s)\n", optc, optarg); Usage(); } break; case 'o': Env.r = strtol(optarg,&p,10); if (p==optarg || *p || Env.r<0) { fprintf(stderr,"option -%c expects int value (%s)\n", optc, optarg); Usage(); } break; case 'p': Pad = strtol(optarg,&p,10); if (p==optarg || *p || Pad<0) { fprintf(stderr,"option -%c expects int value (%s)\n", optc, optarg); Usage(); } break; case 'v': Env.v = strtod(optarg,&p); if (p==optarg || *p) { fprintf(stderr,"option -%c expects float value (%s)\n", optc, optarg); Usage(); } break; case 'h': default: Usage(); } } Env.v *= MAXSAMPL; if (Freq==0.0) Env.v *= sqrt(0.5); //fprintf(stderr,"Vol0 %8.3f\n", Vol0); Env.m += Env.r; Env.f += Env.m; Env.e += Env.f; len = Env.e+Pad; fnam1=NULL; fd1=-1; //fprintf(stderr,"optind=%d argct=%d\n",optind,argct); if (optind <= argct-2) { fnam1=argv[optind++]; fd1=open(fnam1,O_RDONLY); if (fd1<0) { fprintf(stderr,"Open: %s %s\n",fnam1,strerror(errno)); return(1); } len=lseek(fd1,0,SEEK_END)/2; lseek(fd1,0,SEEK_SET); } if (optind != argct-1) Usage(); fd2 = 1; /* stdout */ fnam2=argv[optind++]; if (strcmp(fnam2,"-")) { fd2=open(fnam2,O_WRONLY|O_CREAT|O_TRUNC,0644); if (fd2<0) { fprintf(stderr,"Open: %s %s\n",fnam2,strerror(errno)); return(1); } } //fprintf(stderr, "Files: %s %s\n",fnam1,fnam2); a_init(Freq); ibuff=(SAMPL*)malloc(BSIZ*sizeof(SAMPL)); poflo=moflo=0; max =MINSAMPL; min=MAXSAMPL; for(st=0; st<len; ){ int ct; SAMPL *ibp; ct = len - st; if (ct>BSIZ) ct=BSIZ; ReadN(fd1,ibuff,ct); for (ibp=ibuff; ibp<ibuff+ct; ibp++,st++) { double v = *ibp; if (max<*ibp) max=*ibp; else if (min>*ibp) min=*ibp; v *= Vol0; if (st>=Env.r && st<Env.e) { v += y*env(&Env,st); a_post(st); } if (v>MAXSAMPL) { poflo++; v=MAXSAMPL; } else if (v<MINSAMPL) { moflo++; v=MINSAMPL; } *ibp = rint(v); } write(fd2,(char*)ibuff,ct*sizeof(SAMPL)); } fprintf(stderr,"input range: [%ld,%ld] pos/neg oflos: %d/%d\n",min,max,poflo,moflo); return 0; }