roomresp.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713
  1. /*
  2. * Copyright (c) 1983-2013 Richard Dobson and Composers Desktop Project Ltd
  3. * http://people.bath.ac.uk/masrwd
  4. * http://www.composersdesktop.com
  5. * This file is part of the CDP System.
  6. * The CDP System is free software; you can redistribute it
  7. * and/or modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * The CDP System is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  14. * See the GNU Lesser General Public License for more details.
  15. * You should have received a copy of the GNU Lesser General Public
  16. * License along with the CDP System; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. *
  19. */
  20. /***********************************************************************
  21. Motorola
  22. Motorola does not assume any liability ...
  23. Author: Tom Zudock ([email protected])
  24. see:
  25. http://collaboration.cmc.ec.gc.ca/science/rpn/biblio/ddj/Website/articles/DDJ/1996/9612/9612d/9612d.htm
  26. Presented in Dr Dobbs Journal Vol21:12, December 1996.
  27. Filename: roomresp.cpp
  28. This program calculates the room response for a simple room. The output is not
  29. particularly delightful to listen to (it could sound phasey and
  30. have ringing due to the simple model used), but this program is the
  31. foundation for more complex virtual audio models which will eliminate
  32. these anomalies.
  33. Example form of the InputParametersTextFile:
  34. 0.5 # Input gain for data file (float)
  35. 1 # Open Path = 0 Closed Path = 1 (int)
  36. 6 5 4 # Room Dimensions (X,Y,Z) (float)
  37. 0.85 # Reflectivity of walls (float)
  38. 5 # Number of rooms per dimension, 1 or greater
  39. 2 3 2 # Listener coord (X,Y,Z) (float)
  40. 2 2 2 1 # Source coord and time at coord (X,Y,Z,t) (float)
  41. 3 2 2 1 # Source coord and time at coord (X,Y,Z,t) (float)
  42. 4 3 2 1 # Source coord and time at coord (X,Y,Z,t) (float)
  43. 3 4 2 1 # Source coord and time at coord (X,Y,Z,t) (float)
  44. 2 4 2 1 # Source coord and time at coord (X,Y,Z,t) (float)
  45. ***********************************************************************/
  46. // included header files
  47. #include <stdio.h>
  48. #include <stdlib.h>
  49. #include <math.h>
  50. //#include <process.h>
  51. #include <string.h>
  52. #ifdef _DEBUG
  53. #include <assert.h>
  54. #endif
  55. #include <vector>
  56. #include <algorithm>
  57. using namespace std;
  58. #ifndef _MAX
  59. #define _MAX(x,y) ((x) > (y) ? (x) : (y))
  60. #endif
  61. // macro defined constants
  62. //#define Vs 334.0
  63. static const double Vs = 334.0;
  64. static const double srate = 20000;
  65. #define PI 3.14159265359
  66. #define RefDist 1.0
  67. enum args {
  68. REFLECTIVITY,
  69. REFLECTIONS,
  70. R_X,
  71. R_Y,
  72. R_Z,
  73. S_X,
  74. S_Y,
  75. S_Z,
  76. L_X,
  77. L_Y,
  78. L_Z
  79. };
  80. // structure for a point in 3 dimensional space
  81. struct point {
  82. double X;
  83. double Y;
  84. double Z;
  85. point(){
  86. X = Y = Z = 0.0;
  87. }
  88. virtual ~point() {}
  89. };
  90. // structure for a point paired with a time duration
  91. struct position {
  92. point Coord;
  93. double Time;
  94. position *NextSource;
  95. };
  96. const char* cdp_version = "5.0.0";
  97. bool input_cmds(char *args[],int argc,point &room,point &source,point &listener,double &reflcoef,int &NR);
  98. void
  99. CalcImpResp(
  100. long *,
  101. double *,
  102. point &,
  103. point &,
  104. point &,
  105. double,
  106. double,
  107. int);
  108. position *
  109. InputParameters(
  110. FILE *,
  111. point &,
  112. // point &,
  113. point &,
  114. double &,
  115. double &,
  116. int &);
  117. void
  118. InputParamsError(
  119. int);
  120. //RWD stuff
  121. typedef struct deltap {
  122. long time;
  123. double val;
  124. } DELTAP;
  125. bool operator<(const DELTAP &a,const DELTAP &b)
  126. {
  127. return (a.time < b.time);
  128. }
  129. void usage() //RWD.1..12.98 left out flag -nNORM for now...
  130. {
  131. printf("\n********* ROOMRESP.EXE: by Tom Zudock CDP build 1998,1999 ******"
  132. "\n GENERATE ROOM-RESPONSE EARLY REFLECTIONS DATAFILE\n"
  133. "\nusage: roomresp [-aMAXAMP][-rRES] txtout.dat liveness nrefs "
  134. "\n roomL roomW roomH"
  135. "\n sourceL sourceW sourceH"
  136. "\n listenerL listenerW listenerH");
  137. printf("\ntxtout.dat: text outfile containing early reflections in brkpoint format"
  138. "\n suitable for input to rmverb, reverb or tdelay"
  139. "\nMAXAMP : peak amp for data (0.0 < MAXAMP <= 1.0; default 1.0)"
  140. "\nRES : time resolution for reflections in msecs"
  141. "\n (0.1 <= RES <= 2; default 0.1)"
  142. "\nliveness : degree of reflection from each surface (0 to 1; typ: 0.95)"
  143. "\nnrefs : number of reflections from each surface(nrefs > 0; typ: 2 to 5)"
  144. "\n (WARNING: high values will create extremely long data files!)"
  145. "\nROOM PARAMETERS:"
  146. "\nroomL roomW roomH : room size: (Length, Width, Height)"
  147. "\nsourceL sourceW ourceH : position of sound source (as above)"
  148. "\nlistenerL listenerW listenerH: position of listener (as above)"
  149. "\n all dimensions are in metres"
  150. "\nNB: first output time is non-zero."
  151. );
  152. }
  153. /***********************************************************************
  154. main
  155. The main program is responsible for the primary program flow.
  156. It contains the primary processing loop which calls subroutines
  157. to handle the specialized functionality.
  158. ***********************************************************************/
  159. int main (int argc, char **argv) {
  160. // FILE *PositionFile = 0; // input text parameters file
  161. //RWD to print earlies as text
  162. FILE *earliesFile = 0;
  163. #ifdef TESTING
  164. FILE *rawfile = 0; ///just for testing...raw output from impresp funtionm
  165. #endif
  166. int i,NR = 0; // num of mirrored rooms per dimension
  167. long *TapDelay = 0; // pointer to array of tap delays
  168. double Fs = 0.0; // the sampling frequency
  169. double *TapGain = 0; // pointer to array of tap gains
  170. double ReflCoef = 0.0; // the reflectivity of the walls
  171. // position *CurrentSource = 0; // current source in positions list
  172. point Room; // coords for the room size
  173. point Source; // coords of current sound source
  174. point Listener; // coords of the listener
  175. #ifdef _DEBUG
  176. bool write_c_struct = false;
  177. #endif
  178. bool do_normalize = true;
  179. double normfac = 1.0;
  180. double min_separation = 0.0001;
  181. if((argc==2) && strcmp(argv[1],"--version")==0) {
  182. fprintf(stdout,"%s\n",cdp_version);
  183. fflush(stdout);
  184. return 0;
  185. }
  186. if(argc==1){
  187. usage();
  188. exit(0);
  189. }
  190. if (argc < 13){
  191. fprintf(stderr,"\ninsufficient arguments\n");
  192. usage();
  193. exit(-1);
  194. }
  195. while(argc > 0 && argv[1][0]=='-'){
  196. double val;
  197. switch(argv[1][1]){
  198. #ifdef _DEBUG
  199. //my private facility...
  200. case('c'):
  201. write_c_struct = true;
  202. printf("\nwriting C-format file");
  203. break;
  204. #endif
  205. case('a'):
  206. if(argv[1][2]=='\0'){
  207. fprintf(stderr,"\n-a flag requires a value\n");
  208. usage();
  209. exit(1);
  210. }
  211. val = atof(&(argv[1][2]));
  212. #ifdef _DEBUG
  213. if(val <0.0 || val > 1.0){
  214. #else
  215. if(val <=0.0 || val > 1.0){
  216. #endif
  217. fprintf(stderr,"\n normalization value %lf out of range\n",val);
  218. usage();
  219. exit(1);
  220. }
  221. #ifdef _DEBUG
  222. if(val==0.0) {
  223. do_normalize = false;
  224. normfac = 1.0;
  225. printf("\nskipping normalization");
  226. }
  227. else
  228. #endif
  229. normfac = val;
  230. break;
  231. case('r'):
  232. if(argv[1][2]=='\0'){
  233. fprintf(stderr,"\n-r flag requires a value\n");
  234. usage();
  235. exit(1);
  236. }
  237. val = atof(&(argv[1][2]));
  238. if(val < 0.1 || val > 2.0) {
  239. fprintf(stderr,"\nvalue %.4lf for RES out of range\n",val);
  240. usage();
  241. exit(1);
  242. }
  243. else
  244. min_separation = val * 0.001;
  245. break;
  246. default:
  247. fprintf(stderr,"\nbad flag option\n");
  248. exit(1);
  249. break;
  250. }
  251. argc--;
  252. argv++;
  253. }
  254. //step along arglist:
  255. argc--; argv++;
  256. if(argc != 12){
  257. fprintf(stderr,"\nincorrect number of numeric arguments\n");
  258. usage();
  259. exit(1);
  260. }
  261. if((earliesFile = fopen(argv[0],"w"))==NULL){
  262. printf ("\nUnable to open %s for output\n",argv[2]);
  263. exit(-1);
  264. }
  265. #ifdef TESTING
  266. if((rawfile = fopen("rawdata.txt","w"))==NULL){
  267. printf ("Unable to open rawdata.txt for output\n");
  268. exit(-1);
  269. }
  270. #endif
  271. //step along again...
  272. argc--; argv++;
  273. //NB this sets the efective time-resolution for each tap, ie 1.0 / fs
  274. //so 1000 is a minimum, for 1msec resolution
  275. Fs = srate;
  276. if(!input_cmds(argv,argc,Room,Source,Listener,ReflCoef,NR))
  277. exit(1); //already got the errmsg
  278. if((TapDelay = new long[NR*NR*NR])==NULL) {
  279. printf("Error: Unable to allocate memory\n");
  280. exit(-1);
  281. }
  282. if((TapGain = new double[NR*NR*NR])==NULL) {
  283. printf("Error: Unable to allocate memory\n");
  284. exit(-1);
  285. }
  286. CalcImpResp(
  287. TapDelay,
  288. TapGain,
  289. Room,
  290. /*CurrentSource->Coord,*/Source,
  291. Listener,
  292. ReflCoef,
  293. Fs,
  294. NR);
  295. //sort deltaps, eliminate duplicates, write to file
  296. vector<DELTAP> vtaps;
  297. DELTAP thistap,prevtap;
  298. prevtap.time = 0;
  299. prevtap.val = 0.0;
  300. for(i = 0; i < NR*NR*NR;i++) {
  301. thistap.time = TapDelay[i];
  302. thistap.val =TapGain[i];
  303. #ifdef TESTING
  304. fprintf(rawfile,"%ld\t%.6lf\n",thistap.time,thistap.val);
  305. #endif
  306. //exclude tapval of 1.0: = direct sig at listening point
  307. if(thistap.val > 0.0 && thistap.val < 1.0) // get a problem in release build otherwise....
  308. vtaps.push_back(thistap);
  309. }
  310. //now we can sort them
  311. sort(vtaps.begin(),vtaps.end());
  312. vector<DELTAP>::iterator it;
  313. it = vtaps.begin();
  314. prevtap.time = it->time;
  315. prevtap.val = it->val;
  316. //print all taps as we got them, first!
  317. double maxval = 0.0;
  318. for(;it != vtaps.end();it++){
  319. #ifdef NOTDEF
  320. fprintf(earliesFile,"\n\t%.4lf\t%.6lf",(double)it->time / Fs,it->val);
  321. #endif
  322. maxval = _MAX(it->val,maxval);
  323. }
  324. #ifdef _DEBUG
  325. printf("\noverall maxamp = %.4lf",maxval);
  326. #endif
  327. //print first line, formatted for code
  328. //normalize all vals to max amplitude!
  329. if(do_normalize){
  330. normfac /= prevtap.val;
  331. #ifdef _DEBUG
  332. printf("\nnormalizing by %.4lf",normfac);
  333. #endif
  334. }
  335. it = vtaps.begin();
  336. //normfac= floor(normfac);
  337. #ifdef _DEBUG
  338. printf("\ninitial time= %ld, initial amp = %.4lf",it->time,it->val);
  339. //RWD private facility!
  340. if(write_c_struct){
  341. fprintf(earliesFile,"\n\n{\n\t{%.4lf,%.6lf}",(double)prevtap.time / Fs,prevtap.val * normfac);
  342. int count = 1;
  343. for(;it != vtaps.end();it++){
  344. //get maxamp of any taps sharing a time (to 5 sig figs) - or should I add them somehow?
  345. if(fabs(it->time - prevtap.time) < min_separation){
  346. it->val = _MAX(it->val,prevtap.val);
  347. continue;
  348. }
  349. fprintf(earliesFile,",\n\t{%.5lf,%.6lf}",(double)it->time / Fs,it->val * normfac);
  350. prevtap = *it;
  351. count++;
  352. }
  353. fprintf(earliesFile,"\n\t};\n\nNUMTAPS = %d\n",count);
  354. }
  355. else {
  356. #endif
  357. int count = 1;
  358. fprintf(earliesFile,"%.5lf\t%.6lf\n",(double)prevtap.time / Fs, prevtap.val * normfac);
  359. for(;it != vtaps.end();it++){
  360. if(fabs(it->time - prevtap.time) < min_separation){
  361. it->val = _MAX(it->val,prevtap.val);
  362. continue;
  363. }
  364. fprintf(earliesFile,"%.5lf\t%.6lf\n",(double)it->time / Fs, it->val * normfac);
  365. prevtap = *it;
  366. count++;
  367. }
  368. printf("\n\nNUMTAPS = %d\n",count);
  369. #ifdef _DEBUG
  370. }
  371. #endif
  372. fclose(earliesFile);
  373. #ifdef TESTING
  374. fclose(rawfile);
  375. #endif
  376. delete TapDelay,
  377. delete TapGain,
  378. printf ("done\n");
  379. return(0);
  380. }
  381. /***********************************************************************
  382. CalcImpResp
  383. This subroutine calculates the time delays (in samples) and
  384. attenuations for the early reflections in the room.
  385. ***********************************************************************/
  386. void
  387. CalcImpResp(
  388. long * TapDelay,
  389. double * TapGain,
  390. point & Room,
  391. point & Source,
  392. point & Listener,
  393. double ReflCoef,
  394. double Fs,
  395. int NR)
  396. {
  397. double Dist = 0.0; // distance travelled by sound ray
  398. double ReflOrd = 0.0; // reflection order of sound ray
  399. //RWD.11.98 need volatile, or VC++ optimizer does more bad things!
  400. volatile point MirrSource; // mirrored source x,y,z coords
  401. //RWD
  402. int NRovr2 = NR / 2;
  403. int index = 0;
  404. for (int i=-NRovr2;i<=NRovr2;i++) { // loop through all 3 dimensions
  405. for (int j=-NRovr2;j<=NRovr2;j++) {
  406. for (int k=-NRovr2;k<=NRovr2;k++) {
  407. // calc x,y,z sound source coords in mirrored room
  408. MirrSource.X = (i)*Room.X
  409. +fabs(((i)%2)*Room.X)
  410. +pow(-1,(i))*Source.X;
  411. MirrSource.Y = (j)*Room.Y
  412. +fabs(((j)%2)*Room.Y)
  413. +pow(-1,(j))*Source.Y;
  414. MirrSource.Z = (k)*Room.Z
  415. +fabs(((k)%2)*Room.Z)
  416. +pow(-1,(k))*Source.Z;
  417. // calculate distance to listener
  418. Dist = sqrt(pow(MirrSource.X-Listener.X,2)
  419. +pow(MirrSource.Y-Listener.Y,2)
  420. +pow(MirrSource.Z-Listener.Z,2));
  421. // calculate delayed arrival time of reflection
  422. //RWD problem with release build...
  423. index = (i+NRovr2)*NR*NR+(j+NRovr2)*NR+(k+NRovr2);
  424. //this also stopped the optimizer doing bad things....
  425. //if(index%NR==0)
  426. // printf("\nindex = %d\tX= %.4lf\tY=%.4lf\tZ=%.4lf\tDist = %.4lf",
  427. // index,MirrSource.X,MirrSource.Y,MirrSource.Z,Dist);
  428. TapDelay[index]=Dist/Vs*Fs;
  429. ReflOrd = abs(i)+abs(j)+abs(k);
  430. // calculate attenuation for the reflection
  431. //RWD div/zero avoidance:
  432. if(Dist==0.0)
  433. TapGain[index] = 1.0;
  434. else
  435. TapGain[index]= pow(RefDist/Dist,2.0)*pow(ReflCoef,ReflOrd);
  436. }
  437. }
  438. }
  439. }
  440. /***********************************************************************
  441. InputParameters
  442. This subroutine inputs parameters from a text file. An example of
  443. the format of the parameters file is below. It also checks the
  444. range of some of the parameters and creates a linked list representing
  445. how the sound source changes position in the modeled room.
  446. 0.5 # Input gain for data file (float)
  447. 1 # Open Path = 0 Closed Path = 1 (int)
  448. 6 5 4 # Room Dimensions (X,Y,Z) (float)
  449. 0.85 # Reflectivity of walls (float)
  450. 5 # Number of rooms per dimension, 1 or greater
  451. 2 3 2 # Listener coord (X,Y,Z) (float)
  452. 2 2 2 1 # Source coord and time at coord (X,Y,Z,t) (float)
  453. 3 2 2 1 # Source coord and time at coord (X,Y,Z,t) (float)
  454. 4 3 2 1 # Source coord and time at coord (X,Y,Z,t) (float)
  455. 3 4 2 1 # Source coord and time at coord (X,Y,Z,t) (float)
  456. 2 4 2 1 # Source coord and time at coord (X,Y,Z,t) (float)
  457. ***********************************************************************/
  458. position*
  459. InputParameters(
  460. FILE *PositionFile,
  461. point &Room,
  462. // point &Source,
  463. point &Listener,
  464. double &ReflCoef,
  465. double &InGain,
  466. int &NR)
  467. {
  468. position *First = new position,*Previous=First,*Next=Previous;
  469. int ClosedPath,LineCount=1;
  470. char StrLine[256];
  471. #define ReadParms(arg1) \
  472. if ((fgets(StrLine,256,PositionFile)) != NULL) { \
  473. if (arg1) \
  474. LineCount++; \
  475. else \
  476. InputParamsError(LineCount); \
  477. } \
  478. else \
  479. InputParamsError(0);
  480. #ifdef _DEBUG
  481. assert(PositionFile);
  482. #endif
  483. ReadParms(sscanf(StrLine,"%le",&InGain)==1)
  484. ReadParms(sscanf(StrLine,"%d",&ClosedPath)==1)
  485. ReadParms(sscanf(StrLine,"%le %le %le",&Room.X,&Room.Y,&Room.Z)==3)
  486. ReadParms(sscanf(StrLine,"%le",&ReflCoef)==1)
  487. ReadParms(sscanf(StrLine,"%d",&NR)==1)
  488. ReadParms(sscanf(StrLine,"%le %le %le",&Listener.X,&Listener.Y,&Listener.Z)==3)
  489. if (NR%2 != 1) {
  490. printf ("Error: The number of reflected rooms per dimension must be odd (for symmetry)\n");
  491. exit(-1);
  492. }
  493. //RWD!!! was bitwise OR: '|'
  494. if ((Listener.Y > Room.Y)||(Listener.X > Room.X)) { // Check listener position
  495. printf ("Error: Listener position puts listener outside of room \n");
  496. exit(-1);
  497. }
  498. // Choose a default position for listener
  499. //RWD check this! am I always getting these setings????
  500. First->Coord.X = Room.X/2;
  501. First->Coord.Y = Room.Y/2;
  502. First->Coord.Z = Room.Z/2;
  503. First->Time = 0;
  504. First->NextSource=NULL;
  505. while (feof(PositionFile)==0) {
  506. if ((fgets(StrLine,256,PositionFile)) != NULL) {
  507. if(sscanf(StrLine,"%le %le %le %le",&(Next->Coord.X),&(Next->Coord.Y),&(Next->Coord.Z),&(Next->Time))==4) {
  508. Next->NextSource = new position;
  509. Previous = Next;
  510. Next = Next->NextSource;
  511. LineCount++;
  512. }
  513. else {
  514. InputParamsError(LineCount);
  515. }
  516. }
  517. }
  518. delete (Previous->NextSource);
  519. if (ClosedPath)
  520. Previous->NextSource=First;
  521. else
  522. Previous->NextSource=NULL;
  523. return(First);
  524. }
  525. //RWD get params from cmdline: refl,nrefs,rX,rY,rZ,sX,sY,sZ,lX,lY,lZ
  526. //fix ingain at 1.0
  527. bool input_cmds(char *args[],int argc,point &room,point &source,point &listener,double &reflcoef,int &NR)
  528. {
  529. double dval;
  530. int ival;
  531. #ifdef _DEBUG
  532. assert(argc==11);
  533. #endif
  534. if(argc != 11)
  535. return false;
  536. dval = atof(args[REFLECTIVITY]);
  537. if(dval <= 0.0 || dval > 1.0){
  538. fprintf(stderr,"\nbad value for liveliness\n");
  539. return false;
  540. }
  541. reflcoef = dval;
  542. ival = atoi(args[REFLECTIONS]);
  543. if(ival < 1){
  544. fprintf(stderr,"\nbad value for nrefs\n");
  545. return false;
  546. }
  547. NR = 1 + (2* ival);
  548. room.X = atof(args[R_X]);
  549. if(room.X <= 0.0){
  550. fprintf(stderr,"\nbad size for roomX\n");
  551. return false;
  552. }
  553. room.Y = atof(args[R_Y]);
  554. if(room.Y <= 0.0){
  555. fprintf(stderr,"\nbad size for roomY\n");
  556. return false;
  557. }
  558. room.Z = atof(args[R_Z]);
  559. if(room.Z <= 0.0){
  560. fprintf(stderr,"\nbad size for roomZ\n");
  561. return false;
  562. }
  563. listener.X = atof(args[L_X]);
  564. if(listener.X < 0.0){
  565. fprintf(stderr,"\nbad size for listenerX\n");
  566. return false;
  567. }
  568. listener.Y = atof(args[L_Y]);
  569. if(listener.Y < 0.0){
  570. fprintf(stderr,"\nbad size for listenerY\n");
  571. return false;
  572. }
  573. listener.Z = atof(args[L_Z]);
  574. if(listener.Z < 0.0){
  575. fprintf(stderr,"\nbad size for listenerZ\n");
  576. return false;
  577. }
  578. if ((listener.Y > room.Y)||(listener.X > room.X)|| (listener.Z > room.Z)) { // Check listener position
  579. printf ("\nError: Listener position puts listener outside room\n");
  580. return false;
  581. }
  582. source.X = atof(args[S_X]);
  583. if(source.X <= 0.0){
  584. fprintf(stderr,"\nbad size for sourceX\n");
  585. return false;
  586. }
  587. source.Y = atof(args[S_Y]);
  588. if(source.X <= 0.0){
  589. fprintf(stderr,"\nbad size for sourceY\n");
  590. return false;
  591. }
  592. source.Z = atof(args[S_Z]);
  593. if(source.X <= 0.0){
  594. fprintf(stderr,"\nbad size for sourceX\n");
  595. return false;
  596. }
  597. if ((source.Y > room.Y)||(source.X > room.X)|| (source.Z > room.Z)) { // Check source position
  598. printf ("\nError: Source position puts source outside room\n");
  599. return false;
  600. }
  601. return true;
  602. }
  603. /***********************************************************************
  604. InputParamsError
  605. This subroutine outputs an text error message to standard output
  606. when an error is encountered in the InputParams subroutine. The
  607. error text that is output is selected by the line number of the
  608. input parameters file where the error occured.
  609. ***********************************************************************/
  610. void
  611. InputParamsError(
  612. int ErrNum)
  613. {
  614. char ErrorStr[][256] = {
  615. "Error: EOF reached before all parameters input\n",
  616. "Error: Line %d requires 1 parameter the gain for the input file\n",
  617. "Error: Line %d requires 1 parameter (0 or 1): 0=closed path, 1=open path\n",
  618. "Error: Line %d requires 3 parameters (X,Y,Z): the room dimensions\n",
  619. "Error: Line %d requires 1 parameter the wall refelctivity\n",
  620. "Error: Line %d requires 1 parameter the number of mirrored rooms per dimension\n",
  621. "Error: Line %d requires 3 parameters (X,Y,Z): the listeners position\n",
  622. "Error: Line %d requires 4 parameters (X,Y,Z,t): sound position position and time\n"};
  623. if (ErrNum < 7)
  624. printf(ErrorStr[ErrNum],ErrNum);
  625. else
  626. printf(ErrorStr[7],ErrNum);
  627. exit(-1);
  628. }