props.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  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.cpp: adapted from speclib3.c
  22. * NB this is now real C++ code, not C!
  23. *
  24. */
  25. //LATEST VERSION OCT97: supercedes all previous!
  26. //can I make this fully portable to both graphic and console apps?
  27. //TODO: Feb 2014: replace sizeof(long) with sizeof(int) everywhere!
  28. #include "stdafx.h" //for MFC: def of BOOL, TRUE, FALSE, etc
  29. //#include <propobjs.h>
  30. //use multi-threaded version of sfsys.lib
  31. extern "C" {
  32. #include <sfsys.h>
  33. }
  34. #include "props.h"
  35. char *props_errstr = NULL;
  36. //RWD TODO: also need a copy constructor...
  37. /***************************** HEADREAD *******************************
  38. *
  39. * Read input analysis file header data.
  40. */
  41. //RWD TODO: see Holub: props MUST be a pointer, not ref
  42. BOOL sfheadread(int fd,SFPROPS &props)
  43. {
  44. long srate,chans,samptype,origsize = 0,origrate=0,origchans = 0,dummy;
  45. float arate = (float)0.0;
  46. int wlen=0,dfac=0,specenvcnt = 0,checksum=0;
  47. props_errstr = NULL;
  48. if(fd <0){
  49. props_errstr = "Cannot read Soundfile: Bad Handle";
  50. return FALSE;
  51. }
  52. if(sfgetprop(fd,"sample rate", (char *)&srate, sizeof(long)) < 0) {
  53. props_errstr = "Failure to read sample rate";
  54. return FALSE;
  55. }
  56. if(sfgetprop(fd,"channels", (char *)&chans, sizeof(long)) < 0) {
  57. props_errstr ="Failure to read channel data";
  58. return FALSE;
  59. }
  60. if(sfgetprop(fd,"sample type", (char *)&samptype, sizeof(long)) < 0){
  61. props_errstr = "Failure to read sample size";
  62. return FALSE;
  63. }
  64. if(!(samptype==SAMP_SHORT || samptype== SAMP_FLOAT)){
  65. props_errstr = "unsupported sample type";
  66. return FALSE;
  67. }
  68. props.srate = srate;
  69. props.chans = chans;
  70. if(samptype == SAMP_SHORT || samptype == SAMP_FLOAT){
  71. props.type = wt_wave;
  72. props.samptype = (samptype == SAMP_SHORT ? SHORT16 : FLOAT32);
  73. }
  74. if(props.samptype==FLOAT32) {
  75. //we know we have floats: is it spectral file?
  76. if(sfgetprop(fd,"original sampsize",(char *)&origsize, sizeof(long))<0){
  77. props_errstr = "Failure to read original sample size";
  78. }
  79. if(sfgetprop(fd,"original sample rate",(char *)&origrate,sizeof(long))<0){
  80. props_errstr = "Failure to read original sample rate";
  81. }
  82. if(sfgetprop(fd,"arate",(char *)&arate,sizeof(float)) < 0){
  83. props_errstr = "Failure to read analysis sample rate";
  84. }
  85. if(sfgetprop(fd,"analwinlen",(char *)&wlen,sizeof(int)) < 0){
  86. props_errstr = "Failure to read analysis window length";
  87. }
  88. if(sfgetprop(fd,"decfactor",(char *)&dfac,sizeof(int)) < 0){
  89. props_errstr = "Failure to read decimation factor";
  90. }
  91. checksum = origsize + origrate + wlen + dfac + (int)arate;
  92. if(checksum==0) //its a wave file
  93. return TRUE;
  94. else {
  95. if(props_errstr==NULL){ //its a good spectral file
  96. props.origsize = origsize;
  97. props.origrate = origrate;
  98. props.arate = arate;
  99. props.winlen = wlen; //better be wlen+2 ?
  100. props.decfac = dfac;
  101. //props.chans = (wlen+2)/2; //??
  102. if(sfgetprop(fd,"is a pitch file", (char *)&dummy, sizeof(long))>=0)
  103. props.type = wt_pitch;
  104. else if(sfgetprop(fd,"is a transpos file", (char *)&dummy, sizeof(long))>=0)
  105. props.type = wt_transposition;
  106. else if(sfgetprop(fd,"is a formant file", (char *)&dummy, sizeof(long))>=0)
  107. props.type = wt_formant;
  108. else
  109. props.type = wt_analysis;
  110. } else
  111. return FALSE; //somehow, got a bad analysis file...
  112. }
  113. // get any auxiliary stuff for control file
  114. //adapted from TW's function in speclibg.cpp
  115. switch(props.type){
  116. case(wt_formant):
  117. if(sfgetprop(fd,"specenvcnt",(char *)&specenvcnt,sizeof(int)) < 0){
  118. props_errstr = "Failure to read formant size in formant file";
  119. return FALSE;
  120. }
  121. props.specenvcnt = specenvcnt;
  122. break;
  123. case(wt_pitch):
  124. case(wt_transposition):
  125. if(props.chans != 1){ //RWD: this makes old-style files illegal!
  126. props_errstr = "Channel count does not equal to 1 in transposition file";
  127. return FALSE;
  128. }
  129. if(sfgetprop(fd,"orig channels", (char *)&origchans, sizeof(long)) < 0) {
  130. props_errstr = "Failure to read original channel data from transposition file";
  131. return FALSE;
  132. }
  133. props.origchans = origchans;
  134. break;
  135. default:
  136. break;
  137. }
  138. }
  139. return TRUE;
  140. }
  141. BOOL sndheadread(int fd,SFPROPS &props)
  142. {
  143. long srate,chans,samptype,origsize = 0,origrate = 0, origchans = 0,dummy;
  144. float arate = (float)0.0;
  145. int wlen=0,dfac=0,specenvcnt = 0,checksum=0;
  146. props_errstr = NULL;
  147. if(fd <0){
  148. props_errstr = "Bad Soundfile Handle";
  149. return FALSE;
  150. }
  151. if(sndgetprop(fd,"sample rate", (char *)&srate, sizeof(long)) < 0) {
  152. props_errstr = "Failure to read sample rate";
  153. return FALSE;
  154. }
  155. if(sndgetprop(fd,"channels", (char *)&chans, sizeof(long)) < 0) {
  156. props_errstr ="Failure to read channel data";
  157. return FALSE;
  158. }
  159. if(sndgetprop(fd,"sample type", (char *)&samptype, sizeof(long)) < 0){
  160. props_errstr = "Failure to read sample size";
  161. return FALSE;
  162. }
  163. if(!(samptype==SAMP_SHORT || samptype== SAMP_FLOAT)){
  164. props_errstr = "unsupported sample type";
  165. return FALSE;
  166. }
  167. props.srate = srate;
  168. props.chans = chans;
  169. if(samptype == SAMP_SHORT || samptype== SAMP_FLOAT){
  170. props.type = wt_wave;
  171. props.samptype = (samptype == SAMP_SHORT ? SHORT16 : FLOAT32);
  172. }
  173. if(props.samptype==FLOAT32) {
  174. //we know we have floats: is it spectral file?
  175. if(sndgetprop(fd,"original sampsize",(char *)&origsize, sizeof(long))<0){
  176. props_errstr = "Failure to read original sample size";
  177. }
  178. if(sndgetprop(fd,"original sample rate",(char *)&origrate,sizeof(long))<0){
  179. props_errstr = "Failure to read original sample rate";
  180. }
  181. if(sndgetprop(fd,"arate",(char *)&arate,sizeof(float)) < 0){
  182. props_errstr = "Failure to read analysis sample rate";
  183. }
  184. if(sndgetprop(fd,"analwinlen",(char *)&wlen,sizeof(int)) < 0){
  185. props_errstr = "Failure to read analysis window length";
  186. }
  187. if(sndgetprop(fd,"decfactor",(char *)&dfac,sizeof(int)) < 0){
  188. props_errstr = "Failure to read decimation factor";
  189. }
  190. //TODO: find a way to guarantee unique checksums...
  191. checksum = origsize + origrate + wlen + dfac + (int)arate;
  192. if(checksum==0) //its a wave file
  193. return TRUE;
  194. else {
  195. if(props_errstr==NULL){ //its a good spectral file
  196. props.origsize = origsize;
  197. props.origrate = origrate;
  198. props.arate = arate;
  199. props.winlen = wlen;
  200. props.decfac = dfac;
  201. //props.chans = (wlen+2)/2; //??
  202. if(sndgetprop(fd,"is a pitch file", (char *)&dummy, sizeof(long))>=0)
  203. props.type = wt_pitch;
  204. else if(sndgetprop(fd,"is a transpos file", (char *)&dummy, sizeof(long))>=0)
  205. props.type = wt_transposition;
  206. else if(sndgetprop(fd,"is a formant file", (char *)&dummy, sizeof(long))>=0)
  207. props.type = wt_formant;
  208. else
  209. props.type = wt_analysis;
  210. } else
  211. return FALSE; //somehow, got a bad analysis file...
  212. }
  213. // get any auxiliary stuff for control file
  214. //adapted from TW's function in speclibg.cpp
  215. switch(props.type){
  216. case(wt_formant):
  217. if(sndgetprop(fd,"specenvcnt",(char *)&specenvcnt,sizeof(int)) < 0){
  218. props_errstr = "Failure to read formant size in formant file";
  219. return FALSE;
  220. }
  221. props.specenvcnt = specenvcnt;
  222. break;
  223. case(wt_pitch):
  224. case(wt_transposition):
  225. if(props.chans != 1){
  226. props_errstr = "Channel count not equal to 1 in transposition file";
  227. return FALSE;
  228. }
  229. if(sndgetprop(fd,"orig channels", (char *)&origchans, sizeof(long)) < 0) {
  230. props_errstr = "Failure to read original channel data from transposition file";
  231. return FALSE;
  232. }
  233. props.origchans = origchans;
  234. break;
  235. default:
  236. break;
  237. }
  238. }
  239. return TRUE;
  240. }
  241. // next is for SOUND files only...
  242. //TODO: full support for analysis and control files!
  243. BOOL sfwave_headwrite(int fd,const SFPROPS &props)
  244. {
  245. #ifdef _DEBUG
  246. ASSERT(fd >= 0);
  247. ASSERT(props.samptype==SHORT16 || props.samptype==FLOAT32);
  248. ASSERT(props.srate > 0);
  249. ASSERT(props.chans > 0);
  250. #endif
  251. int srate = props.srate;
  252. int chans = props.chans;
  253. int samptype;
  254. if(fd <0){
  255. props_errstr = "Cannot write soundfile: bad Handle";
  256. return FALSE;
  257. }
  258. if(props.type == wt_wave)
  259. samptype = (props.samptype == SHORT16 ? SAMP_SHORT : SAMP_FLOAT); //within sfsys,mostly safe assumption...
  260. else {
  261. props_errstr = "Not a wave file";
  262. return FALSE;
  263. }
  264. if(sfputprop(fd,"sample rate", (char *)&srate, sizeof(long)) < 0) {
  265. props_errstr = "Failure to write sample rate";
  266. return FALSE;
  267. }
  268. if(sfputprop(fd,"channels", (char *)&chans, sizeof(long)) < 0) {
  269. props_errstr ="Failure to write channel data";
  270. return FALSE;
  271. }
  272. if(sfputprop(fd,"sample type", (char *)&samptype, sizeof(long)) < 0){
  273. props_errstr = "Failure to write sample size";
  274. return FALSE;
  275. }
  276. return TRUE;
  277. }
  278. fileprops::~fileprops()
  279. {
  280. }
  281. fileprops::fileprops()
  282. {
  283. srate = 0L;
  284. stype = -1L;
  285. filetype = UNKNOWN;
  286. channels = 0L;
  287. origstype = -1L;
  288. origrate = 0L;
  289. origchans = 0L;
  290. specenvcnt = 0;
  291. Mlen = 0;
  292. Dfac = 0;
  293. arate = 0.0f;
  294. }
  295. //TODO: when I have unique checksums, can just compare them
  296. const fileprops& fileprops::operator=(const fileprops &rhs)
  297. {
  298. if(!(rhs == *this)){ //use my operator==; TODO: define operator!= as well...
  299. srate = rhs.srate;
  300. channels = rhs.channels;
  301. stype = rhs.stype;
  302. origstype = rhs.origstype;
  303. origrate = rhs.origrate;
  304. Mlen = rhs.Mlen;
  305. Dfac = rhs.Dfac;
  306. arate = rhs.arate;
  307. origchans = rhs.origchans;
  308. specenvcnt = rhs.specenvcnt; //RWD: comes from?
  309. }
  310. return *this;
  311. }
  312. int fileprops::operator==(const fileprops &rhs) const
  313. {
  314. return (srate == rhs.srate
  315. && channels == rhs.channels
  316. && stype == rhs.stype
  317. && origstype == rhs.origstype
  318. && origrate == rhs.origrate
  319. && Mlen == rhs.Mlen
  320. && Dfac == rhs.Dfac
  321. && arate == rhs.arate
  322. && origchans == rhs.origchans
  323. && specenvcnt == rhs.specenvcnt);
  324. }