snd.c 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747
  1. /* RWD version to support pvx files */
  2. /*
  3. * Copyright (c) 1983-2013 Martin Atkins, Richard Dobson and Composers Desktop Project Ltd
  4. * http://people.bath.ac.uk/masrwd
  5. * http://www.composersdesktop.com
  6. *
  7. This file is part of the CDP System.
  8. The CDP System is free software; you can redistribute it
  9. and/or modify it under the terms of the GNU Lesser General Public
  10. License as published by the Free Software Foundation; either
  11. version 2.1 of the License, or (at your option) any later version.
  12. The CDP System is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. GNU Lesser General Public License for more details.
  16. You should have received a copy of the GNU Lesser General Public
  17. License along with the CDP System; if not, write to the Free Software
  18. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  19. 02111-1307 USA
  20. *
  21. */
  22. /*
  23. * Sound Filing System - Buffered sound system, open/close, etc.
  24. *
  25. * Portable version
  26. *
  27. * Copyright M. C. Atkins, 1986, 1987, 1993; RWD 2007,2014,2022
  28. * All Rights Reserved.
  29. */
  30. /* RWD: old sfsys functions DEPRECATED and emptied */
  31. /* RWD Dec 2019 fixed SndCloseEx for int64 comps */
  32. /* RWD 2022 added PVX support */
  33. #ifdef _DEBUG
  34. #include <stdio.h>
  35. #endif
  36. #include <stdlib.h>
  37. #include <string.h>
  38. #include <math.h>
  39. #include <sfsys.h>
  40. #include "sffuncs.h"
  41. #ifdef unix
  42. #include <unistd.h>
  43. #endif
  44. #ifdef ENABLE_PVX
  45. # ifdef unix
  46. # include "wavdefs.h"
  47. # include "pvdefs.h"
  48. # endif
  49. # include "pvfileio.h"
  50. # ifdef _DEBUG
  51. # include <assert.h>
  52. # endif
  53. #endif
  54. #ifdef _WIN32
  55. # ifdef _MSC_VER
  56. # if _MSC_VER <=1200
  57. static __inline int cdp_round(double fval)
  58. {
  59. int result;
  60. asm{
  61. fld fval
  62. fistp result
  63. mov eax,result /* RWD: need this line? */
  64. }
  65. return result;
  66. }
  67. # endif
  68. #else
  69. # ifndef __GNUWIN32__
  70. static int cdp_round(double val)
  71. {
  72. int k;
  73. k = (int)(fabs(val)+0.5);
  74. if(val < 0.0)
  75. k = -k;
  76. return k;
  77. }
  78. # endif
  79. #endif
  80. #endif
  81. /*
  82. * This is the main structure describing a procom file
  83. */
  84. struct sndfile {
  85. int flags; /* various flags */
  86. int fd; /* SFfile/gemfile file descripter */
  87. #ifdef ENABLE_PVX
  88. int pvxid;
  89. #endif
  90. char *buffer; /* pointer to the buffer */
  91. char *next; /* next entry in buffer to access */
  92. int bufsiz; /* the size of the buffer (in sectors) */
  93. int remain; /* number of samples remaining in buffer */
  94. char *endbuf; /* end of buffer (for short bufs at eof) */
  95. int samptype; /* the type of samples in the file */
  96. int lastread; /* number of bytes obtained from last read */
  97. int true_bufsize; /*for 24bit alignment, etc: adjust buffer downwards*/
  98. int scale_floats;
  99. double fscalefac;
  100. };
  101. typedef union {
  102. int lsamp;
  103. /*float fsamp; //any use for this? */
  104. unsigned char bytes[4];
  105. } SND_SAMP;
  106. /*
  107. * values for sndfile.flags
  108. */
  109. #define SNDFLG_WRITTEN (1) /* the buffer must be flushed back to disk */
  110. #define SNDFLG_LASTWR (4) /* last i/o was a write (for sndtell) */
  111. #define SNDFLG_TRUNC (8) /* truncate when closed */
  112. #define SNDFLG_USERBUF (32) /* the buffer was supplied by the user */
  113. #define SNDFLG_ATEND (64) /* the last i/o went over the end of the file */
  114. /*
  115. * Various constants/global data
  116. */
  117. #define SNDFDBASE (4000) /* sndfd's allocated from here */
  118. #define SNDBUFSIZE (64)
  119. /*
  120. * global storage
  121. */
  122. /*
  123. * The array of open sndfiles
  124. */
  125. //#if defined ENABLE_PVX
  126. //static struct sndfile *sndfiles[MAXSNDFILES];
  127. //#else
  128. static struct sndfile *sndfiles[MAXSNDFILES];
  129. //#endif
  130. /*
  131. * mapping table from sample type, to size
  132. */
  133. /* the possible sample types are now:
  134. SAMP_SHORT (0) * 16-bit short integers *
  135. SAMP_FLOAT (1) * 32-bit (IEEE) floating point *
  136. SAMP_BYTE (2) //recognize 8bit soundfiles?
  137. SAMP_LONG (3) // four most likely formats
  138. SAMP_2424 (4)
  139. SAMP_2432 (5)
  140. SAMP_2024 (6)
  141. SAMP_MASKED (7) //some weird WAVE_EX format!
  142. */
  143. /*RWD.6.99 set this as container-size
  144. *private, but sfsys.c needs to have it
  145. */
  146. int sampsize[] = {
  147. /* SAMP_SHORT */ sizeof(short),
  148. /* SAMP_FLOAT */ sizeof(float),
  149. /* SAMP_BYTE */ sizeof(unsigned char),
  150. /* SAMP_LONG */ sizeof(int),
  151. /* SAMP_2424 */ 3 * sizeof(unsigned char),
  152. /* SAMP_2432 */ sizeof(int),
  153. /* SAMP_2024 */ 3 * sizeof(unsigned char),
  154. /* dummy */ 0 /*for masked formats, have to calc from 1st principles...*/
  155. };
  156. /*
  157. * Utility routines
  158. */
  159. #define getmem(type) ((type *)malloc(sizeof(type)))
  160. extern int _rsf_getmaxpeak(int sfd,float *peak);
  161. extern int _rsf_getbitmask(int sfd);
  162. /*
  163. * initialisation/termination routines
  164. */
  165. static void
  166. rsndallclose(void)
  167. {
  168. int fd;
  169. for(fd = 0; fd < MAXSFNAME; fd++)
  170. if(sndfiles[fd] != 0)
  171. sndcloseEx(fd + SNDFDBASE); //RWD was plain sndclose()
  172. #if defined ENABLE_PVX
  173. pvsys_release();
  174. #endif
  175. }
  176. static void
  177. rsndinit()
  178. {
  179. register int fd;
  180. static int inited = 0;
  181. if(inited != 0)
  182. return;
  183. inited++;
  184. for(fd = 0; fd < MAXSFNAME; fd++)
  185. sndfiles[fd] = 0;
  186. atexit(rsndallclose); //RWD if we need to be reentrant, we can't use this!
  187. }
  188. /*
  189. * map a sndfd onto a sndfiles index,
  190. * return 0 on failure
  191. */
  192. /*RWD I want a public version of this, for use in ASSERT etc*/
  193. static int
  194. mapsndfd(int *sfdp)
  195. {
  196. *sfdp -= SNDFDBASE;
  197. if(*sfdp < 0 || *sfdp >= MAXSNDFILES) {
  198. rsferrno = ESFBADADDR;
  199. rsferrstr = "sfd is not in valid range";
  200. return 0;
  201. }
  202. if(sndfiles[*sfdp] == 0) {
  203. rsferrno = ESFNOTOPEN;
  204. rsferrstr = "sndfile is not open (bad sndfd)";
  205. return 0;
  206. }
  207. return 1;
  208. }
  209. /*
  210. * do the underlying seek
  211. * NOTE
  212. * seeks to the end of an sffile are rounded down!!
  213. */
  214. static int
  215. doseek(struct sndfile *sf, int dist, int whence)
  216. {
  217. return sfseek(sf->fd, dist, whence);
  218. }
  219. /*RWD Feb 2010 ??? */
  220. //static long
  221. //doseekEx(struct sndfile *sf, long dist, int whence)
  222. //{
  223. // return sfseek_buffered(sf->fd, dist, whence);
  224. //}
  225. static __int64 doseekEx(struct sndfile *sf, __int64 dist, int whence)
  226. {
  227. return sfseek_buffered(sf->fd, dist, whence);
  228. }
  229. /*
  230. * sndfilbuf - fill a buffer, for reading
  231. * return true, if an error occurs
  232. */
  233. static int
  234. sndfilbuf(struct sndfile *sfd)
  235. {
  236. long want /* = SECSIZE * sfd->bufsiz*/ ; /*RWD: almost a const!*/
  237. long got;
  238. int rc = 0;
  239. if(sfd->flags & SNDFLG_ATEND)
  240. return 0;
  241. want = sfd->true_bufsize;
  242. /*only difference - supports other sample sizes*/
  243. got = sfread_buffered(sfd->fd, sfd->buffer, want);
  244. if(got < 0) {
  245. rc = 1;
  246. got = 0;
  247. }
  248. if(got < want)
  249. sfd->flags |= SNDFLG_ATEND;
  250. sfd->lastread = got; /*bytes of <size>samps*/
  251. sfd->flags &= ~(SNDFLG_WRITTEN|SNDFLG_LASTWR);
  252. sfd->endbuf = &sfd->buffer[got];
  253. /*RWD NB all snd funcs think in SAMPLES, of 2 types: SHORTS or FLOATS; all 8bit stuff hidden in sf_calls*/
  254. sfd->remain = got / sampsize[sfd->samptype]; /*RWD : adjust for 8bit files...*/
  255. sfd->next = sfd->buffer;
  256. return rc;
  257. }
  258. /*
  259. * sndflsbuf - flush a buffer, after writing
  260. * return true, if an error occurs
  261. */
  262. static int
  263. sndflsbuf(struct sndfile *sfd)
  264. {
  265. int toput = sfd->endbuf - sfd->buffer;
  266. int put;
  267. if(sfd->next == sfd->buffer)
  268. return 0;
  269. if(sfd->flags & SNDFLG_ATEND)
  270. return 0;
  271. sfd->next = sfd->buffer;
  272. sfd->flags &= ~SNDFLG_WRITTEN;
  273. sfd->endbuf = sfd->buffer;
  274. if(!(sfd->flags&SNDFLG_LASTWR) ) {
  275. if(doseek(sfd, -sfd->lastread, 1) < 0) {
  276. sfd->flags |= SNDFLG_LASTWR;
  277. sfd->remain = (sfd->bufsiz<<LOGSECSIZE) / sampsize[sfd->samptype];
  278. return 1;
  279. }
  280. }
  281. sfd->flags |= SNDFLG_LASTWR;
  282. sfd->remain = (sfd->bufsiz<<LOGSECSIZE) / sampsize[sfd->samptype];
  283. toput = (toput+SECSIZE-1)&~(SECSIZE-1);
  284. if((put = sfwrite(sfd->fd, sfd->buffer, toput)) < 0)
  285. return 1;
  286. if(put < toput) {
  287. sfd->flags |= SNDFLG_ATEND;
  288. sfd->remain = 0;
  289. }
  290. return 0;
  291. }
  292. static int
  293. sndflsbufEx(struct sndfile *sfd)
  294. {
  295. int toput = sfd->endbuf - sfd->buffer;
  296. int put;
  297. if(sfd->next == sfd->buffer)
  298. return 0;
  299. if(sfd->flags & SNDFLG_ATEND)
  300. return 0;
  301. sfd->next = sfd->buffer;
  302. sfd->flags &= ~SNDFLG_WRITTEN;
  303. sfd->endbuf = sfd->buffer;
  304. if(!(sfd->flags&SNDFLG_LASTWR) ) {
  305. if(doseekEx(sfd,(__int64) -sfd->lastread, 1) < 0) {
  306. sfd->flags |= SNDFLG_LASTWR;
  307. sfd->remain = sfd->true_bufsize / sampsize[sfd->samptype];
  308. return 1;
  309. }
  310. }
  311. sfd->flags |= SNDFLG_LASTWR;
  312. sfd->remain = sfd->true_bufsize / sampsize[sfd->samptype];
  313. if((put = sfwrite_buffered(sfd->fd, sfd->buffer, toput)) < 0)
  314. return 1;
  315. if(put < toput) {
  316. sfd->flags |= SNDFLG_ATEND;
  317. sfd->remain = 0;
  318. }
  319. return 0;
  320. }
  321. /*
  322. * free the sample buffer, if it wasn't supplied by a sndsetbuf
  323. */
  324. static void
  325. freesndbuf(int fd)
  326. {
  327. if(sndfiles[fd]->flags & SNDFLG_USERBUF)
  328. return;
  329. free(sndfiles[fd]->buffer);
  330. }
  331. /*
  332. * free the memory for an open SFfile
  333. * used on last close, and failure of creat
  334. */
  335. static void
  336. freesndfd(int fd)
  337. {
  338. freesndbuf(fd);
  339. free((char *)sndfiles[fd]);
  340. sndfiles[fd] = 0;
  341. return;
  342. }
  343. /*
  344. * Try to find a snd file descripter
  345. * returns -1, if there aren't any
  346. */
  347. static int
  348. findsndfd()
  349. {
  350. register int fd = 0;
  351. while(sndfiles[fd] != 0)
  352. if(++fd >= MAXSNDFILES) {
  353. rsferrno = ESFNOSFD;
  354. rsferrstr = "Too many sndfiles are already open";
  355. return -1;
  356. }
  357. rsferrstr = "no memory to open sndfile";
  358. rsferrno = ESFNOMEM;
  359. if((sndfiles[fd] = getmem(struct sndfile)) == 0)
  360. return -1;
  361. if((sndfiles[fd]->buffer = (char*) malloc(SNDBUFSIZE*SECSIZE)) == 0) {
  362. free((char *)sndfiles[fd]);
  363. sndfiles[fd] = 0;
  364. return -1;
  365. }
  366. #ifdef ENABLE_PVX
  367. sndfiles[fd]->pvxid = -1;
  368. #endif
  369. sndfiles[fd]->flags = 0;
  370. sndfiles[fd]->bufsiz = SNDBUFSIZE;
  371. sndfiles[fd]->lastread = 0;
  372. sndfiles[fd]->endbuf = sndfiles[fd]->next = sndfiles[fd]->buffer;
  373. sndfiles[fd]->true_bufsize = SNDBUFSIZE * SECSIZE; /*may get rounded down for 24bit formats*/
  374. return fd;
  375. }
  376. /*
  377. * The user-accessable routines
  378. */
  379. /*
  380. * open a sndfile
  381. */
  382. int
  383. sndopenEx(const char *fn,int auto_scale, int access)
  384. {
  385. register struct sndfile *sf;
  386. int fd;
  387. #ifdef ENABLE_PVX
  388. PVOCDATA pvxdata;
  389. int rc;
  390. #endif
  391. rsndinit();
  392. if((fd = findsndfd()) < 0)
  393. return -1;
  394. sf = sndfiles[fd];
  395. if((sf->fd = sfopenEx(fn,access)) < 0) {
  396. freesndfd(fd);
  397. return -1;
  398. }
  399. /* RWD TODO: add pvx support here_ sfopenEx can produce one */
  400. #ifdef ENABLE_PVX
  401. if(sf_ispvx(sf->fd)){
  402. if((rc = get_pvxfd(sf->fd ,&pvxdata )) < 0){
  403. # ifdef _DEBUG
  404. fprintf(stderr,"sndopenEx: bad sf id\n");
  405. # endif
  406. return -1;
  407. }
  408. else if (rc >= 0){
  409. # ifdef _DEBUG
  410. fprintf(stderr,"sndopenEx: file %s is a pvx file!\n", fn);
  411. # endif
  412. return fd + SNDFDBASE;
  413. }
  414. }
  415. // else its a soundfile or a .ana file, carry on as usual
  416. #endif
  417. /* all the rest just for standard CDP files */
  418. sf->remain = 0;
  419. if(sfgetprop(sf->fd, "sample type",
  420. (char *)&sf->samptype, sizeof(int)) != sizeof(int)) {
  421. rsferrno = ESFNOSTYPE;
  422. rsferrstr = "no sample type defined";
  423. freesndfd(fd);
  424. return -1;
  425. }
  426. /*RWD only used to rescale floatsams when read into shorts (eg for playback)*/
  427. sf->scale_floats = 0;
  428. sf->fscalefac = 1.0;
  429. if(auto_scale && (sf->samptype==SAMP_FLOAT)){
  430. float fac = 0.0f;
  431. /* RWD 4:2002: I would prefer to rely on PEAK only for this now... */
  432. if(sfgetprop(sf->fd,"maxamp",(char *)&fac,sizeof(float)) == sizeof(float)){
  433. if(fac > sf->fscalefac){
  434. sf->scale_floats = 1;
  435. sf->fscalefac = 0.99995 / (double) fac;
  436. }
  437. }
  438. /*get it from PEAK data if available*/
  439. else if (_rsf_getmaxpeak(sf->fd,&fac) > 0){
  440. if(fac > sf->fscalefac){
  441. sf->scale_floats = 1;
  442. sf->fscalefac = 0.99995 / (double) fac;
  443. }
  444. }
  445. /*Could also provide a set_autoscale() func, legal only before first read (like sndsetbuf)*/
  446. }
  447. /*adjust internal buffer if reading 24bit formats*/
  448. if(sf->samptype==SAMP_2424 || sf->samptype == SAMP_2024)
  449. sf->true_bufsize = (sf->true_bufsize / sampsize[sf->samptype]) * sampsize[sf->samptype];
  450. /* need superfluous seek to overcome daft OS problems reopening just-closed file */
  451. if(sndseekEx(fd+SNDFDBASE,0,0) != 0)
  452. return -1;
  453. return fd+SNDFDBASE;
  454. }
  455. /* RWD PVX note: this is the form called by CDP for ANAL files */
  456. /* Also, NB stype is according to the SAMP_* list, gets converted by sampsize[] for sf routines as here */
  457. int
  458. sndcreat_formatted(const char *fn, int size, int stype,int channels,
  459. int srate,cdp_create_mode mode)
  460. {
  461. register struct sndfile *sf;
  462. int fd;
  463. rsndinit();
  464. if((fd = findsndfd()) < 0)
  465. return -1;
  466. sf = sndfiles[fd];
  467. sf->flags |= SNDFLG_TRUNC;
  468. sf->samptype = stype;
  469. /*RWD NB sampsize[] - no slot for 24bit size yet*/
  470. /* ALSO: at this stage, CDP still assumes 32bits if an analysis file, no "original sampsize" info yet -
  471. we have to rely on sfputprop("original sampsize" being set by program
  472. */
  473. /* if pvx file, sets sffile->pvxfileno (which may be 0 ), but returns sf id (which may be 1) */
  474. if((sf->fd = sfcreat_formatted(fn, size*sampsize[stype], (__int64 *)0,channels,srate,
  475. stype,mode)) < 0) {
  476. freesndfd(fd);
  477. return -1;
  478. }
  479. // now need to set sf->pvxid, if this is a pvx file.
  480. sf->remain = sf->true_bufsize / sampsize[stype];
  481. return fd+SNDFDBASE;
  482. }
  483. /* RWD PVX: Trouble is, we need to use this one, to get props */
  484. /* means just one change (???!!!???) inside cdp2k, mainfunc.c */
  485. int
  486. sndcreat_ex(const char *name, int size,SFPROPS *props,int min_header,cdp_create_mode mode)
  487. {
  488. register struct sndfile *sf;
  489. int fd;
  490. int smpsize;
  491. rsndinit();
  492. if((fd = findsndfd()) < 0)
  493. return -1;
  494. sf = sndfiles[fd];
  495. sf->flags |= SNDFLG_TRUNC;
  496. /* RWD.6.99 write 24bit formats, etc */
  497. switch(props->samptype){
  498. case(FLOAT32):
  499. sf->samptype = SAMP_FLOAT;
  500. break;
  501. case(SHORT16):
  502. sf->samptype = SAMP_SHORT;
  503. break;
  504. case(INT_32):
  505. sf->samptype = SAMP_LONG;
  506. break;
  507. case(INT2424):
  508. sf->samptype = SAMP_2424;
  509. /*adjust sndbuffer with 3-byte alignment*/
  510. sf->true_bufsize = (sf->true_bufsize / sampsize[sf->samptype]) * sampsize[sf->samptype];
  511. break;
  512. case(INT2024):
  513. sf->samptype = SAMP_2024;
  514. /*adjust sndbuffer with 3-byte alignment*/
  515. sf->true_bufsize = (sf->true_bufsize / sampsize[sf->samptype]) * sampsize[sf->samptype];
  516. break;
  517. case(SAMP_MASKED):
  518. /*don't know how to do this yet...*/
  519. rsferrno = ESFBADPARAM;
  520. rsferrstr = "cannot write masked sample type";
  521. return -1;
  522. default:
  523. rsferrno = ESFBADPARAM;
  524. rsferrstr = "unknown sample type";
  525. return -1;
  526. break;
  527. }
  528. /*sf->samptype = (props->samptype == FLOAT32 ? SAMP_FLOAT : SAMP_SHORT);*/
  529. smpsize = sampsize[sf->samptype];
  530. /*need to return to outsize: size / smpsize - check this...*/
  531. if((sf->fd = sfcreat_ex(name, (__int64)size *smpsize, (__int64 *)0,
  532. props,min_header,mode)) < 0) {
  533. freesndfd(fd);
  534. return -1;
  535. }
  536. sf->remain = sf->true_bufsize / smpsize;
  537. return fd+SNDFDBASE;
  538. }
  539. /*
  540. * close a sndfile
  541. */
  542. int
  543. sndcloseEx(int fd)
  544. {
  545. register struct sndfile *sf;
  546. int rc = 0;
  547. __int64 length, pos;
  548. if(!mapsndfd(&fd))
  549. return -1;
  550. sf = sndfiles[fd];
  551. #ifdef ENABLE_PVX
  552. if(sf_ispvx(sf->fd)){
  553. // if(sf_ispvx(sf->fd,0) >=0) {
  554. # ifdef _DEBUG
  555. fprintf(stderr,"calling sfclose with fd %d\n",sf->fd);
  556. # endif
  557. rc = sfclose(sf->fd); // I think..nothing else to do for pvx file!
  558. if(rc < 0) {
  559. # ifdef _DEBUG
  560. fprintf(stderr,"sfclose error, rc = %d\n",rc);
  561. # endif
  562. sfperror("sndcloseEx");
  563. }
  564. freesndfd(fd);
  565. return rc;
  566. // }
  567. }
  568. #endif
  569. if(sf->flags&SNDFLG_TRUNC) {
  570. length = sfsize(sf->fd);
  571. pos = sndtellEx(fd + SNDFDBASE); //RWD 12-12-19 make sure of 64bit ints in calcs
  572. pos *= sampsize[sf->samptype];
  573. if(sf->flags & SNDFLG_WRITTEN ) /* should never exec */
  574. sndflsbufEx(sf); /* rsfsize does it! */
  575. if((rc = sfadjust(sf->fd,pos-length)) < 0) {
  576. rsferrno = ESFWRERR;
  577. rsferrstr = "can't truncate SFfile";
  578. }
  579. } else if(sf->flags & SNDFLG_WRITTEN )
  580. sndflsbufEx(sf);
  581. rc |= sfclose(sf->fd);
  582. freesndfd(fd);
  583. return rc;
  584. }
  585. /*RWD.6.98 needed for Release98!*/
  586. int sndunlink(int sndfd)
  587. {
  588. //int size;
  589. struct sndfile *sf;
  590. /* RWD PVX TODO: hopefully wouldn't need to perform this hack on pvx file....? */
  591. (void)sndseekEx(sndfd,0,0); /*RWD.7.98 hack to fix bug when closing empty file*/
  592. if(!mapsndfd(&sndfd))
  593. return -1;
  594. sf = sndfiles[sndfd];
  595. return sfunlink(sf->fd);
  596. }
  597. /*
  598. * Return the size (in samples) of a sndfile
  599. * NOTE
  600. * the first sndseek will flush buffer if necessary
  601. */
  602. int
  603. sndsizeEx(int sfd)
  604. {
  605. int oldpos;
  606. int size;
  607. if((oldpos = sndtellEx(sfd)) < 0) /* RWD: pvx handling done */
  608. return -1;
  609. if((size = sndseekEx(sfd, 0L, 2)) < 0) {
  610. size = -1;
  611. rsferrno = ESFNOSEEK;
  612. rsferrstr = "can't seek to end of file to find size";
  613. }
  614. if(sndseekEx(sfd, oldpos, 0) < 0) {
  615. rsferrno = ESFNOSEEK;
  616. rsferrstr = "can't restore position after finding file size";
  617. return -1;
  618. }
  619. return size;
  620. }
  621. /*
  622. * seek in a sndfile (of SHORTS or FLOATS)
  623. */
  624. int
  625. sndseek(int fd, int dist, int whence)
  626. {
  627. //return sndseekEx(fd,dist,whence);
  628. return -1;
  629. }
  630. //RWD NB PVX: returns new file pos (in samples), or -1 for error
  631. int
  632. sndseekEx(int fd, int dist, int whence)
  633. {
  634. register struct sndfile *sf;
  635. long bufsize;
  636. __int64 secpos;
  637. __int64 newpos = 0;
  638. __int64 gotpos;
  639. if(!mapsndfd(&fd))
  640. return -1;
  641. sf = sndfiles[fd];
  642. #ifdef ENABLE_PVX
  643. if(sf_ispvx(sf->fd)){ // RWD TODO: shoukld add test for error return
  644. PVOCDATA pvxdata;
  645. // we must return currentframepos as raw floatsams
  646. int frameoffset;
  647. int curframe;
  648. int goalframe = 0;
  649. int rc = 0;
  650. int pvxid;
  651. pvxid = get_pvxfd(sf->fd,&pvxdata);
  652. # ifdef _DEBUG
  653. assert(pvxid >= 0);
  654. // eventually we will code this permanently...but is this the best place to put this test?
  655. //if(dist > 0)
  656. assert(abs(dist) % (pvxdata.nAnalysisBins * 2) == 0);
  657. # endif
  658. //RWD Oct 2025, can't divide signed val by unsigned val. No warning, but CPU goes nuts!
  659. frameoffset = dist / (int) (pvxdata.nAnalysisBins * 2); //NB: always mono stream in CDP
  660. switch(whence){
  661. //set: go to "dist" samples: must be int multiple of framesize
  662. // seems never to be called for CDP ana routines, except for dist= 0
  663. case SEEK_SET:
  664. rc = pvoc_seek_mcframe(pvxid, frameoffset,SEEK_SET);
  665. //or: if dist==0, use pvoc_rewind()?
  666. if(rc < 0){
  667. return rc;
  668. }
  669. rc = pvoc_framepos(pvxid) * (pvxdata.nAnalysisBins * 2);
  670. break;
  671. //tell - Ok to use pvoc_framepos, OR can use sndtellEx below
  672. case SEEK_CUR:
  673. // not directly handled in pvfileio.c yet
  674. rc = pvoc_seek_mcframe(pvxid, frameoffset,SEEK_CUR);
  675. if(rc < 0){
  676. return rc;
  677. }
  678. rc = pvoc_framepos(pvxid) * (pvxdata.nAnalysisBins * 2);
  679. break;
  680. //end: step back dist samps if negative. We do not allow setting beyond EOF.
  681. case SEEK_END:
  682. rc = pvoc_seek_mcframe(pvxid, frameoffset,SEEK_END);
  683. if(rc < 0){
  684. return rc;
  685. }
  686. rc = pvoc_framepos(pvxid); //frames
  687. rc *= pvxdata.nAnalysisBins * 2; // samps. caller has to compute nframes
  688. break;
  689. }
  690. return rc;
  691. }
  692. #endif
  693. // std CDP files from here
  694. bufsize = sf->true_bufsize;
  695. if((sf->flags & SNDFLG_WRITTEN) && sndflsbufEx(sf))
  696. return -1;
  697. switch(whence) {
  698. case 0:
  699. newpos = dist; /*in SAMPLES: NB must deal with 8bit files!*/
  700. break;
  701. case 1:
  702. newpos = sndtellEx(fd+SNDFDBASE) + dist;
  703. break;
  704. case 2:
  705. newpos = sfsize(sf->fd); /*size-specific:SHORTSAMS, from datachunksize*/
  706. newpos = (newpos / sampsize[sf->samptype]) + dist; /*make non-size-specific*/
  707. break;
  708. }
  709. if(newpos < 0)
  710. newpos = 0;
  711. newpos *= sampsize[sf->samptype]; /* byte offset */ /*restore size-specific for doseek*/
  712. /*RWD.6.99 still need to do this - not a SECSIZE calc, but just cdp_round to our buffersize*/
  713. secpos = (newpos/bufsize)*bufsize; /* cdp_round down */
  714. /*RWD 2007: NB for FILE64_WIN doseekEx takes and returns __int64 */
  715. if((gotpos = doseekEx(sf, secpos, 0)) < 0)/*NB seek might be truncated */ /*gotpos = non-size-specific*/
  716. return -1;
  717. sf->flags &= ~SNDFLG_ATEND;
  718. if(sndfilbuf(sf)) { /* if sndfilbuf fails... */
  719. sf->next = sf->buffer;
  720. sf->remain = 0;
  721. return -1;
  722. }
  723. if(gotpos < secpos) {
  724. newpos -= sf->remain; /*RWD 2007 !!! remain supposed to count ~samples~ */
  725. sf->remain = 0;
  726. }
  727. sf->next = &sf->buffer[(unsigned long)newpos % bufsize];
  728. newpos /= sampsize[sf->samptype];
  729. sf->remain = (sf->endbuf - sf->next)/sampsize[sf->samptype];
  730. return (long) newpos;
  731. }
  732. /*
  733. * Where are we in the present sndfile
  734. * NOTE
  735. * This does not need to flush buffers, etc
  736. */
  737. int
  738. sndtell(int fd)
  739. {
  740. return -1;
  741. }
  742. /*RWD 2007 FIXME for 64bit reads: */
  743. /* doseekEx must return unsigned long, or __int64 value */
  744. /* RWD PVX: this is called only once in all of CDP7/8: pvthreads.cpp, to get current framepos */
  745. /* direct equivalent is pvoc_framepos() */
  746. /* but sfsys expects (float) sample pos as for (mono) .ana file */
  747. /* don't want to clone all the sf calls here (dealing with SECSIZE etc */
  748. int
  749. sndtellEx(int fd)
  750. {
  751. struct sndfile *sf;
  752. //long off;
  753. __int64 off;
  754. if(!mapsndfd(&fd)) //strips SNDFDBASE: fd = 0
  755. return -1;
  756. sf = sndfiles[fd]; //sf-fd = 1000
  757. #ifdef ENABLE_PVX
  758. if(sf_ispvx(sf->fd)){
  759. int pvxid;
  760. PVOCDATA pvxdata;
  761. pvxid = get_pvxfd(sf->fd,&pvxdata);
  762. if(pvxid >=0){
  763. // we must return currentframepos as raw floatsams
  764. int32_t framepos;
  765. int32_t nsamps;
  766. //TODO: sf->fd is sf element, offset by SFDBASE= 1000
  767. // need to remove that first - how?
  768. framepos = pvoc_framepos(pvxid);
  769. if(framepos < 0){
  770. # ifdef _DEBUG
  771. fprintf(stderr,"bad return %d from pvoc_framepos\n",framepos);
  772. # endif
  773. return -1;
  774. }
  775. nsamps = framepos * (pvxdata.nAnalysisBins * 2); //of course, 1 bin = [amp,freq] duplet
  776. return (int) nsamps;
  777. }
  778. }
  779. #endif
  780. // std CDP files from here
  781. if((off = doseekEx(sf, 0L, 1)) < 0) { /*NB: must return cnt of samples * sizeof(type=SHORTS or FLOATS)*/
  782. rsferrno = ESFNOSEEK;
  783. rsferrstr = "can't seek to find present position in file";
  784. return -1;
  785. }
  786. if(sf->flags & SNDFLG_LASTWR) /*RWD.5.1.99 fails for short sndfiles within a buffer*/
  787. off += sf->true_bufsize;
  788. if(sf->flags & SNDFLG_ATEND)
  789. off = sfsize(sf->fd); /*bytes, of SHORTS or FLOATS samps*/
  790. off /= sampsize[sf->samptype];
  791. return (int)(off - ( (sf->remain < 0) ? 0 : sf->remain));
  792. }
  793. /*
  794. * let the user supply a larger buffer
  795. */
  796. /*RWD.6.99 NB bufsize is in SECTORS - may need new version for new formats...*/
  797. int
  798. sndsetbuf(int sfd, char *buf, int bufsize)
  799. {
  800. struct sndfile *sf;
  801. if(!mapsndfd(&sfd))
  802. return -1;
  803. sf = sndfiles[sfd];
  804. if(sf->remain != 0) {
  805. rsferrno = ESFLOSEDATA;
  806. rsferrstr = "sndsetbuf would lose data";
  807. return -1;
  808. }
  809. freesndbuf(sfd);
  810. sf->buffer = buf;
  811. sf->bufsiz = bufsize;
  812. sf->true_bufsize = sf->bufsiz << LOGSECSIZE;
  813. sf->flags |= SNDFLG_USERBUF;
  814. return 0;
  815. }
  816. /*
  817. * snd I/O routines
  818. */
  819. /*
  820. * fgetfloat - read the next float
  821. */
  822. // RWD TODO: looks like several programs still call this!
  823. int
  824. fgetfloat(float *fp, int sfd)
  825. {
  826. register struct sndfile *sfp;
  827. if(!mapsndfd(&sfd))
  828. return -1;
  829. sfp = sndfiles[sfd];
  830. if(sfp->remain < 0)
  831. return 0;
  832. if(sfp->remain-- == 0) {
  833. if(sndfilbuf(sfp))
  834. return -1;
  835. if(sfp->remain-- <= 0)
  836. return 0;
  837. }
  838. if(sfp->samptype == SAMP_FLOAT) {
  839. *fp = *(float *)sfp->next;
  840. sfp->next += sizeof(float);
  841. } else {
  842. *fp = (float)(*(short *)sfp->next) / (float)MAXSHORT;
  843. sfp->next += sizeof(short);
  844. }
  845. return 1;
  846. }
  847. int
  848. fgetfloatEx(float *fp, int sfd,int expect_floats)
  849. {
  850. register struct sndfile *sfp;
  851. long lword = 0;
  852. long mask; /*we need signed ints*/
  853. SND_SAMP ssamp;
  854. if(!mapsndfd(&sfd))
  855. return -1;
  856. sfp = sndfiles[sfd];
  857. if(sfp->remain < 0)
  858. return 0;
  859. if(sfp->remain-- == 0) {
  860. if(sndfilbuf(sfp))
  861. return -1;
  862. if(sfp->remain-- <= 0)
  863. return 0;
  864. }
  865. ssamp.lsamp = 0;
  866. switch(sfp->samptype){
  867. case(SAMP_FLOAT):
  868. *fp = *(float *)sfp->next;
  869. sfp->next += sizeof(float);
  870. break;
  871. case(SAMP_SHORT):
  872. *fp = (float)(*(short *)sfp->next) / (float)MAXSHORT;
  873. sfp->next += sizeof(short);
  874. break;
  875. case(SAMP_LONG):
  876. if(expect_floats){
  877. *fp = *(float *)sfp->next;
  878. sfp->next += sizeof(float);
  879. }
  880. else{
  881. *fp = (float)((double) (*(int *)sfp->next) / (float)MAXINT);
  882. sfp->next += sizeof(int);
  883. }
  884. break;
  885. case(SAMP_2432):
  886. /*mask the word first*/
  887. lword = *(long *)sfp->next;
  888. lword &= 0xffffff00;
  889. *fp = (float)((double)lword / MAXINT);
  890. sfp->next += sizeof(int);
  891. break;
  892. case(SAMP_2024): /*need to mask it?*/
  893. ssamp.lsamp = 0;
  894. mask = _rsf_getbitmask(sfp->fd);
  895. if(mask==0)
  896. return -1;
  897. //#ifdef LSBFIRST
  898. ssamp.bytes[1] = sfp->next[0];
  899. ssamp.bytes[2] = sfp->next[1];
  900. ssamp.bytes[3] = sfp->next[2];
  901. //#else
  902. // ssamp.bytes[0] = sfp->next[0];
  903. // ssamp.bytes[1] = sfp->next[1];
  904. // ssamp.bytes[2] = sfp->next[2];
  905. //#endif
  906. *fp = (float)((double)(ssamp.lsamp & mask) / MAXINT);
  907. sfp->next += 3;
  908. break;
  909. case(SAMP_2424):
  910. //#ifdef LSBFIRST
  911. ssamp.bytes[1] = sfp->next[0];
  912. ssamp.bytes[2] = sfp->next[1];
  913. ssamp.bytes[3] = sfp->next[2];
  914. //#else
  915. // ssamp.bytes[0] = sfp->next[0];
  916. // ssamp.bytes[1] = sfp->next[1];
  917. // ssamp.bytes[2] = sfp->next[2];
  918. //#endif
  919. *fp = (float)((double)(ssamp.lsamp) / MAXINT);
  920. sfp->next += 3;
  921. break;
  922. default:
  923. rsferrno = ESFBADPARAM;
  924. rsferrstr = "attempted to read unknown sample format";
  925. return -1; /*do others later...*/
  926. break;
  927. }
  928. return 1;
  929. }
  930. /*
  931. * fputfloat - write the next float
  932. */
  933. int
  934. fputfloat(float *fp, int sfd)
  935. {
  936. register struct sndfile *sfp;
  937. if(!mapsndfd(&sfd))
  938. return -1;
  939. sfp = sndfiles[sfd];
  940. if(sfp->flags&SNDFLG_ATEND)
  941. return 0;
  942. sfp->flags |= SNDFLG_WRITTEN;
  943. /* sndtell checks this*/
  944. sfp->flags |= SNDFLG_LASTWR;
  945. if(sfp->samptype == SAMP_FLOAT) {
  946. *(float *)sfp->next = *fp;
  947. sfp->next += sizeof(float);
  948. } else {
  949. /* *(short *)sfp->next = (short) floor(0.5 + *fp * MAXSHORT);*/
  950. *(short *)sfp->next = (short) cdp_round( *fp * MAXSHORT);
  951. sfp->next += sizeof(short);
  952. }
  953. if(sfp->next > sfp->endbuf)
  954. sfp->endbuf = sfp->next;
  955. if(--sfp->remain == 0) {
  956. if(sndflsbuf(sfp))
  957. return -1;
  958. }
  959. return 1;
  960. }
  961. /*RWD.7.99 replace floor calc with cdp_round(): more accurate!*/
  962. int
  963. fputfloatEx(float *fp, int sfd)
  964. {
  965. register struct sndfile *sfp;
  966. SND_SAMP ssamp;
  967. if(!mapsndfd(&sfd))
  968. return -1;
  969. sfp = sndfiles[sfd];
  970. if(sfp->flags&SNDFLG_ATEND)
  971. return 0;
  972. sfp->flags |= SNDFLG_WRITTEN;
  973. /* sndtell checks this*/
  974. sfp->flags |= SNDFLG_LASTWR;
  975. ssamp.lsamp = 0;
  976. switch(sfp->samptype){
  977. case(SAMP_FLOAT):
  978. *(float *)sfp->next = *fp;
  979. sfp->next += sizeof(float);
  980. break;
  981. case(SAMP_SHORT):
  982. /* *(short *)sfp->next = (short)floor(0.5 + *fp * MAXSHORT);*/
  983. *(short *)sfp->next = (short) cdp_round( *fp * MAXSHORT);
  984. sfp->next += sizeof(short);
  985. break;
  986. case(SAMP_2024):
  987. /*ssamp.lsamp = (int) floor(0.5 + *fp * MAXINT);*/
  988. ssamp.lsamp = (int) cdp_round(*fp * MAXINT);
  989. //#ifdef LSBFIRST
  990. sfp->next[0] = ssamp.bytes[1] & 0xf0;
  991. sfp->next[1] = ssamp.bytes[2];
  992. sfp->next[2] = ssamp.bytes[3];
  993. //#else
  994. // sfp->next[0] = ssamp.bytes[0] & 0xf0;
  995. // sfp->next[1] = ssamp.bytes[1];
  996. // sfp->next[2] = ssamp.bytes[2];
  997. //#endif
  998. sfp->next += 3;
  999. break;
  1000. case(SAMP_2424):
  1001. /*ssamp.lsamp = (int) floor(0.5 + *fp * MAXINT);*/
  1002. ssamp.lsamp = (int) cdp_round(*fp * MAXINT);
  1003. //#ifdef LSBFIRST
  1004. sfp->next[0] = ssamp.bytes[1];
  1005. sfp->next[1] = ssamp.bytes[2];
  1006. sfp->next[2] = ssamp.bytes[3];
  1007. //#else
  1008. // sfp->next[0] = ssamp.bytes[0];
  1009. // sfp->next[1] = ssamp.bytes[1];
  1010. // sfp->next[2] = ssamp.bytes[2];
  1011. //#endif
  1012. sfp->next += 3;
  1013. break;
  1014. case(SAMP_LONG):
  1015. /* *(long *)sfp->next = (long) floor(0.5 + *fp * MAXINT);*/
  1016. *(int *)sfp->next = (int) cdp_round(*fp * MAXINT);
  1017. sfp->next += sizeof(int);
  1018. break;
  1019. case(SAMP_2432):
  1020. /*ssamp.lsamp = (int) floor(0.5 + *fp * MAXINT);*/
  1021. ssamp.lsamp = (int) cdp_round(*fp * MAXINT);
  1022. ssamp.bytes[0] = 0;
  1023. *(int *)sfp->next = ssamp.lsamp;
  1024. sfp->next += sizeof(int);
  1025. break;
  1026. default:
  1027. rsferrno = ESFBADPARAM;
  1028. rsferrstr = "attempted to write unknown sample format";
  1029. return -1; /*do others later...*/
  1030. break;
  1031. }
  1032. if(sfp->next > sfp->endbuf)
  1033. sfp->endbuf = sfp->next;
  1034. if(--sfp->remain == 0) {
  1035. if(sndflsbufEx(sfp))
  1036. return -1;
  1037. }
  1038. return 1;
  1039. }
  1040. /*
  1041. * fgetfbuf - get a sequence of float-sams
  1042. */
  1043. /*RWD.6.99 probably the tidiest way of dealing with old floatsam files
  1044. * expect_float must be non-zero to trigger
  1045. */
  1046. int
  1047. fgetfbufEx(float *fp, int n, int sfd,int expect_floats)
  1048. {
  1049. register struct sndfile *sfp;
  1050. int chunk;
  1051. int cnt = 0;
  1052. #ifdef ENABLE_PVX
  1053. int rc;
  1054. #endif
  1055. if(!mapsndfd(&sfd))
  1056. return -1;
  1057. sfp = sndfiles[sfd];
  1058. #ifdef ENABLE_PVX
  1059. rc = sf_ispvx(sfp->fd);
  1060. if(rc < 0){
  1061. # ifdef _DEBUG
  1062. fprintf(stderr,"fgetfbufEx: bad sf id\n");
  1063. # endif
  1064. return cnt;
  1065. }
  1066. else if(rc){
  1067. PVOCDATA pvxdata;
  1068. int n_frames = 0;
  1069. int binsamps;
  1070. int pvxfd = get_pvxfd(sfp->fd,&pvxdata);
  1071. // we absolutely have to confirm n is exact multiple of nAnalysisBins * 2)
  1072. binsamps = pvxdata.nAnalysisBins * 2;
  1073. if((n % binsamps) != 0){
  1074. # ifdef _DEBUG
  1075. fprintf(stderr,"fgetfbufEx: buffersize(%d) must be multiple of analysis frame size\n",n);
  1076. # endif
  1077. cnt = 0;
  1078. }
  1079. n_frames = n / binsamps;
  1080. // test sfp->samptype too?
  1081. cnt = pvoc_getframes(pvxfd , fp, n_frames);
  1082. if(cnt <= 0)
  1083. cnt = 0; // EOF or error
  1084. else
  1085. cnt *= binsamps;
  1086. return cnt;
  1087. }
  1088. #endif
  1089. // std CDP files from here
  1090. if(sfp->samptype==SAMP_FLOAT || ((sfp->samptype==INT_32) && expect_floats)){
  1091. while(cnt < n) {
  1092. if(sfp->remain == 0) {
  1093. if(sndfilbuf(sfp) || sfp->remain == 0)
  1094. return cnt;
  1095. }
  1096. chunk = n - cnt;
  1097. if(chunk > sfp->remain)
  1098. chunk = sfp->remain;
  1099. memcpy((char *)fp, sfp->next, chunk*sizeof(float));
  1100. sfp->remain -= chunk;
  1101. sfp->next += chunk*sizeof(float);
  1102. cnt += chunk;
  1103. fp += chunk;
  1104. }
  1105. }
  1106. else{
  1107. sfd += SNDFDBASE;
  1108. while(cnt < n && (fgetfloatEx(fp++, sfd,expect_floats) > 0))
  1109. cnt++;
  1110. /*return cnt;*/
  1111. }
  1112. return cnt;
  1113. }
  1114. /*
  1115. * fputfbuf - put a sequence of float-sams
  1116. */
  1117. int
  1118. fputfbuf(float *fp, int n, int sfd)
  1119. {
  1120. register struct sndfile *sfp;
  1121. int chunk;
  1122. int cnt = 0;
  1123. if(!mapsndfd(&sfd))
  1124. return -1;
  1125. sfp = sndfiles[sfd];
  1126. if(sfp->samptype == SAMP_SHORT) {
  1127. sfd += SNDFDBASE;
  1128. while(cnt < n && fputfloat(fp++, sfd) > 0)
  1129. cnt++;
  1130. return cnt;
  1131. }
  1132. while(cnt < n) {
  1133. sfp->flags |= SNDFLG_WRITTEN;
  1134. /* sndtell checks this*/
  1135. sfp->flags |= SNDFLG_LASTWR;
  1136. chunk = n - cnt;
  1137. if(chunk > sfp->remain)
  1138. chunk = sfp->remain;
  1139. memcpy(sfp->next, (char *)fp, chunk*sizeof(float));
  1140. sfp->remain -= chunk;
  1141. sfp->next += chunk*sizeof(float);
  1142. if(sfp->next > sfp->endbuf)
  1143. sfp->endbuf = sfp->next;
  1144. cnt += chunk;
  1145. fp += chunk;
  1146. if(sfp->remain == 0) {
  1147. if(sndflsbuf(sfp))
  1148. return -1;
  1149. if(sfp->remain == 0)
  1150. return cnt;
  1151. }
  1152. }
  1153. return cnt;
  1154. }
  1155. #ifdef ENABLE_PVX
  1156. // not used yet...
  1157. int snd_getpvxfno(int sfd)
  1158. {
  1159. register struct sndfile *sfp;
  1160. if(!mapsndfd(&sfd))
  1161. return -1;
  1162. sfp = sndfiles[sfd];
  1163. return sfp->pvxid;
  1164. }
  1165. #endif
  1166. int
  1167. fputfbufEx(float *fp, int n, int sfd)
  1168. {
  1169. register struct sndfile *sfp;
  1170. int chunk;
  1171. int cnt = 0;
  1172. #ifdef ENABLE_PVX
  1173. int rc;
  1174. #endif
  1175. if(!mapsndfd(&sfd))
  1176. return -1;
  1177. sfp = sndfiles[sfd];
  1178. #ifdef ENABLE_PVX
  1179. rc = sf_ispvx(sfp->fd);
  1180. if(rc < 0)
  1181. return -1;
  1182. else if(rc) {
  1183. PVOCDATA pvxdata;
  1184. int n_frames = 0;
  1185. int binsamps;
  1186. int rc;
  1187. int pvxid = -1;
  1188. pvxid = get_pvxfd(sfp->fd,&pvxdata);
  1189. if(pvxid < 0){
  1190. # ifdef _DEBUG
  1191. fprintf(stderr,"fputfbufEx: bad pvx id %d\n",pvxid);
  1192. # endif
  1193. return cnt;
  1194. }
  1195. else {
  1196. // we absolutely have to confirm n is exact multiple of nAnalysisBins * 2)
  1197. # ifdef _DEBUG
  1198. assert(pvxid >= 0);
  1199. assert(pvxdata.nAnalysisBins > 0);
  1200. # endif
  1201. binsamps = pvxdata.nAnalysisBins * 2;
  1202. if((n % binsamps) != 0){
  1203. # ifdef _DEBUG
  1204. fprintf(stderr,"fputfbufEx: buffersize(%d) must be multiple of analysis frame size\n",n);
  1205. # endif
  1206. cnt = 0;
  1207. }
  1208. n_frames = n / binsamps;
  1209. // test sfp->samptype too?
  1210. cnt = pvoc_putframes(pvxid, fp, n_frames);
  1211. if(cnt <= 0)
  1212. cnt = 0; // EOF or error
  1213. else
  1214. cnt *= binsamps;
  1215. return binsamps * n_frames;
  1216. }
  1217. }
  1218. #endif
  1219. // std CDP files from here
  1220. if(sfp->samptype == SAMP_SHORT) {
  1221. sfd += SNDFDBASE;
  1222. while(cnt < n && fputfloatEx(fp++, sfd) > 0)
  1223. cnt++;
  1224. return cnt;
  1225. }
  1226. if(sfp->samptype == SAMP_FLOAT){
  1227. while(cnt < n) {
  1228. sfp->flags |= SNDFLG_WRITTEN;
  1229. /* sndtell checks this*/
  1230. sfp->flags |= SNDFLG_LASTWR;
  1231. chunk = n - cnt;
  1232. if(chunk > sfp->remain)
  1233. chunk = sfp->remain;
  1234. memcpy(sfp->next, (char *)fp, chunk*sizeof(float));
  1235. sfp->remain -= chunk;
  1236. sfp->next += chunk*sizeof(float);
  1237. if(sfp->next > sfp->endbuf)
  1238. sfp->endbuf = sfp->next;
  1239. cnt += chunk;
  1240. fp += chunk;
  1241. if(sfp->remain == 0) {
  1242. if(sndflsbufEx(sfp))
  1243. return -1;
  1244. if(sfp->remain == 0)
  1245. return cnt;
  1246. }
  1247. }
  1248. }
  1249. else {
  1250. sfd += SNDFDBASE;
  1251. while(cnt < n && fputfloatEx(fp++, sfd) > 0)
  1252. cnt++;
  1253. return cnt;
  1254. }
  1255. return cnt;
  1256. }
  1257. /* RWD.7.99 use cdp_round() instead of floor(): later, try shoft/truncate and/or dithering! */
  1258. int
  1259. fgetshortEx(short *sp, int sfd,int expect_floats)
  1260. {
  1261. struct sndfile *sfp;
  1262. int lword = 0;
  1263. int mask;
  1264. SND_SAMP ssamp;
  1265. if(!mapsndfd(&sfd))
  1266. return -1;
  1267. sfp = sndfiles[sfd];
  1268. if(sfp->remain < 0)
  1269. return 0;
  1270. if(sfp->remain-- == 0) {
  1271. if(sndfilbuf(sfp))
  1272. return -1;
  1273. if(sfp->remain-- <= 0)
  1274. return 0;
  1275. }
  1276. ssamp.lsamp = 0;
  1277. switch(sfp->samptype){
  1278. case(SAMP_FLOAT):
  1279. if(sfp->scale_floats==1)
  1280. /* *sp = (short)(floor(0.5 + (sfp->fscalefac * (*(float *)sfp->next * MAXSHORT))));*/
  1281. *sp = (short) cdp_round((sfp->fscalefac * (*(float *)sfp->next * MAXSHORT)));
  1282. else
  1283. /* *sp = (short)floor(0.5 + *(float *)sfp->next * MAXSHORT);*/
  1284. *sp = (short) cdp_round( *(float *)sfp->next * MAXSHORT);
  1285. sfp->next += sizeof(float);
  1286. break;
  1287. case(SAMP_SHORT):
  1288. *sp = *(short *)sfp->next;
  1289. sfp->next += sizeof(short);
  1290. break;
  1291. case(SAMP_LONG):
  1292. if(expect_floats){
  1293. if(sfp->scale_floats==1)
  1294. /* *sp = (short)(floor(0.5 + (sfp->fscalefac * (*(float *)sfp->next * MAXSHORT))));*/
  1295. *sp = (short) cdp_round((sfp->fscalefac * (*(float *)sfp->next * MAXSHORT)));
  1296. else
  1297. /* *sp = (short)floor(0.5 + *(float *)sfp->next * MAXSHORT);*/
  1298. *sp = (short) cdp_round( *(float *)sfp->next * MAXSHORT);
  1299. sfp->next += sizeof(float);
  1300. }
  1301. else{
  1302. *sp = (short)( (*(int *)sfp->next) >> 16);
  1303. sfp->next += sizeof(int);
  1304. }
  1305. break;
  1306. case(SAMP_2432):
  1307. /*mask the word first*/
  1308. lword = *(int *)sfp->next;
  1309. lword &= 0xffffff00;
  1310. *sp = (short)(lword >> 16);
  1311. sfp->next += sizeof(int);
  1312. break;
  1313. case(SAMP_2024): /*need to mask it?*/
  1314. mask = _rsf_getbitmask(sfp->fd);
  1315. if(mask==0)
  1316. return -1;
  1317. ssamp.bytes[1] = sfp->next[0];
  1318. ssamp.bytes[2] = sfp->next[1];
  1319. ssamp.bytes[3] = sfp->next[2];
  1320. *sp = (short)((ssamp.lsamp & mask) >> 16);
  1321. sfp->next += 3;
  1322. break;
  1323. case(SAMP_2424):
  1324. ssamp.bytes[1] = sfp->next[0];
  1325. ssamp.bytes[2] = sfp->next[1];
  1326. ssamp.bytes[3] = sfp->next[2];
  1327. *sp = (short)(ssamp.lsamp >> 16);
  1328. sfp->next += 3;
  1329. break;
  1330. default:
  1331. rsferrno = ESFBADPARAM;
  1332. rsferrstr = "attempted to read unknown sample format";
  1333. return -1; /*do others later...*/
  1334. break;
  1335. }
  1336. return 1;
  1337. }
  1338. int
  1339. fputshortEx(short *sp, int sfd)
  1340. {
  1341. register struct sndfile *sfp;
  1342. SND_SAMP ssamp;
  1343. if(!mapsndfd(&sfd))
  1344. return -1;
  1345. sfp = sndfiles[sfd];
  1346. if(sfp->flags&SNDFLG_ATEND)
  1347. return 0;
  1348. sfp->flags |= SNDFLG_WRITTEN;
  1349. /* sndtell checks this*/
  1350. sfp->flags |= SNDFLG_LASTWR;
  1351. ssamp.lsamp = 0;
  1352. switch(sfp->samptype){
  1353. case(SAMP_FLOAT):
  1354. *(float *)sfp->next = (float)*sp / (float)MAXSHORT;
  1355. sfp->next += sizeof(float);
  1356. break;
  1357. case(SAMP_SHORT):
  1358. *(short *)sfp->next = *sp;
  1359. sfp->next += sizeof(short);
  1360. break;
  1361. case(SAMP_2024):
  1362. /*no need to mask; 16 bits anyway!*/
  1363. case(SAMP_2424):
  1364. ssamp.lsamp = (int) ((*sp) << 16);
  1365. sfp->next[0] = ssamp.bytes[1];
  1366. sfp->next[1] = ssamp.bytes[2];
  1367. sfp->next[2] = ssamp.bytes[3];
  1368. sfp->next += 3;
  1369. break;
  1370. case(SAMP_LONG):
  1371. case(SAMP_2432):
  1372. ssamp.lsamp = (int) ((*sp) << 16);
  1373. *(int *)sfp->next = ssamp.lsamp;
  1374. sfp->next += sizeof(int);
  1375. break;
  1376. default:
  1377. rsferrno = ESFBADPARAM;
  1378. rsferrstr = "attempted to write unknown sample format";
  1379. return -1; /*do others later...*/
  1380. break;
  1381. }
  1382. if(sfp->next > sfp->endbuf)
  1383. sfp->endbuf = sfp->next;
  1384. if(--sfp->remain == 0) {
  1385. if(sndflsbufEx(sfp))
  1386. return -1;
  1387. }
  1388. return 1;
  1389. }
  1390. int
  1391. fgetsbufEx(short *sp, int n, int sfd,int expect_floats)
  1392. {
  1393. register struct sndfile *sfp;
  1394. int chunk;
  1395. int cnt = 0;
  1396. if(!mapsndfd(&sfd))
  1397. return -1;
  1398. sfp = sndfiles[sfd];
  1399. switch(sfp->samptype){
  1400. case(SAMP_SHORT):
  1401. while(cnt < n) {
  1402. if(sfp->remain <= 0) { /*RWD.6.99 was == 0*/
  1403. if(sndfilbuf(sfp) || (sfp->remain == 0))
  1404. return cnt;
  1405. }
  1406. chunk = n - cnt;
  1407. if(chunk > sfp->remain)
  1408. chunk = sfp->remain;
  1409. memcpy((char *)sp, sfp->next, chunk*sizeof(short));
  1410. sfp->remain -= chunk;
  1411. sfp->next += chunk*sizeof(short);
  1412. cnt += chunk;
  1413. sp += chunk;
  1414. }
  1415. break;
  1416. default:
  1417. sfd += SNDFDBASE;
  1418. while(cnt < n && fgetshortEx(sp++, sfd,expect_floats) > 0)
  1419. cnt++;
  1420. break;
  1421. }
  1422. return cnt;
  1423. }
  1424. int
  1425. fputsbufEx(short *sp, int n, int sfd)
  1426. {
  1427. register struct sndfile *sfp;
  1428. int chunk;
  1429. int cnt = 0;
  1430. if(!mapsndfd(&sfd))
  1431. return -1;
  1432. sfp = sndfiles[sfd];
  1433. switch(sfp->samptype){
  1434. case(SAMP_SHORT):
  1435. while(cnt < n) {
  1436. sfp->flags |= SNDFLG_WRITTEN;
  1437. /* sndtell checks this*/
  1438. sfp->flags |= SNDFLG_LASTWR;
  1439. chunk = n - cnt;
  1440. if(chunk > sfp->remain)
  1441. chunk = sfp->remain;
  1442. memcpy(sfp->next, (char *)sp, chunk*sizeof(short));
  1443. sfp->remain -= chunk;
  1444. sfp->next += chunk*sizeof(short);
  1445. if(sfp->next > sfp->endbuf)
  1446. sfp->endbuf = sfp->next;
  1447. cnt += chunk;
  1448. sp += chunk;
  1449. if(sfp->remain == 0) {
  1450. if(sndflsbufEx(sfp))
  1451. return -1;
  1452. if(sfp->remain == 0)
  1453. return cnt;
  1454. }
  1455. }
  1456. break;
  1457. default:
  1458. sfd += SNDFDBASE;
  1459. while(cnt < n && fputshortEx(sp++, sfd) > 0)
  1460. cnt++;
  1461. break;
  1462. }
  1463. return cnt;
  1464. }
  1465. /*
  1466. * The property stuff, for sndfiles
  1467. */
  1468. int
  1469. sndgetprop(int sfd, char *prop, char *dest, int lim)
  1470. {
  1471. if(!mapsndfd(&sfd))
  1472. return -1;
  1473. return sfgetprop(sndfiles[sfd]->fd, prop, dest, lim);
  1474. }
  1475. int
  1476. sndputprop(int sfd, char *prop, char *src, int size)
  1477. {
  1478. if(!mapsndfd(&sfd))
  1479. return -1;
  1480. if(strcmp(prop, "sample type") == 0) {
  1481. rsferrno = ESFNOSTYPE;
  1482. rsferrstr = "can't change sample type on sndfile";
  1483. return -1;
  1484. }
  1485. return sfputprop(sndfiles[sfd]->fd, prop, src, size);
  1486. }
  1487. int
  1488. sndrmprop(int sfd, char *prop)
  1489. {
  1490. if(!mapsndfd(&sfd))
  1491. return -1;
  1492. if(strcmp(prop, "sample type") == 0) {
  1493. rsferrno = ESFNOSTYPE;
  1494. rsferrstr = "can't remove sample type on sndfile";
  1495. return -1;
  1496. }
  1497. return sfrmprop(sndfiles[sfd]->fd, prop);
  1498. }
  1499. int
  1500. snddirprop(int sfd, int (*func)(char *propname, int propsize))
  1501. {
  1502. if(!mapsndfd(&sfd))
  1503. return -1;
  1504. return sfdirprop(sndfiles[sfd]->fd, func);
  1505. }
  1506. /*RWD OCT97*/
  1507. int sndgetwordsize(int sfd)
  1508. {
  1509. if(!mapsndfd(&sfd))
  1510. return -1;
  1511. return sfgetwordsize(sndfiles[sfd]->fd);
  1512. }
  1513. /*recognise shortcuts in WIN32*/
  1514. #if defined _WIN32
  1515. /*TODO: add arg for full targetname*/
  1516. int snd_is_shortcut(int sfd)
  1517. {
  1518. if(!mapsndfd(&sfd))
  1519. return -1;
  1520. return sf_is_shortcut(sndfiles[sfd]->fd,NULL);
  1521. }
  1522. #endif
  1523. /*RWD.5.99*/
  1524. int snd_fileformat(int sfd, fileformat *pfmt)
  1525. {
  1526. if(!mapsndfd(&sfd))
  1527. return -1;
  1528. /* RWD 2022: this should now recognise pvx file as PVOCEX */
  1529. return sfformat(sndfiles[sfd]->fd,pfmt);
  1530. }
  1531. int sndgetchanmask(int sfd)
  1532. {
  1533. if(!mapsndfd(&sfd))
  1534. return -1;
  1535. return sfgetchanmask(sndfiles[sfd]->fd);
  1536. }
  1537. int snd_getchanformat(int sfd, channelformat *chformat)
  1538. {
  1539. if(!mapsndfd(&sfd))
  1540. return -1;
  1541. return sf_getchanformat(sndfiles[sfd]->fd,chformat);
  1542. }
  1543. int sndreadpeaks(int sfd,int channels,CHPEAK peakdata[],int *peaktime)
  1544. {
  1545. if(!mapsndfd(&sfd))
  1546. return -1;
  1547. return sfreadpeaks(sndfiles[sfd]->fd,(int) channels,peakdata,peaktime);
  1548. }
  1549. int sndputpeaks(int sfd,int channels,const CHPEAK peakdata[])
  1550. {
  1551. if(!mapsndfd(&sfd))
  1552. return -1;
  1553. return sfputpeaks(sndfiles[sfd]->fd,channels,peakdata);
  1554. }
  1555. const char * snd_getfilename(int sfd)
  1556. {
  1557. if(!mapsndfd(&sfd))
  1558. return NULL;
  1559. return sf_getfilename(sndfiles[sfd]->fd);
  1560. }
  1561. extern int sf_makepath(char path[], const char* sfname);
  1562. int snd_makepath(char path[], const char* sfname)
  1563. {
  1564. return sf_makepath(path,sfname);
  1565. }