snd.c 48 KB

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