dshift.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. /*
  2. *
  3. This file is part of the CDP System.
  4. The CDP System is free software; you can redistribute it
  5. and/or modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The CDP System is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the CDP System; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  15. 02111-1307 USA
  16. *
  17. */
  18. /**************
  19. DSHIFT.C
  20. Version 2.1
  21. REVISED 29/12/05
  22. Calculates Doppler shift for a source moving with a velocity
  23. Vs between two speakers that are 10m appart and a listener
  24. that is at rest, 5m from the line between them.
  25. It uses data similar to pan, when -1 means left and
  26. 1 means right.
  27. If the frequency of the source is f and the frequency
  28. perceived by the listener is f'
  29. then f'/f = ( 1 + Vs*cosA/V )
  30. where
  31. V = 331.45 speed of sound in air
  32. Vs = -(distance between speakers / 2) *
  33. (next pan position - current pan position) /
  34. (next point in time - current point in time)
  35. cosA = current pan position/ (1 + (current pan pos)^2 ) ^ 1/2
  36. is the angle between the speed of the source
  37. and the line joining the listener and the source.
  38. Finally, it converts f'/f into semitone shift by means of
  39. semitone shift = 12 * log( f'/f ) / log2
  40. The program can be called by name with no parameters, in which
  41. case it will start asking questions.
  42. Alternatively it can be called using the command
  43. dshift [-d] infile outfile [distance_between_speakers]
  44. where -d is a flag setting the time it takes an object to change direction
  45. This is useful in order to avoid clicks. N is the time in milliseconds.
  46. Default: 10ms
  47. default distance between speakers = 10 m
  48. Copyright (c) Rajmil Fischman. Keele 1994.
  49. *******************/
  50. #include <stdio.h>
  51. #include <stdlib.h>
  52. #include <math.h>
  53. #include <string.h>
  54. #define VSOUND 341.45 /* speed of sound in air */
  55. #define LOG2 log(2.0)
  56. //RWD cannot allocate 2^32 bytes!
  57. #define MAXMEMORY /*INT_MAX*/ (1024*1024) /* maximum memory to allocate */
  58. #define MINMEMORY 512 /* minimum memory needed */
  59. void usage(void);
  60. void calculate(void);
  61. void output(long);
  62. void* getbpbuf(void);
  63. long input(char*,char*);
  64. typedef struct brpts {
  65. double time;
  66. double param;
  67. } BREAKPOINTS;
  68. BREAKPOINTS *bp;
  69. FILE *ifp; /* input file pointer */
  70. FILE *ofp; /* output file pointer */
  71. long total; /* total entries */
  72. long maxentr; /* maximum entries */
  73. double spdist = 10.0; /* distance between speakers */
  74. double turn_time = 0.01; /* turning time delay */
  75. double vs; /* source velocity */
  76. double ccosa; /* current cosA */
  77. double ncosa; /* next cosA */
  78. double cfrat; /* current f'/f */
  79. double nfrat; /* next f'/f */
  80. double cstshift; /* currentsemitone shift */
  81. double nstshift; /* next semitone shift */
  82. const char* cdp_version = "7.1.1";
  83. int
  84. main(int argc,char* argv[])
  85. {
  86. char inname[2048];
  87. char outname[2048];
  88. if((argc==2) && strcmp(argv[1],"--version")==0) {
  89. fprintf(stdout,"%s\n",cdp_version);
  90. fflush(stdout);
  91. return 0;
  92. }
  93. /* if not enough parameters */
  94. if((argc < 3) || (argc == 3 && argv[1][2]=='-' && argv[1][1]=='d'))
  95. {
  96. usage();
  97. return 1;
  98. }
  99. /* if there is a flag */
  100. if(argv[1][0]=='-' && argv[1][1] == 'd')
  101. {
  102. /* get turning time */
  103. turn_time = atof(&argv[1][2]);
  104. // REW make msecs to secs
  105. if(turn_time < 0.0){
  106. printf("Error: turn-time cannot be negative!\n");
  107. return 1;
  108. }
  109. turn_time *= 0.001;
  110. /* get soundfile names */
  111. strcpy(&inname[0],argv[2]);
  112. strcpy(&outname[0],argv[3]);
  113. /* get speaker distance if needed */
  114. if(argc > 4)
  115. spdist = atof(argv[4]);
  116. }
  117. else
  118. {
  119. /* get soundfile names only */
  120. strcpy(&inname[0],argv[1]);
  121. strcpy(&outname[0],argv[2]);
  122. /* get speaker distance if needed */
  123. if(argc > 3)
  124. spdist = atof(argv[3]);
  125. }
  126. /* print info */
  127. fprintf(stderr,"turning time = %7.3lf sec.\t",turn_time);
  128. fprintf(stderr,"speakers distance = %7.2lf m\n",spdist);
  129. /* allocate memory, get input, calculate Doppler and write to output */
  130. if(getbpbuf()!=NULL && input(inname,outname)>0)
  131. {
  132. calculate();
  133. free(bp);
  134. }
  135. //RWD close outfile!
  136. if(ofp)
  137. fclose(ofp);
  138. return 0;
  139. }
  140. void
  141. usage(void)
  142. {
  143. fprintf(stderr,"CDP Release 5 2005\n");
  144. fprintf(stderr,"USAGE:\tdshift [-dN] infile outfile [distance between speakers]\n\n");
  145. fprintf(stderr,"Calculates Doppler shift for a source moving between two speakers\n"
  146. "that are 10m apart and a listener that is at rest,\n"
  147. "5m from the line between them.\n");
  148. fprintf(stderr,"infile is the pan breakpoint file, as used with modify:pan\n"
  149. "outfile is breakpoint file of semitone shifts\n"
  150. "to give to modify:speed, Mode 2(semitones).\n");
  151. fprintf(stderr,"(NB: modify:pan range: -1 = full left, 1 = full right)\n");
  152. fprintf(stderr,"-d is a flag setting the time it takes a sound to change direction.\n");
  153. fprintf(stderr,"N is the time in milliseconds. Default: 10ms\n");
  154. fprintf(stderr,"This is useful in order to avoid clicks.\n");
  155. }
  156. void*
  157. getbpbuf(void)
  158. {
  159. size_t size = MAXMEMORY;
  160. void *p;
  161. do
  162. {
  163. if((p=malloc(size)) == NULL )
  164. {
  165. if(size<MINMEMORY)
  166. fprintf(stderr,"Cannot allocate memory for breakpoints");
  167. }
  168. else
  169. break;
  170. size >>=1;
  171. } while (size>MINMEMORY);
  172. bp = (BREAKPOINTS*)p;
  173. maxentr = size/sizeof(BREAKPOINTS);
  174. return((void*)bp);
  175. }
  176. void
  177. calculate(void)
  178. {
  179. long i;
  180. double deltaTime;
  181. /* calculate cosine of next angle */
  182. ncosa = bp[0].param/sqrt(1+bp[0].param*bp[0].param);
  183. output(-1);
  184. for( i=0 ; i<total-1 ; i++ )
  185. {
  186. /* avoid division by zero */
  187. deltaTime = (bp[i+1].time-bp[i].time);
  188. if(deltaTime <= 0)
  189. deltaTime = 0.0000001;
  190. /* calculate speed */
  191. vs = - (spdist/2) * (bp[i+1].param-bp[i].param) / deltaTime;
  192. /* Cap maximum speed to avoid values higher than the speed of sound */
  193. if( vs >= VSOUND )
  194. vs = 0.999 * VSOUND;
  195. else if( vs <= -VSOUND )
  196. vs = -0.999 * VSOUND;
  197. /* calculate cosine of current angle */
  198. ccosa = ncosa;
  199. /* calculate cosine of next angle */
  200. ncosa = bp[i+1].param/sqrt(1+bp[i+1].param*bp[i+1].param);
  201. /* calculate current and next frequency ratio */
  202. cfrat = 1 + vs*ccosa/VSOUND;
  203. nfrat = 1 + vs*ncosa/VSOUND;
  204. /* convert these into semitones */
  205. cstshift = 12 * log(cfrat)/LOG2;
  206. nstshift = 12 * log(nfrat)/LOG2;
  207. /* write to file and to standard output */
  208. output(i);
  209. }
  210. fprintf(stderr,"\nread %ld breakpoints\n",i+1);
  211. }
  212. /*
  213. INPUT()
  214. Open and read input file. Open output file
  215. */
  216. long
  217. input(char *inname,char *outname)
  218. {
  219. //static char first = 1;
  220. if((ifp=fopen(inname,"ra")) == NULL )
  221. {
  222. fprintf(stderr,"Cannot open input file %s\n",inname);
  223. return(0);
  224. }
  225. for( total=0 ; total< maxentr ; total++ )
  226. {
  227. int got;
  228. got = fscanf(ifp,"%lf%lf",&(bp[total].time),&(bp[total].param));
  229. if(got < 2 || bp[total].time < 0.0 || feof(ifp) != 0 )
  230. break;
  231. }
  232. //RWD
  233. fprintf(stderr,"read %ld breakpoints\n",total);
  234. fclose(ifp);
  235. if((ofp=fopen(outname,"wa")) == NULL )
  236. fprintf(stderr,"Cannot open output file %s\n",outname);
  237. return(1);
  238. }
  239. /*
  240. OUTPUT()
  241. Write to output file and standard output
  242. */
  243. void
  244. output(long i)
  245. {
  246. static int add = 0; /* variable used to avoid adding the turining time
  247. to the first pair of points */
  248. if( i<0 )
  249. {
  250. // fprintf(stderr,"\n\n TIME\t PAN\t VS\t COS(A)\t F'/F\tSEMITONES\n\n");
  251. return;
  252. }
  253. /* else if (i<total-1)
  254. {
  255. fprintf(stderr,"%- 7.3lf\t%- 7.3lf\t%- 7.3lf\t%- 7.3lf\t%- 7.6lf\t%- 7.6lf\t\n",
  256. bp[i].time+add*turn_time,bp[i].param,vs,ccosa,cfrat,cstshift);
  257. fprintf(stderr,"%- 7.3lf\t%- 7.3lf\t%- 7.3lf\t%- 7.3lf\t%- 7.6lf\t%- 7.6lf\t\n",
  258. bp[i+1].time,bp[i+1].param,vs,ncosa,nfrat,nstshift); }
  259. else
  260. fprintf(stderr,"%- 7.3lf\t%- 7.3lf\t%- 7.3lf\t%- 7.3lf\t%- 7.6lf\t%- 7.6lf\t\n",
  261. bp[i].time+add*turn_time,bp[i].param,vs,ccosa,cfrat,cstshift);
  262. */
  263. if(ofp!=NULL)
  264. {
  265. fprintf(ofp,"%lf\t%lf\n",bp[i].time+add*turn_time,cstshift);
  266. fprintf(ofp,"%lf\t%lf\n",bp[i+1].time,nstshift);
  267. }
  268. add = 1;
  269. }