allpass.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /*
  2. * Copyright (c) 1983-2013 Composers Desktop Project Ltd
  3. * http://www.composersdesktop.com
  4. * This file is part of the CDP System.
  5. * The CDP System is free software; you can redistribute it
  6. * and/or modify it under the terms of the GNU Lesser General Public
  7. * License as published by the Free Software Foundation; either
  8. * version 2.1 of the License, or (at your option) any later version.
  9. *
  10. * The CDP System is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. * See the GNU Lesser General Public License for more details.
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with the CDP System; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17. *
  18. */
  19. /* allpass.c
  20. * allpass filter
  21. * A. Bentley, Composers' Desktop Project, Version Nov 1987
  22. */
  23. /*
  24. * $Log: allpass.c%v $
  25. * Revision 3.3 1994/10/31 22:08:15 martin
  26. * first rcs version
  27. *
  28. */
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <math.h>
  32. #include <sfsys.h>
  33. #include <cdplib.h>
  34. static char *sfsys_h_rcsid = SFSYS_H_RCSID;
  35. static char *cdplib_h_rcsid = CDPLIB_H_RCSID;
  36. void usage();
  37. void allpass_long(long,long,long,long,const short*,short*,long*,short *);
  38. #define BUFLEN (32768)
  39. #define FP_ONE (65536.0)
  40. #define LOG_PS (16)
  41. PROGRAM_NUMBER(0xf93c2700);
  42. void
  43. main(argc,argv)
  44. int argc;
  45. char *argv[];
  46. {
  47. int ifd, ofd;
  48. int sampsize;
  49. int quickflag = 1; /* default is fast fixed point calc */
  50. register int rv;
  51. float ip, op;
  52. #ifdef ORIGINAL_VERSION
  53. long lip, lop;
  54. long i;
  55. #endif
  56. float *delbuf1;
  57. float *delbuf2;
  58. long rdsamps;
  59. long *ldelbuf1;
  60. short *sdelbuf2;
  61. short *sinbuf;
  62. short *soutbuf;
  63. double delay;
  64. float gain, prescale = 1.0f;
  65. long lgain, lprescale;
  66. long delsamps;
  67. long dbp1 = 0, dbp2 = 0;
  68. long chans;
  69. long isr;
  70. double sr;
  71. if(sflinit("allpass")){
  72. sfperror("Allpass: initialisation");
  73. exit(1);
  74. }
  75. while(argv[1] != 0 && argv[1][0] == '-') {
  76. switch(argv[1][1]) {
  77. case 'f':
  78. quickflag--;
  79. argv++;
  80. argc--;
  81. break;
  82. default:
  83. usage();
  84. break;
  85. }
  86. }
  87. if(argc < 5 || argc > 6) usage();
  88. if(argv[1] != 0) {
  89. if((ifd = sndopen(argv[1])) < 0) {
  90. fprintf(stderr,"Allpass: cannot open input file %s\n", argv[1]);
  91. exit(1);
  92. }
  93. }
  94. if(sndgetprop(ifd,"sample rate",(char *) &isr, sizeof(long)) < 0){
  95. fprintf(stderr,
  96. "\nAllpass: failed to read sample rate for file %s",argv[1]);
  97. exit(1);
  98. }
  99. sr = (double) (isr);
  100. if(sndgetprop(ifd,"channels",(char *) &chans, sizeof(long)) < 0){
  101. fprintf(stderr,
  102. "\nAllpass: failed to read channel data for file %s", argv[1]);
  103. exit(1);
  104. }
  105. if(chans != 1){
  106. fprintf(stderr,"\nAllpass works only on mono files");
  107. exit(1);
  108. }
  109. if(sndgetprop(ifd,"sample type",(char *) &sampsize, sizeof(long)) < 0){
  110. fprintf(stderr,
  111. "\nAllpass: failed to read sample type for file %s", argv[1]);
  112. exit(1);
  113. }
  114. /* get command line args */
  115. delay = abexpr(argv[3],sr);
  116. if(delay < 0.0){
  117. fprintf(stderr,"\nAllpass: invalid delay parameter");
  118. exit(1);
  119. }
  120. gain = (float)abexpr(argv[4],sr);
  121. if((gain < -1.0) || (gain > 1.0)){
  122. fprintf(stderr,"\nAllpass: gain out of range");
  123. exit(1);
  124. }
  125. if((ofd = sndcreat(argv[2],-1,sampsize)) < 0) {
  126. fprintf(stderr,"Cannot open output file %s\n",argv[2]);
  127. exit(1);
  128. }
  129. lgain = (long) (gain * FP_ONE);
  130. if(argc > 5) {
  131. prescale = (float)abexpr(argv[5],sr);
  132. if((prescale < -1.0) || (prescale > 1.0))
  133. fprintf(stderr,
  134. "Allpass: warning - prescale exceeds +/-1\n");
  135. }
  136. lprescale = (long) (prescale * FP_ONE);
  137. /* allocate buffer for delay line */
  138. delsamps = (long) (delay * sr);
  139. if(quickflag) {
  140. if(( sinbuf = (short *) malloc(BUFLEN * sizeof(short))) == NULL) {
  141. fprintf(stderr,"\nNot enough memory for input buffer");
  142. exit(1);
  143. }
  144. if(( soutbuf = (short *) malloc(BUFLEN * sizeof(short))) == NULL) {
  145. fprintf(stderr,"\nNot enough memory for output buffer");
  146. exit(1);
  147. }
  148. if(( ldelbuf1 = (long *) calloc(delsamps, sizeof(long))) == NULL) {
  149. fprintf(stderr,"\nNot enough memory for delay buffer 1");
  150. exit(1);
  151. }
  152. if(( sdelbuf2 = (short *) calloc(delsamps, sizeof(short))) == NULL) {
  153. fprintf(stderr,"\nNot enough memory for delay buffer 2");
  154. exit(1);
  155. }
  156. }else{
  157. if(( delbuf1 = (float *) calloc(delsamps, sizeof(float))) == NULL) {
  158. fprintf(stderr,"\nNot enough memory for delay buffer 1");
  159. exit(1);
  160. }
  161. if(( delbuf2 = (float *) calloc(delsamps, sizeof(float))) == NULL) {
  162. fprintf(stderr,"\nNot enough memory for delay buffer 2");
  163. exit(1);
  164. }
  165. }
  166. stopwatch(1);
  167. for(;;){
  168. if((rv = fgetfloat(&ip,ifd)) < 0){
  169. fprintf(stderr,"\nError in reading file");
  170. exit(1);
  171. }
  172. if(!rv) break;
  173. ip *= prescale;
  174. op = (-gain) * ip;
  175. op += delbuf1[dbp1];
  176. op += gain * delbuf2[dbp2];
  177. delbuf1[dbp1++] = ip;
  178. delbuf2[dbp2++] = op;
  179. if(dbp1 >= delsamps) dbp1 = 0;
  180. if(dbp2 >= delsamps) dbp2 = 0;
  181. if(fputfloat(&op,ofd) < 1){
  182. fprintf(stderr,"\nError writing to output file");
  183. exit(1);
  184. }
  185. }
  186. stopwatch(0);
  187. sndclose(ifd);
  188. if(sndputprop(ofd,"sample rate", (char *) &isr, sizeof(long)) < 0){
  189. fprintf(stderr,"\nAllpass: failed to write sample rate");
  190. }
  191. if(sndputprop(ofd,"channels",(char *) &chans, sizeof(long)) < 0){
  192. fprintf(stderr,"\nAllpass: failed to write channel data");
  193. }
  194. sndclose(ofd);
  195. }
  196. void
  197. usage()
  198. {
  199. fprintf(stderr,"\nAllpass - A Groucho Program: $Revision: 3.3 $");
  200. fprintf(stderr,"\n%s\n",
  201. "usage: allpass [-f] infile outfile delay gain [prescale]");
  202. exit(0);
  203. }
  204. /*RWD: my allpass functions */
  205. //TODO: optimize using ptr arithmetic
  206. void allpass_long(long prescale,
  207. long buflen,
  208. long l_gain,
  209. long l_delsamps,
  210. const short *s_inbuf,
  211. short *s_outbuf,
  212. long *l_delbuf1,
  213. short *s_delbuf2)
  214. {
  215. int i;
  216. static long db_p1 = 0;
  217. static long db_p2 = 0;
  218. //do allpass on block of samples
  219. for(i = 0; i < buflen; i++){
  220. long lip,lop;
  221. lip = s_inbuf[i] * prescale;
  222. lop = (-l_gain) * (lip >> LOG_PS);
  223. lop += l_delbuf1[db_p1];
  224. lop += l_gain * s_delbuf2[db_p2];
  225. l_delbuf1[db_p1++] = lip;
  226. s_outbuf[i] = s_delbuf2[db_p2++] = (short) (lop >> LOG_PS);
  227. if(db_p1 >= l_delsamps) db_p1 = 0;
  228. if(db_p2 >= l_delsamps) db_p2 = 0;
  229. }
  230. //block done
  231. //return &soutbuf[0]; //if we return anything?
  232. }