props.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. /*
  2. * Copyright (c) 1983-2013 Martin Atkins, Richard Dobson and Composers Desktop Project Ltd
  3. * http://people.bath.ac.uk/masrwd
  4. * http://www.composersdesktop.com
  5. *
  6. This file is part of the CDP System.
  7. The CDP System is free software; you can redistribute it
  8. and/or modify it under the terms of the GNU Lesser General Public
  9. License as published by the Free Software Foundation; either
  10. version 2.1 of the License, or (at your option) any later version.
  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. See the
  14. 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
  18. 02111-1307 USA
  19. *
  20. */
  21. /*props.c*/
  22. /*builtin- C version of props.cpp*/
  23. /*RWD.5.99 private version to support WAVE_EX*/
  24. /*RWD.5.99 NB NO SUPPORT FOR LONG INT FORMATS YET!*/
  25. /*RWD Feb 2014 release 7, added 6.1 speaker format */
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <sfsys.h>
  29. #include "sffuncs.h"
  30. #include "chanmask.h"
  31. char *props_errstr;
  32. int sf_headread(int fd,SFPROPS *props)
  33. {
  34. int srate,chans,samptype,origsize = 0,origrate=0,origchans = 0,dummy;
  35. float arate = (float)0.0;
  36. int wlen=0,dfac=0,specenvcnt = 0,checksum=0;
  37. channelformat chformat;
  38. props->window_size = 0.0f;
  39. props_errstr = NULL;
  40. if(props==NULL)
  41. return 0;
  42. if(fd <0){
  43. props_errstr = "Cannot read Soundfile: Bad Handle";
  44. return 0;
  45. }
  46. if(sfgetprop(fd,"sample rate", (char *)&srate, sizeof(int)) < 0) {
  47. props_errstr = "Failure to read sample rate";
  48. return 0;
  49. }
  50. if(sfgetprop(fd,"channels", (char *)&chans, sizeof(int)) < 0) {
  51. props_errstr ="Failure to read channel data";
  52. return 0;
  53. }
  54. if(sfgetprop(fd,"sample type", (char *)&samptype, sizeof(int)) < 0){
  55. props_errstr = "Failure to read sample size";
  56. return 0;
  57. }
  58. props->srate = srate;
  59. props->chans = chans;
  60. props->type = wt_wave;
  61. if(sf_getchanformat(fd,&chformat) < 0){
  62. props_errstr = "cannot find channel format information";
  63. return 0;
  64. }
  65. props->chformat = chformat;
  66. switch(samptype){
  67. case(SAMP_SHORT):
  68. props->samptype = SHORT16;
  69. break;
  70. case(SAMP_FLOAT):
  71. props->samptype = FLOAT32;
  72. break;
  73. case(SAMP_LONG):
  74. props->samptype = INT_32;
  75. break;
  76. case(SAMP_2432):
  77. props->samptype = INT2432;
  78. break;
  79. case(SAMP_2424):
  80. props->samptype = INT2424;
  81. break;
  82. case(SAMP_2024):
  83. props->samptype = INT2024;
  84. break;
  85. case(SAMP_MASKED):
  86. props->samptype = INT_MASKED;
  87. break;
  88. default:
  89. props_errstr = "unrecognised integer sample format";
  90. return 0;
  91. break;
  92. }
  93. /*now elaborate the format...*/
  94. if(chformat > STDWAVE && chformat != MC_BFMT){
  95. long chmask = sfgetchanmask(fd);
  96. /*we want to know the channel config, if any, and the brand of file*/
  97. if(chmask < 0) {
  98. props_errstr = "internal error: cannot read channel mask";
  99. return 0;
  100. }
  101. /*RWD Jan 2007 accept chancount > numbits set in speakermask */
  102. switch(chmask){
  103. /*check all cross-platform formats first...*/
  104. case(SPKRS_UNASSIGNED):
  105. props->chformat = MC_STD;
  106. break;
  107. case(SPKRS_MONO):
  108. if(props->chans==1)
  109. props->chformat = MC_MONO;
  110. else
  111. props->chformat = MC_WAVE_EX; /*something weird...*/
  112. break;
  113. case(SPKRS_STEREO):
  114. if(props->chans==2)
  115. props->chformat = MC_STEREO;
  116. else
  117. props->chformat = MC_WAVE_EX; /*something weird...*/
  118. break;
  119. case(SPKRS_GENERIC_QUAD):
  120. if(props->chans==4)
  121. props->chformat = MC_QUAD;
  122. else
  123. props->chformat = MC_WAVE_EX; /*something weird...*/
  124. break;
  125. case(SPKRS_SURROUND_LCRS):
  126. if(props->chans==4)
  127. props->chformat = MC_LCRS;
  128. else
  129. props->chformat = MC_WAVE_EX; /*something weird...*/
  130. break;
  131. case(SPKRS_DOLBY5_1):
  132. if(props->chans==6)
  133. props->chformat = MC_DOLBY_5_1;
  134. else
  135. props->chformat = MC_WAVE_EX; /*something weird...*/
  136. break;
  137. case(SPKRS_SURR_6_1):
  138. props->chformat = MC_SURR_6_1;
  139. break;
  140. case(SPKRS_SURR_7_1):
  141. props->chformat = MC_SURR_7_1;
  142. break;
  143. case(SPKRS_CUBE):
  144. props->chformat = MC_CUBE;
  145. break;
  146. default:
  147. props->chformat = MC_WAVE_EX; /*something weird... */
  148. break;
  149. }
  150. }
  151. if(props->samptype==FLOAT32) {
  152. /*we know we have floats: is it spectral file?*/
  153. if(sfgetprop(fd,"original sampsize",(char *)&origsize, sizeof(int))<0){
  154. props_errstr = "Failure to read original sample size";
  155. }
  156. if(sfgetprop(fd,"original sample rate",(char *)&origrate,sizeof(int))<0){
  157. props_errstr = "Failure to read original sample rate";
  158. }
  159. if(sfgetprop(fd,"arate",(char *)&arate,sizeof(float)) < 0){
  160. props_errstr = "Failure to read analysis sample rate";
  161. }
  162. if(sfgetprop(fd,"analwinlen",(char *)&wlen,sizeof(int)) < 0){
  163. props_errstr = "Failure to read analysis window length";
  164. }
  165. if(sfgetprop(fd,"decfactor",(char *)&dfac,sizeof(int)) < 0){
  166. props_errstr = "Failure to read decimation factor";
  167. }
  168. checksum = origsize + origrate + wlen + dfac + (int)arate;
  169. if(checksum==0) { /*its a wave file, or an envelope file*/
  170. int isenv = 0;
  171. float winsize;
  172. if(sfgetprop(fd,"is an envelope",(char *) &isenv,sizeof(int)) < 0){
  173. props_errstr = "Failure to read envelope property";
  174. }
  175. if(isenv){
  176. /*its an envelope file, get window size*/
  177. if(sfgetprop(fd,"window size",(char *)&winsize,sizeof(/*double*/float)) < 0) {
  178. props_errstr = "Error reading window size in envelope file";
  179. return 0;
  180. }
  181. props->window_size = /*(float)*/ winsize;
  182. props->type = wt_binenv;
  183. }
  184. /*return 1;*/
  185. /*tell props what brand of file this is - e.g WAVE_EX*/
  186. return (sfformat(fd,&props->format) == 0);
  187. }
  188. else {
  189. if(props_errstr==NULL){ /*its a good spectral file*/
  190. props->origsize = origsize;
  191. props->origrate = origrate;
  192. props->arate = arate;
  193. props->winlen = wlen; /*better be wlen+2 ?*/
  194. props->decfac = dfac;
  195. /*props.chans = (wlen+2)/2; //?? */
  196. if(sfgetprop(fd,"is a pitch file", (char *)&dummy, sizeof(int))>=0)
  197. props->type = wt_pitch;
  198. else if(sfgetprop(fd,"is a transpos file", (char *)&dummy, sizeof(int))>=0)
  199. props->type = wt_transposition;
  200. else if(sfgetprop(fd,"is a formant file", (char *)&dummy, sizeof(int))>=0)
  201. props->type = wt_formant;
  202. else
  203. props->type = wt_analysis;
  204. } else
  205. return 0; /*somehow, got a bad analysis file...*/
  206. }
  207. /* get any auxiliary stuff for control file*/
  208. /*adapted from TW's function in speclibg.cpp*/
  209. switch(props->type){
  210. case(wt_formant):
  211. if(sfgetprop(fd,"specenvcnt",(char *)&specenvcnt,sizeof(int)) < 0){
  212. props_errstr = "Failure to read formant size in formant file";
  213. return 0;
  214. }
  215. props->specenvcnt = specenvcnt;
  216. case(wt_pitch):
  217. case(wt_transposition):
  218. if(props->chans != 1){ /*RWD: this makes old-style files illegal!*/
  219. props_errstr = "Channel count does not equal to 1 formant,pitch or transposition file";
  220. return 0;
  221. }
  222. if(sfgetprop(fd,"orig channels", (char *)&origchans, sizeof(int)) < 0) {
  223. props_errstr = "Failure to read original channel data in formant,pitch or transposition file";
  224. return 0;
  225. }
  226. props->origchans = origchans;
  227. break;
  228. default:
  229. break;
  230. }
  231. /*for a spectral or binenv file, we say standard channel format*/
  232. props->chformat = STDWAVE; /*might be MC_STD in due course!*/
  233. }
  234. /*return 1;*/
  235. /*tell props what brand of file this is - e.g WAVE_EX*/
  236. return (sfformat(fd,&props->format) == 0);
  237. }
  238. int snd_headread(int fd,SFPROPS *props)
  239. {
  240. int srate,chans,samptype,origsize = 0,origrate = 0, origchans = 0,dummy;
  241. float arate = (float)0.0;
  242. int wlen=0,dfac=0,specenvcnt = 0,checksum=0;
  243. channelformat chformat;
  244. props->window_size = 0.0f;
  245. props_errstr = NULL;
  246. if(props==NULL)
  247. return 0;
  248. if(fd <0){
  249. props_errstr = "Bad Soundfile Handle";
  250. return 0;
  251. }
  252. if(sndgetprop(fd,"sample rate", (char *)&srate, sizeof(int)) < 0) {
  253. props_errstr = "Failure to read sample rate";
  254. return 0;
  255. }
  256. if(sndgetprop(fd,"channels", (char *)&chans, sizeof(int)) < 0) {
  257. props_errstr ="Failure to read channel data";
  258. return 0;
  259. }
  260. if(sndgetprop(fd,"sample type", (char *)&samptype, sizeof(int)) < 0){
  261. props_errstr = "Failure to read sample size";
  262. return 0;
  263. }
  264. props->srate = srate;
  265. props->chans = chans;
  266. props->type = wt_wave;
  267. if(snd_getchanformat(fd,&chformat) < 0){
  268. props_errstr = "cannot find channel format information";
  269. return 0;
  270. }
  271. props->chformat = chformat;
  272. switch(samptype){
  273. case(SAMP_SHORT):
  274. props->samptype = SHORT16;
  275. break;
  276. case(SAMP_FLOAT):
  277. props->samptype = FLOAT32;
  278. break;
  279. case(SAMP_LONG):
  280. props->samptype = INT_32;
  281. break;
  282. case(SAMP_2432):
  283. props->samptype = INT2432;
  284. break;
  285. case(SAMP_2424):
  286. props->samptype = INT2424;
  287. break;
  288. case(SAMP_2024):
  289. props->samptype = INT2024;
  290. break;
  291. case(SAMP_MASKED):
  292. props->samptype = INT_MASKED;
  293. break;
  294. default:
  295. props_errstr = "unrecognised integer sample format";
  296. return 0;
  297. break;
  298. }
  299. /*now elaborate the format..*/
  300. if(chformat > STDWAVE && chformat != MC_BFMT){
  301. int chmask = sndgetchanmask(fd);
  302. /*we want to know the channel config, if any, and the brand of file */
  303. if(chmask < 0)
  304. return 0;
  305. switch(chmask){
  306. /*check all cross-platform formats first...*/
  307. case(SPKRS_UNASSIGNED):
  308. props->chformat = MC_STD;
  309. break;
  310. case(SPKRS_MONO):
  311. props->chformat = MC_MONO;
  312. break;
  313. case(SPKRS_STEREO):
  314. props->chformat = MC_STEREO;
  315. break;
  316. case(SPKRS_GENERIC_QUAD):
  317. props->chformat = MC_QUAD;
  318. break;
  319. case(SPKRS_SURROUND_LCRS):
  320. props->chformat = MC_LCRS;
  321. break;
  322. case(SPKRS_DOLBY5_1):
  323. props->chformat = MC_DOLBY_5_1;
  324. break;
  325. case(SPKRS_SURR_6_1):
  326. props->chformat = MC_SURR_6_1;
  327. break;
  328. case(SPKRS_SURR_7_1):
  329. props->chformat = MC_SURR_7_1;
  330. break;
  331. case(SPKRS_CUBE):
  332. props->chformat = MC_CUBE;
  333. break;
  334. default:
  335. props->chformat = MC_WAVE_EX; /*could be something weird from WAVE-EX...*/
  336. break;
  337. }
  338. }
  339. if(props->samptype==FLOAT32 || props->samptype== SAMP_LONG) {
  340. /*we know we have floats: is it spectral file?*/
  341. if(sndgetprop(fd,"original sampsize",(char *)&origsize, sizeof(int))<0){
  342. props_errstr = "Failure to read original sample size";
  343. }
  344. if(sndgetprop(fd,"original sample rate",(char *)&origrate,sizeof(int))<0){
  345. props_errstr = "Failure to read original sample rate";
  346. }
  347. if(sndgetprop(fd,"arate",(char *)&arate,sizeof(float)) < 0){
  348. props_errstr = "Failure to read analysis sample rate";
  349. }
  350. if(sndgetprop(fd,"analwinlen",(char *)&wlen,sizeof(int)) < 0){
  351. props_errstr = "Failure to read analysis window length";
  352. }
  353. if(sndgetprop(fd,"decfactor",(char *)&dfac,sizeof(int)) < 0){
  354. props_errstr = "Failure to read decimation factor";
  355. }
  356. /*TODO: find a way to guarantee unique checksums...*/
  357. checksum = origsize + origrate + wlen + dfac + (int)arate;
  358. if(checksum==0) { /*its a wave file*/
  359. int isenv = 0;
  360. float winsize;
  361. if(sndgetprop(fd,"is an envelope",(char *) &isenv,sizeof(int)) < 0){
  362. props_errstr = "Error looking for envelope property";
  363. }
  364. if(isenv){
  365. /*its an envelope file, get window size*/
  366. if(sndgetprop(fd,"window size",(char *)&winsize,sizeof(float)) < 0) {
  367. props_errstr = "Error reading window size in envelope file";
  368. return 0;
  369. }
  370. props->window_size = /*(float)*/ winsize;
  371. props->type = wt_binenv;
  372. /*must be floatsams, in this case*/
  373. props->samptype = /*SAMP_FLOAT;*/ FLOAT32; /* RWD July 2004 */
  374. /*and it won't (yet) be anything other than a standard file*/
  375. props->chformat = STDWAVE;
  376. }
  377. /*tell props what brand of file this is - e.g WAVE_EX*/
  378. return (snd_fileformat(fd,&props->format) == 0);
  379. }
  380. else {
  381. if(props_errstr==NULL){ /*its a good spectral file*/
  382. /*must be floatsams*/
  383. props->samptype= FLOAT32;
  384. props->origsize = origsize;
  385. props->origrate = origrate;
  386. props->arate = arate;
  387. props->winlen = wlen;
  388. props->decfac = dfac;
  389. if(sndgetprop(fd,"is a pitch file", (char *)&dummy, sizeof(int))>=0)
  390. props->type = wt_pitch;
  391. else if(sndgetprop(fd,"is a transpos file", (char *)&dummy, sizeof(int))>=0)
  392. props->type = wt_transposition;
  393. else if(sndgetprop(fd,"is a formant file", (char *)&dummy, sizeof(int))>=0)
  394. props->type = wt_formant;
  395. else
  396. props->type = wt_analysis;
  397. } else
  398. return 0; /*somehow, got a bad analysis file...*/
  399. }
  400. /* get any auxiliary stuff for control file */
  401. /* adapted from TW's function in speclibg.cpp */
  402. switch(props->type){
  403. case(wt_formant):
  404. if(sndgetprop(fd,"specenvcnt",(char *)&specenvcnt,sizeof(int)) < 0){
  405. props_errstr = "Failure to read formant size in formant file";
  406. return 0;
  407. }
  408. props->specenvcnt = specenvcnt;
  409. /* break; */ /*RWD July 2004*/
  410. case(wt_pitch):
  411. case(wt_transposition):
  412. if(props->chans != 1){
  413. props_errstr = "Channel count not equal to 1 in transposition file";
  414. return 0;
  415. }
  416. if(sndgetprop(fd,"orig channels", (char *)&origchans, sizeof(int)) < 0) {
  417. props_errstr = "Failure to read original channel data from transposition file";
  418. return 0;
  419. }
  420. props->origchans = origchans;
  421. break;
  422. default:
  423. break;
  424. }
  425. props->chformat = STDWAVE;
  426. }
  427. /*tell props what brand of file this is - e.g WAVE_EX*/
  428. return (snd_fileformat(fd,&props->format) == 0);
  429. }