sndfile.c
上传用户:sy_wanhua
上传日期:2013-07-25
资源大小:3048k
文件大小:33k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

C/C++

  1. /*
  2. ** Copyright (C) 1999-2000 Erik de Castro Lopo <erikd@zip.com.au>
  3. **  
  4. ** This program is free software; you can redistribute it and/or modify
  5. ** it under the terms of the GNU Lesser General Public License as published by
  6. ** the Free Software Foundation; either version 2.1 of the License, or
  7. ** (at your option) any later version.
  8. ** 
  9. ** This program is distributed in the hope that it will be useful,
  10. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. ** GNU Lesser General Public License for more details.
  13. ** 
  14. ** You should have received a copy of the GNU Lesser General Public License
  15. ** along with this program; if not, write to the Free Software 
  16. ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. */
  18. #include <stdio.h>
  19. #include <unistd.h>
  20. #include <fcntl.h>
  21. #include <string.h>
  22. #include <ctype.h>
  23. /* For the Metrowerks CodeWarrior Pro Compiler (mainly MacOS) */
  24. #if (defined (__MWERKS__))
  25. #include <stat.h>
  26. #else
  27. #include <sys/stat.h>
  28. #endif
  29. #include "sndfile.h"
  30. #include "config.h"
  31. #include "sfendian.h"
  32. #include "common.h"
  33. #if (CPU_IS_LITTLE_ENDIAN == 1)
  34. # define MAKE_MARKER(a,b,c,d) ((a)|((b)<<8)|((c)<<16)|((d)<<24))
  35. #elif (CPU_IS_BIG_ENDIAN == 1)
  36. # define MAKE_MARKER(a,b,c,d) (((a)<<24)|((b)<<16)|((c)<<8)|(d))
  37. #else
  38. # error "Cannot determine endian-ness of processor."
  39. #endif
  40. #define SNDFILE_MAGICK 0x1234C0DE
  41. typedef struct
  42. { int  error ;
  43. char *str ;
  44. } ErrorStruct ;
  45. static
  46. ErrorStruct SndfileErrors [] = 
  47. { SFE_NO_ERROR , "No Error." },
  48. { SFE_BAD_FILE , "File does not exist or is not a regular file (possibly a pipe?)." },
  49. { SFE_OPEN_FAILED , "Could not open file." },
  50. { SFE_BAD_OPEN_FORMAT , "Bad format specified for file open." },
  51. { SFE_BAD_SNDFILE_PTR , "Not a valid SNDFILE* pointer." },
  52. { SFE_BAD_SF_INFO_PTR , "NULL SF_INFO pointer passed to libsndfile." },
  53. { SFE_BAD_INT_FD , "Bad file descriptor." },
  54. { SFE_BAD_INT_PTR , "Internal error, Bad pointer." },
  55. { SFE_MALLOC_FAILED , "Internal malloc () failed." },
  56. { SFE_BAD_SEEK , "Internal fseek() failed." },
  57. { SFE_NOT_SEEKABLE , "Seek attempted on unseekable file type." },
  58. { SFE_UNIMPLEMENTED , "File contains data in an unimplemented format." },
  59. { SFE_BAD_READ_ALIGN   , "Attempt to read a non-integer number of channels." },
  60. { SFE_BAD_WRITE_ALIGN  , "Attempt to write a non-integer number of channels." },
  61. { SFE_UNKNOWN_FORMAT , "File contains data in an unknown format." },
  62. { SFE_NOT_READMODE , "Read attempted on file currently open for write." },
  63. { SFE_NOT_WRITEMODE , "Write attempted on file currently open for read." },
  64. { SFE_BAD_MODE_RW , "This file format does not support read/write mode." },
  65. { SFE_BAD_SF_INFO , "Internal error : SF_INFO struct incomplete." },
  66. { SFE_SHORT_READ , "Short read error." },
  67. { SFE_SHORT_WRITE , "Short write error." },
  68. { SFE_INTERNAL , "Unspecified internal error." },
  69. { SFE_WAV_NO_RIFF , "Error in WAV file. No 'RIFF' chunk marker." },
  70. { SFE_WAV_NO_WAVE , "Error in WAV file. No 'WAVE' chunk marker." },
  71. { SFE_WAV_NO_FMT , "Error in WAV file. No 'fmt ' chunk marker." },
  72. { SFE_WAV_FMT_SHORT , "Error in WAV file. Short 'fmt ' chunk." },
  73. { SFE_WAV_FMT_TOO_BIG , "Error in WAV file. 'fmt ' chunk too large." },
  74. { SFE_WAV_BAD_FORMAT , "Error in WAV file. Errors in 'fmt ' chunk." },
  75. { SFE_WAV_BAD_BLOCKALIGN , "Error in WAV file. Block alignment in 'fmt ' chunk is incorrect." },
  76. { SFE_WAV_NO_DATA , "Error in WAV file. No 'data' chunk marker." },
  77. { SFE_WAV_UNKNOWN_CHUNK , "Error in WAV file. File contains an unknown chunk marker." },
  78. { SFE_WAV_ADPCM_NOT4BIT , "Error in ADPCM WAV file. Invalid bit width."},
  79. { SFE_WAV_ADPCM_CHANNELS , "Error in ADPCM WAV file. Invalid number of channels."},
  80. { SFE_WAV_GSM610_FORMAT , "Error in GSM610 WAV file. Invalid format chunk."},
  81.   
  82. { SFE_AIFF_NO_FORM , "Error in AIFF file, bad 'FORM' marker."},
  83. { SFE_AIFF_UNKNOWN_CHUNK , "Error in AIFF file, unknown chunk."},
  84. { SFE_COMM_CHUNK_SIZE , "Error in AIFF file, bad 'COMM' chunk size."},
  85. { SFE_AIFF_NO_SSND , "Error in AIFF file, bad 'SSND' chunk."},
  86. { SFE_AIFF_NO_DATA , "Error in AIFF file, no sound data."},
  87. { SFE_AU_UNKNOWN_FORMAT , "Error in AU file, unknown format."},
  88. { SFE_AU_NO_DOTSND , "Error in AU file, missing '.snd' or 'dns.' marker."},
  89. { SFE_RAW_READ_BAD_SPEC , "Error while opening RAW file for read. Must specify format, pcmbitwidth and channels."},
  90. { SFE_RAW_BAD_BITWIDTH , "Error. RAW file bitwidth must be a multiple of 8."},
  91. { SFE_PAF_NO_MARKER , "Error in PAF file, no marker."},
  92. { SFE_PAF_VERSION , "Error in PAF file, bad version."}, 
  93. { SFE_PAF_UNKNOWN_FORMAT , "Error in PAF file, unknown format."}, 
  94. { SFE_PAF_SHORT_HEADER , "Error in PAF file. File shorter than minimal header."},
  95. { SFE_SVX_NO_FORM , "Error in 8SVX / 16SV file, no 'FORM' marker."}, 
  96. { SFE_SVX_NO_BODY , "Error in 8SVX / 16SV file, no 'BODY' marker."}, 
  97. { SFE_SVX_NO_DATA , "Error in 8SVX / 16SV file, no sound data."},
  98. { SFE_SVX_BAD_COMP , "Error in 8SVX / 16SV file, unsupported compression format."},
  99. { SFE_NIST_BAD_HEADER , "Error in NIST file, bad header."},
  100. { SFE_NIST_BAD_ENCODING , "Error in NIST file, unsupported compression format."},
  101. { SFE_MAX_ERROR , "Maximum error number." }
  102. } ;
  103. /*------------------------------------------------------------------------------
  104. ** Private (static) variables.
  105. */
  106. static int sf_errno = 0 ;
  107. static char sf_strbuffer [SF_BUFFER_LEN] = { 0 } ;
  108. /*------------------------------------------------------------------------------
  109. ** Private static functions.
  110. */
  111. #define VALIDATE_SNDFILE_AND_ASSIGN_PSF(a,b)
  112. { if (! (a))
  113. return SFE_BAD_SNDFILE_PTR ;
  114. (b) = (SF_PRIVATE*) (a) ;
  115. if (!((b)->file))
  116. return SFE_BAD_INT_FD ;
  117. if ((b)->Magick != SNDFILE_MAGICK)
  118. return SFE_BAD_SNDFILE_PTR ;
  119. (b)->error = 0 ;
  120. static
  121. int does_extension_match (const char *ext, const char *test)
  122. { char c1, c2 ;
  123. if ((! ext) || (! test))
  124. return 0 ;
  125. if (strlen (ext) != strlen (test))
  126. return 0 ;
  127. while (*ext && *test)
  128. { c1 = tolower (*ext) ;
  129. c2 = tolower (*test) ;
  130. if (c1 > c2)
  131. return 0 ;
  132. if (c1 < c2)
  133. return 0 ;
  134. ext ++ ;
  135. test ++ ;
  136. return 1 ;
  137. } /* does_extension_match */
  138. static
  139. int is_au_snd_file (const char *filename)
  140. { const char *cptr ;
  141. if (! (cptr = strrchr (filename, '.')))
  142. return 0 ;
  143. cptr ++ ;
  144. if (does_extension_match (cptr, "au"))
  145. return 1 ;
  146. if (does_extension_match (cptr, "snd"))
  147. return 1 ;
  148. return 0 ;
  149. } /* is_au_snd_file */
  150. static
  151. int guess_file_type (FILE *file, const char *filename)
  152. { unsigned int buffer [3] ;
  153. fread (buffer, sizeof(buffer), 1, file) ;
  154. fseek (file, 0, SEEK_SET) ;
  155. if (buffer [0] == MAKE_MARKER ('R','I','F','F') && buffer [2] == MAKE_MARKER ('W','A','V','E'))
  156. return SF_FORMAT_WAV ;
  157. if (buffer [0] == MAKE_MARKER ('F','O','R','M'))
  158. { if (buffer [2] == MAKE_MARKER ('A','I','F','F') || buffer [2] == MAKE_MARKER ('A','I','F','C'))
  159. return SF_FORMAT_AIFF ;
  160. if (buffer [2] == MAKE_MARKER ('8','S','V','X') || buffer [2] == MAKE_MARKER ('1','6','S','V'))
  161. return SF_FORMAT_SVX ;
  162. return 0 ;
  163. } ;
  164. if ((buffer [0] == MAKE_MARKER ('.','s','n','d') || buffer [0] == MAKE_MARKER ('d','n','s','.')))
  165. return SF_FORMAT_AU ;
  166. if ((buffer [0] == MAKE_MARKER ('f','a','p',' ') || buffer [0] == MAKE_MARKER (' ','p','a','f')))
  167. return SF_FORMAT_PAF ;
  168. if (buffer [0] == MAKE_MARKER ('N','I','S','T'))
  169. return SF_FORMAT_NIST ;
  170. if (filename && is_au_snd_file (filename))
  171. return SF_FORMAT_AU | SF_FORMAT_ULAW ;
  172. /* Default to header-less RAW PCM file type. */
  173. return SF_FORMAT_RAW ;
  174. } /* guess_file_type */
  175. static
  176. int validate_sfinfo (SF_INFO *sfinfo)
  177. { if (! sfinfo->samplerate)
  178. return 0 ;
  179. if (! sfinfo->samples && (sfinfo->format & SF_FORMAT_SUBMASK != SF_FORCE_OPEN) ) //or
  180. return 0 ;
  181. if (! sfinfo->channels)
  182. return 0 ;
  183. if (! sfinfo->pcmbitwidth && (sfinfo->format & SF_FORMAT_SUBMASK != SF_FORCE_OPEN) ) //or
  184. return 0 ;
  185. if (! sfinfo->format & SF_FORMAT_TYPEMASK)
  186. return 0 ;
  187. if (! sfinfo->format & SF_FORMAT_SUBMASK)
  188. return 0 ;
  189. if (! sfinfo->sections)
  190. return 0 ;
  191. return 1 ;
  192. } /* validate_sfinfo */
  193. static
  194. int validate_psf (SF_PRIVATE *psf)
  195. {
  196. if (! psf->blockwidth && (psf->sf.format & SF_FORMAT_SUBMASK != SF_FORCE_OPEN) ) //or
  197. return 0 ;
  198. if (! psf->bytewidth && (psf->sf.format & SF_FORMAT_SUBMASK != SF_FORCE_OPEN)  ) //or
  199. return 0 ;
  200. if (! psf->datalength )
  201. return 0 ;
  202. if (psf->blockwidth != psf->sf.channels * psf->bytewidth)
  203. return 0 ;
  204. return 1 ;
  205. } /* validate_psf */
  206. static
  207. void save_header_info (SF_PRIVATE *psf)
  208. { memset (sf_strbuffer, 0, sizeof (sf_strbuffer)) ;
  209. strcpy (sf_strbuffer, psf->strbuffer) ;
  210. } /* validate_psf */
  211. static
  212. void copy_filename (SF_PRIVATE *psf, const char *path)
  213. { const char *cptr ;
  214. if ((cptr = strrchr (path, '/')) || (cptr = strrchr (path, '\')))
  215. cptr ++ ;
  216. else
  217. cptr = path ;
  218. memset (psf->filename, 0, SF_FILENAME_LEN) ;
  219. strncpy (psf->filename, cptr, SF_FILENAME_LEN - 1) ;
  220. psf->filename [SF_FILENAME_LEN - 1] = 0 ;
  221. } /* copy_filename */
  222. /*------------------------------------------------------------------------------
  223. ** Public functions.
  224. */
  225. SNDFILE*  sf_open_read (const char *path, SF_INFO *sfinfo)
  226. { SF_PRIVATE  *psf ;
  227. int filetype, seekable ;
  228. if (! sfinfo)
  229. { sf_errno = SFE_BAD_SF_INFO_PTR ;
  230. return NULL ;
  231. } ;
  232. sf_errno = 0 ;
  233. sf_strbuffer [0] = 0 ;
  234. psf = malloc (sizeof (SF_PRIVATE)) ; 
  235. if (! psf)
  236. { sf_errno = SFE_MALLOC_FAILED ;
  237. return NULL ;
  238. } ;
  239. memset (psf, 0, sizeof (SF_PRIVATE)) ;
  240. psf->Magick = SNDFILE_MAGICK ;
  241. if (! strcmp (path, "-"))
  242. { psf->file = stdin ;
  243. seekable = SF_FALSE ;
  244. }
  245. else
  246. { /* fopen with 'b' means binary file mode for Win32 systems. */
  247. psf->file = fopen (path, "rb") ;
  248. seekable = SF_TRUE ;
  249. } ;
  250.  
  251. if (! psf->file) 
  252. { sf_errno = SFE_OPEN_FAILED ;
  253. sf_close (psf) ;
  254. return NULL ;
  255. } ;
  256. psf->mode = SF_MODE_READ ;
  257. psf_sprintf (psf, "%sn", path) ;
  258. if (seekable)
  259. { fseek (psf->file, 0, SEEK_END) ;
  260. psf->filelength = ftell (psf->file) ;
  261. fseek (psf->file, 0, SEEK_SET) ;
  262. psf_sprintf (psf, "size : %dn", psf->filelength) ;
  263. }
  264. else
  265. psf->filelength = 2048 ;
  266. copy_filename (psf, path) ;
  267. filetype = guess_file_type (psf->file, psf->filename) ;
  268. fseek (psf->file, 0, SEEK_SET) ;
  269. //or
  270. memcpy (&(psf->sf), sfinfo, sizeof (SF_INFO)) ;
  271. // end or
  272. switch (filetype)
  273. { case SF_FORMAT_WAV :
  274. sf_errno = wav_open_read (psf) ;
  275. break ;
  276. case SF_FORMAT_AIFF :
  277. sf_errno = aiff_open_read (psf) ;
  278. break ;
  279. case SF_FORMAT_AU :
  280. sf_errno = au_open_read (psf) ;
  281. break ;
  282. case SF_FORMAT_AU | SF_FORMAT_ULAW :
  283. psf_sprintf (psf, "Headers-less u-law encoded file.n") ;
  284. sf_errno = au_nh_open_read (psf) ;
  285. break ;
  286. case SF_FORMAT_RAW :
  287. /* For RAW files, need the sfinfo struct data to
  288. ** figure out the bitwidth, endian-ness etc.
  289. */
  290. memcpy (&(psf->sf), sfinfo, sizeof (SF_INFO)) ;
  291. sf_errno = raw_open_read (psf) ;
  292. break ;
  293. case SF_FORMAT_PAF :
  294. sf_errno = paf_open_read (psf) ;
  295. break ;
  296. case SF_FORMAT_SVX :
  297. sf_errno = svx_open_read (psf) ;
  298. break ;
  299. default :
  300. sf_errno = SFE_UNKNOWN_FORMAT ;
  301. } ;
  302. /* Both the file format and the file must be seekable to enable sf_seek(). */
  303. psf->sf.seekable = (psf->sf.seekable && seekable) ? SF_TRUE : SF_FALSE ;
  304. if (sf_errno)
  305. { save_header_info (psf) ;
  306. sf_close (psf) ;
  307. return NULL ;
  308. } ;
  309. if (! validate_sfinfo (&(psf->sf)))
  310. { save_header_info (psf) ;
  311. sf_errno = SFE_BAD_SF_INFO ;
  312. sf_close (psf) ;
  313. return NULL ;
  314. } ;
  315. if (! validate_psf (psf))
  316. { save_header_info (psf) ;
  317. sf_errno = SFE_INTERNAL ;
  318. sf_close (psf) ;
  319. return NULL ;
  320. } ;
  321. memcpy (sfinfo, &(psf->sf), sizeof (SF_INFO)) ;
  322. return (SNDFILE*) psf ;
  323. } /* sf_open_read */
  324. /*------------------------------------------------------------------------------
  325. */
  326. SNDFILE*  sf_open_write (const char *path, const SF_INFO *sfinfo)
  327. { SF_PRIVATE  *psf ;
  328. if (! sfinfo)
  329. { sf_errno = SFE_BAD_SF_INFO_PTR ;
  330. return NULL ;
  331. } ;
  332. if (! sf_format_check (sfinfo))
  333. { sf_errno = SFE_BAD_OPEN_FORMAT ;
  334. return NULL ;
  335. } ;
  336. sf_errno = 0 ;
  337. sf_strbuffer [0] = 0 ;
  338. psf = malloc (sizeof (SF_PRIVATE)) ; 
  339. if (! psf)
  340. { sf_errno = SFE_MALLOC_FAILED ;
  341. return NULL ;
  342. } ;
  343. memset (psf, 0, sizeof (SF_PRIVATE)) ;
  344. memcpy (&(psf->sf), sfinfo, sizeof (SF_INFO)) ;
  345. psf->Magick = SNDFILE_MAGICK ;
  346. /* fopen with 'b' means binary file mode for Win32 systems. */
  347. if (! (psf->file = fopen (path, "wb")))
  348. { sf_errno = SFE_OPEN_FAILED ;
  349. sf_close (psf) ;
  350. return NULL ;
  351. } ;
  352. psf->mode = SF_MODE_WRITE ;
  353. psf->filelength = ftell (psf->file) ;
  354. fseek (psf->file, 0, SEEK_SET) ;
  355. copy_filename (psf, path) ;
  356. switch (sfinfo->format & SF_FORMAT_TYPEMASK)
  357. { case SF_FORMAT_WAV :
  358. if ((sf_errno = wav_open_write (psf)))
  359. { sf_close (psf) ;
  360. return NULL ;
  361. } ;
  362. break ;
  363. case SF_FORMAT_AIFF :
  364. if ((sf_errno = aiff_open_write (psf)))
  365. { sf_close (psf) ;
  366. return NULL ;
  367. } ;
  368. break ;
  369. case SF_FORMAT_AU :
  370. case SF_FORMAT_AULE :
  371. if ((sf_errno = au_open_write (psf)))
  372. { sf_close (psf) ;
  373. return NULL ;
  374. } ;
  375. break ;
  376. case    SF_FORMAT_RAW :
  377. if ((sf_errno = raw_open_write (psf)))
  378. { sf_close (psf) ;
  379. return NULL ;
  380. } ;
  381. break ;
  382. case    SF_FORMAT_PAF :
  383. if ((sf_errno = paf_open_write (psf)))
  384. { sf_close (psf) ;
  385. return NULL ;
  386. } ;
  387. break ;
  388. case    SF_FORMAT_SVX :
  389. if ((sf_errno = svx_open_write (psf)))
  390. { sf_close (psf) ;
  391. return NULL ;
  392. } ;
  393. break ;
  394. default :
  395. sf_errno = SFE_UNKNOWN_FORMAT ;
  396. sf_close (psf) ;
  397. return NULL ;
  398. } ;
  399. return (SNDFILE*) psf ;
  400. } /* sf_open_write */
  401. /*------------------------------------------------------------------------------
  402. */
  403. int sf_perror (SNDFILE *sndfile)
  404. { SF_PRIVATE  *psf ;
  405. int  k, errnum ;
  406. if (! sndfile)
  407. { errnum = sf_errno ;
  408. }
  409. else
  410. { VALIDATE_SNDFILE_AND_ASSIGN_PSF(sndfile,psf) ;
  411. errnum = psf->error ;
  412. } ;
  413. errnum = (errnum >= SFE_MAX_ERROR || errnum < 0) ? 0 : errnum ;
  414. for (k = 0 ; SndfileErrors[k].str ; k++)
  415. if (errnum == SndfileErrors[k].error)
  416. { printf ("%sn", SndfileErrors[k].str) ;
  417. return SFE_NO_ERROR ;
  418. } ;
  419. printf ("No error string for error number %d.n", errnum) ;
  420. return SFE_NO_ERROR ;
  421. } /* sf_perror */
  422. /*------------------------------------------------------------------------------
  423. */
  424. int sf_set_bytewidth(SNDFILE *sndfile, SF_INFO* sfinfo)
  425. {   
  426.     SF_PRIVATE  *psf ;
  427.     VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile,psf) ;
  428.     psf->sf.pcmbitwidth=sfinfo->pcmbitwidth;
  429.     psf->sf.bytewidth=sfinfo->bytewidth;
  430.     psf->bytewidth=sfinfo->bytewidth;
  431.     psf->blockwidth = psf->sf.channels * psf->bytewidth ;
  432.     if ( psf->blockwidth)
  433. psf->sf.samples = psf->datalength / psf->blockwidth ;
  434.     sfinfo->samples=psf->sf.samples;
  435.     return 0;    
  436. }
  437. /*------------------------------------------------------------------------------
  438. */
  439. int sf_error_str (SNDFILE *sndfile, char *str, size_t maxlen)
  440. { SF_PRIVATE  *psf ;
  441. int  errnum, k ;
  442. if (! sndfile)
  443. { errnum = sf_errno ;
  444. }
  445. else
  446. { VALIDATE_SNDFILE_AND_ASSIGN_PSF(sndfile,psf) ;
  447. errnum = psf->error ;
  448. } ;
  449. errnum = (errnum >= SFE_MAX_ERROR || errnum < 0) ? 0 : errnum ;
  450. for (k = 0 ; SndfileErrors[k].str ; k++)
  451. if (errnum == SndfileErrors[k].error)
  452. { strncpy (str, SndfileErrors [errnum].str, maxlen) ;
  453. str [maxlen-1] = 0 ;
  454. return SFE_NO_ERROR ;
  455. } ;
  456. strncpy (str, "No error defined for this error number. This is a bug in libsndfile.", maxlen) ;
  457. str [maxlen-1] = 0 ;
  458. return SFE_NO_ERROR ;
  459. } /* sf_error_str */
  460. /*------------------------------------------------------------------------------
  461. */
  462. int sf_error_number (int errnum, char *str, size_t maxlen)
  463. { int  k ;
  464. errnum = (errnum >= SFE_MAX_ERROR || errnum < 0) ? 0 : errnum ;
  465. for (k = 0 ; SndfileErrors[k].str ; k++)
  466. if (errnum == SndfileErrors[k].error)
  467. { strncpy (str, SndfileErrors [errnum].str, maxlen) ;
  468. str [maxlen-1] = 0 ;
  469. return SFE_NO_ERROR ;
  470. } ;
  471. strncpy (str, "No error defined for this error number. This is a bug in libsndfile.", maxlen) ;
  472. str [maxlen-1] = 0 ;
  473. return SFE_NO_ERROR ;
  474. } /* sf_error_number */
  475. /*------------------------------------------------------------------------------
  476. */
  477. int sf_format_check (const SF_INFO *info)
  478. { int subformat = info->format & SF_FORMAT_SUBMASK ;
  479. int force_open; //or
  480. /* This is the place where each file format can check if the suppiled
  481. ** SF_INFO struct is valid.
  482. ** Return 0 on failure, 1 ons success. 
  483. */
  484. if (info->channels < 1 || info->channels > 256)
  485. return 0 ;
  486. //or
  487. force_open = ((info->format & SF_FORMAT_SUBMASK) == SF_FORCE_OPEN)?1:0;
  488. if(force_open && info->format_tag && info->bytewidth) 
  489.     return 1;
  490. //end or
  491. switch (info->format & SF_FORMAT_TYPEMASK)
  492. { case SF_FORMAT_WAV :
  493. if (subformat == SF_FORMAT_PCM && (info->pcmbitwidth >= 8 && info->pcmbitwidth <= 32))
  494. return 1 ;
  495. if (subformat == SF_FORMAT_FLOAT && info->pcmbitwidth == 32)
  496. return 1 ;
  497. if (subformat == SF_FORMAT_IMA_ADPCM && info->pcmbitwidth == 16 && info->channels <= 2)
  498. return 1 ;
  499. if (subformat == SF_FORMAT_MS_ADPCM && info->pcmbitwidth == 16 && info->channels <= 2)
  500. return 1 ;
  501. if (subformat == SF_FORMAT_GSM610 && info->pcmbitwidth == 16 && info->channels == 1)
  502. return 1 ;
  503. if (subformat == SF_FORMAT_ULAW || subformat == SF_FORMAT_ALAW)
  504. return 1 ;
  505. break ;
  506. case SF_FORMAT_AIFF :
  507. if (subformat == SF_FORMAT_PCM && (info->pcmbitwidth >= 8 && info->pcmbitwidth <= 32))
  508. return 1 ;
  509. break ;
  510. case SF_FORMAT_AU :
  511. case SF_FORMAT_AULE :
  512. if (subformat == SF_FORMAT_PCM && (info->pcmbitwidth >= 8 && info->pcmbitwidth <= 32))
  513. return 1 ;
  514. if (subformat == SF_FORMAT_ULAW)
  515. return 1 ;
  516. if (subformat == SF_FORMAT_ALAW)
  517. return 1 ;
  518. if (subformat == SF_FORMAT_G721_32 && info->channels == 1)
  519. return 1 ;
  520. if (subformat == SF_FORMAT_G723_24 && info->channels == 1)
  521. return 1 ;
  522. break ;
  523. case SF_FORMAT_RAW :
  524. if (subformat == SF_FORMAT_ULAW || subformat == SF_FORMAT_ALAW)
  525. return 1 ;
  526. if (subformat == SF_FORMAT_PCM_S8 && info->pcmbitwidth == 8)
  527. return 1 ;
  528. if (subformat == SF_FORMAT_PCM_U8 && info->pcmbitwidth == 8)
  529. return 1 ;
  530. if (subformat != SF_FORMAT_PCM_BE && subformat != SF_FORMAT_PCM_LE)
  531. break ;
  532. if (info->pcmbitwidth % 8 || info->pcmbitwidth > 32)
  533. break ;
  534. return 1 ;
  535. break ;
  536. case SF_FORMAT_PAF :
  537. if (subformat == SF_FORMAT_PCM_S8 && info->pcmbitwidth == 8)
  538. return 1 ;
  539. if (subformat != SF_FORMAT_PCM_BE && subformat != SF_FORMAT_PCM_LE)
  540. break ;
  541. if (info->pcmbitwidth % 8 || info->pcmbitwidth > 24)
  542. break ;
  543. return 1 ;
  544. break ;
  545. case SF_FORMAT_SVX :
  546. if (subformat == SF_FORMAT_PCM && (info->pcmbitwidth == 8 || info->pcmbitwidth == 16))
  547. return 1 ;
  548. break ;
  549. default : break ;
  550. } ;
  551. return 0 ;
  552. } /* sf_format_check */
  553. /*------------------------------------------------------------------------------
  554. */
  555. size_t sf_get_header_info (SNDFILE *sndfile, char *buffer, size_t bufferlen, size_t offset)
  556. { SF_PRIVATE *psf ;
  557. int len ;
  558. if (! sndfile)
  559. { strncpy (buffer, sf_strbuffer, bufferlen - 1) ;
  560. buffer [bufferlen - 1] = 0 ;
  561. return strlen (sf_strbuffer) ;
  562. } ;
  563. VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile,psf) ;
  564. len = strlen (psf->strbuffer) ;
  565. if (offset < 0 || offset >= len)
  566. return 0 ;
  567. strncpy (buffer, psf->strbuffer, bufferlen - 1) ;
  568. buffer [bufferlen - 1] = 0 ;
  569. return strlen (psf->strbuffer) ;
  570. } /* sf_get_header_info */
  571. /*------------------------------------------------------------------------------
  572. */
  573. size_t sf_get_lib_version (char *buffer, size_t bufferlen)
  574. { if (! buffer || ! bufferlen)
  575. return 0 ;
  576. strncpy (buffer, PACKAGE, bufferlen - 1) ;
  577. buffer [bufferlen - 1] = 0 ;
  578. strncat (buffer, "-", bufferlen - strlen (buffer) - 1) ;
  579. strncat (buffer, VERSION, bufferlen - strlen (buffer) - 1) ;
  580. return strlen (buffer) ;
  581. } /* sf_get_lib_version */
  582. /*------------------------------------------------------------------------------
  583. */
  584. double  sf_signal_max   (SNDFILE *sndfile)
  585. { SF_PRIVATE  *psf ;
  586. off_t position ;
  587. unsigned int k, len, readcount ;
  588. double  max = 0.0, *data, temp ;
  589. VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile,psf) ;
  590. if (! psf->sf.seekable)
  591. { psf->error = SFE_NOT_SEEKABLE ;
  592. return 0.0 ;
  593. } ;
  594. if (! psf->read_double)
  595. { psf->error = SFE_UNIMPLEMENTED ;
  596. return -1 ;
  597. } ;
  598. position = sf_seek (sndfile, 0, SEEK_CUR) ; /* Get current position in file */
  599. sf_seek (sndfile, 0, SEEK_SET) ; /* Go to start of file. */
  600. len = psf->sf.channels * 1024 ;
  601. data = malloc (len * sizeof (double)) ;
  602. readcount = len ;
  603. while (readcount == len)
  604. { readcount = psf->read_double (psf, data, len, 0) ;
  605. for (k = 0 ; k < len ; k++)
  606. { temp = data [k] ;
  607. temp = temp < 0.0 ? -temp : temp ;
  608. max  = temp > max ? temp : max ;
  609. } ;
  610. } ;
  611. free (data) ;
  612. sf_seek (sndfile, position, SEEK_SET) ; /* Return to original position. */
  613. return max ;
  614. } /* sf_signal_max */
  615. /*------------------------------------------------------------------------------
  616. */
  617. off_t sf_seek (SNDFILE *sndfile, off_t offset, int whence)
  618. { SF_PRIVATE  *psf ;
  619. off_t realseek, position ;
  620. VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile,psf) ;
  621. if (! psf->sf.seekable)
  622. { psf->error = SFE_NOT_SEEKABLE ;
  623. return ((off_t) -1) ;
  624. } ;
  625. if (psf->seek_func)
  626. return psf->seek_func (psf, offset, whence) ;
  627. if (! (psf->blockwidth && psf->datalength && psf->dataoffset))
  628. { psf->error = SFE_BAD_SEEK ;
  629. return ((off_t) -1) ;
  630. } ;
  631. switch (whence)
  632. { case SEEK_SET :
  633. if (offset < 0 || offset * psf->blockwidth > psf->datalength)
  634. { psf->error = SFE_BAD_SEEK ;
  635. return ((off_t) -1) ;
  636. } ;
  637. realseek = psf->dataoffset + offset * psf->blockwidth ;
  638. fseek (psf->file, realseek, SEEK_SET) ;
  639. position = ftell (psf->file) ;
  640. break ;
  641. case SEEK_CUR :
  642. realseek = offset * psf->blockwidth ;
  643. position = ftell (psf->file) - psf->dataoffset ;
  644. if (position + realseek > psf->datalength || position + realseek < 0)
  645. { psf->error = SFE_BAD_SEEK ;
  646. return ((off_t) -1) ;
  647. } ;
  648. fseek (psf->file, realseek, SEEK_CUR) ;
  649. position = ftell (psf->file) ;
  650. break ;
  651. case SEEK_END :
  652. if (offset > 0 || psf->sf.samples + offset < 0)
  653. { psf->error = SFE_BAD_SEEK ;
  654. return ((off_t) -1) ;
  655. } ;
  656. realseek = (psf->sf.samples + offset) * psf->blockwidth + psf->dataoffset ;
  657. fseek (psf->file, realseek, SEEK_SET) ;
  658. position = ftell (psf->file) ;
  659. break ;
  660. default : 
  661. psf->error = SFE_BAD_SEEK ;
  662. return ((off_t) -1) ;
  663. } ;
  664. psf->current = (position - psf->dataoffset) / psf->blockwidth ;
  665. return psf->current ;
  666. } /* sf_seek */
  667. /*------------------------------------------------------------------------------
  668. */
  669. size_t sf_read_raw (SNDFILE *sndfile, void *ptr, size_t bytes)
  670. { SF_PRIVATE  *psf ;
  671. size_t count ;
  672. VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile,psf) ;
  673. if (psf->mode != SF_MODE_READ)
  674. { psf->error = SFE_NOT_READMODE ;
  675. return ((size_t) -1) ;
  676. } ;
  677. if (psf->current >= psf->datalength)
  678. { memset (ptr, 0, bytes) ;
  679. return 0 ;
  680. } ;
  681. if (bytes % (psf->sf.channels * psf->bytewidth))
  682. { psf->error = SFE_BAD_READ_ALIGN ;
  683. return (size_t) -1 ;
  684. } ;
  685. count = fread (ptr, 1, bytes, psf->file) ;
  686. if (count < bytes)
  687. memset (((char*)ptr) + count, 0, bytes - count) ;
  688. psf->current += count / psf->blockwidth ;
  689. return count ;
  690. } /* sf_read_raw */
  691. /*------------------------------------------------------------------------------
  692. */
  693. size_t sf_read_short (SNDFILE *sndfile, short *ptr, size_t len)
  694. { SF_PRIVATE  *psf ;
  695. size_t count, extra ;
  696. VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile,psf) ;
  697. if (psf->mode != SF_MODE_READ)
  698. { psf->error = SFE_NOT_READMODE ;
  699. return (size_t) -1 ;
  700. } ;
  701. if (len % psf->sf.channels)
  702. { psf->error = SFE_BAD_READ_ALIGN ;
  703. return (size_t) -1 ;
  704. } ;
  705. if (psf->current >= psf->sf.samples)
  706. { memset (ptr, 0, len * sizeof (short)) ;
  707. return 0 ; /* End of file. */
  708. } ;
  709. if (! psf->read_short)
  710. { psf->error = SFE_UNIMPLEMENTED ;
  711. return (size_t) -1 ;
  712. } ;
  713. count = psf->read_short (psf, ptr, len) ;
  714. if (psf->current + count / psf->sf.channels > psf->sf.samples)
  715. { count = (psf->sf.samples - psf->current) * psf->sf.channels ;
  716. extra = len - count ;
  717. memset (ptr + count, 0, extra * sizeof (short)) ;
  718. psf->current = psf->sf.samples ;
  719. } ;
  720. psf->current += count / psf->sf.channels ;
  721. return count ;
  722. } /* sf_read_short */
  723. size_t sf_readf_short (SNDFILE *sndfile, short *ptr, size_t frames)
  724. { SF_PRIVATE  *psf ;
  725. size_t count, extra ;
  726. VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile,psf) ;
  727. if (psf->mode != SF_MODE_READ)
  728. { psf->error = SFE_NOT_READMODE ;
  729. return (size_t) -1 ;
  730. } ;
  731. if (psf->current >= psf->sf.samples)
  732. { memset (ptr, 0, frames * psf->sf.channels * sizeof (short)) ;
  733. return 0 ; /* End of file. */
  734. } ;
  735. if (! psf->read_short)
  736. { psf->error = SFE_UNIMPLEMENTED ;
  737. return (size_t) -1 ;
  738. } ;
  739. count = psf->read_short (psf, ptr, frames * psf->sf.channels) ;
  740. if (psf->current + count / psf->sf.channels > psf->sf.samples)
  741. { count = (psf->sf.samples - psf->current) * psf->sf.channels ;
  742. extra =  frames * psf->sf.channels - count ;
  743. memset (ptr + count, 0, extra * sizeof (short)) ;
  744. psf->current = psf->sf.samples ;
  745. } ;
  746. psf->current += count / psf->sf.channels ;
  747. return count / psf->sf.channels ;
  748. } /* sf_readf_short */
  749. /*------------------------------------------------------------------------------
  750. */
  751. size_t sf_read_int (SNDFILE *sndfile, int *ptr, size_t len)
  752. { SF_PRIVATE  *psf ;
  753. size_t count, extra ;
  754. VALIDATE_SNDFILE_AND_ASSIGN_PSF   (sndfile,psf) ;
  755. if (psf->mode != SF_MODE_READ)
  756. return SFE_NOT_READMODE ;
  757. if (len % psf->sf.channels)
  758. return (psf->error = SFE_BAD_READ_ALIGN) ;
  759. if (psf->current >= psf->sf.samples)
  760. { memset (ptr, 0, len * sizeof (int)) ;
  761. return 0 ;
  762. } ;
  763. if (! psf->read_int)
  764. { psf->error = SFE_UNIMPLEMENTED ;
  765. return (size_t) -1 ;
  766. } ;
  767. count = psf->read_int (psf, ptr, len) ;
  768. if (psf->current + count / psf->sf.channels > psf->sf.samples)
  769. { count = (psf->sf.samples - psf->current) * psf->sf.channels ;
  770. extra = len - count ;
  771. memset (ptr + count, 0, extra * sizeof (int)) ;
  772. psf->current = psf->sf.samples ;
  773. } ;
  774. psf->current += count / psf->sf.channels ;
  775. return count ;
  776. } /* sf_read_int */
  777. size_t sf_readf_int (SNDFILE *sndfile, int *ptr, size_t frames)
  778. { SF_PRIVATE  *psf ;
  779. size_t count, extra ;
  780. VALIDATE_SNDFILE_AND_ASSIGN_PSF   (sndfile,psf) ;
  781. if (psf->mode != SF_MODE_READ)
  782. return SFE_NOT_READMODE ;
  783. if (psf->current >= psf->sf.samples)
  784. { memset (ptr, 0, frames * psf->sf.channels * sizeof (int)) ;
  785. return 0 ;
  786. } ;
  787. if (! psf->read_int)
  788. { psf->error = SFE_UNIMPLEMENTED ;
  789. return (size_t) -1 ;
  790. } ;
  791. count = psf->read_int (psf, ptr, frames * psf->sf.channels) ;
  792. if (psf->current + count / psf->sf.channels > psf->sf.samples)
  793. { count = (psf->sf.samples - psf->current) * psf->sf.channels ;
  794. extra = frames * psf->sf.channels - count ;
  795. memset (ptr + count, 0, extra * sizeof (int)) ;
  796. psf->current = psf->sf.samples ;
  797. } ;
  798. psf->current += count / psf->sf.channels ;
  799. return count / psf->sf.channels ;
  800. } /* sf_readf_int */
  801. /*------------------------------------------------------------------------------
  802. */
  803. size_t sf_read_double (SNDFILE *sndfile, double *ptr, size_t len, int normalize)
  804. { SF_PRIVATE  *psf ;
  805. size_t count, extra ;
  806. VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf) ;
  807. if (psf->mode != SF_MODE_READ)
  808. return SFE_NOT_READMODE ;
  809. if (len % psf->sf.channels)
  810. return (psf->error = SFE_BAD_READ_ALIGN) ;
  811. if (psf->current >= psf->sf.samples)
  812. { memset (ptr, 0, len * sizeof (double)) ;
  813. return 0 ;
  814. } ;
  815. if (! psf->read_double)
  816. { psf->error = SFE_UNIMPLEMENTED ;
  817. return (size_t) -1 ;
  818. } ;
  819. count = psf->read_double (psf, ptr, len, normalize) ;
  820. if (psf->current + count / psf->sf.channels > psf->sf.samples)
  821. { count = (psf->sf.samples - psf->current) * psf->sf.channels ;
  822. extra = len - count ;
  823. memset (ptr + count, 0, extra * sizeof (double)) ;
  824. psf->current = psf->sf.samples ;
  825. } ;
  826. psf->current += count / psf->sf.channels ;
  827. return count ;
  828. } /* sf_read_double */
  829. size_t sf_readf_double (SNDFILE *sndfile, double *ptr, size_t frames, int normalize)
  830. { SF_PRIVATE  *psf ;
  831. size_t count, extra ;
  832. VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf) ;
  833. if (psf->mode != SF_MODE_READ)
  834. return SFE_NOT_READMODE ;
  835. if (psf->current >= psf->sf.samples)
  836. { memset (ptr, 0, frames * psf->sf.channels * sizeof (double)) ;
  837. return 0 ;
  838. } ;
  839. if (! psf->read_double)
  840. { psf->error = SFE_UNIMPLEMENTED ;
  841. return (size_t) -1 ;
  842. } ;
  843. count = psf->read_double (psf, ptr, frames * psf->sf.channels, normalize) ;
  844. if (psf->current + count / psf->sf.channels > psf->sf.samples)
  845. { count = (psf->sf.samples - psf->current) * psf->sf.channels ;
  846. extra = frames * psf->sf.channels - count ;
  847. memset (ptr + count, 0, extra * sizeof (double)) ;
  848. psf->current = psf->sf.samples ;
  849. } ;
  850. psf->current += count / psf->sf.channels ;
  851. return count / psf->sf.channels ;
  852. } /* sf_readf_double */
  853. /*------------------------------------------------------------------------------
  854. */
  855. size_t sf_write_raw (SNDFILE *sndfile, void *ptr, size_t len)
  856. { SF_PRIVATE  *psf ;
  857. size_t count ;
  858. VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile,psf) ;
  859. if (psf->mode != SF_MODE_WRITE)
  860. { psf->error = SFE_NOT_WRITEMODE ;
  861. return (size_t) -1 ;
  862. } ;
  863. if (len % (psf->sf.channels * psf->bytewidth))
  864. { psf->error = SFE_BAD_WRITE_ALIGN ;
  865. return (size_t) -1 ;
  866. } ;
  867. count = fwrite (ptr, 1, len, psf->file) ;
  868. psf->current += count / psf->blockwidth ;
  869. return count ;
  870. } /* sf_write_raw */
  871. /*------------------------------------------------------------------------------
  872. */
  873. size_t sf_write_short (SNDFILE *sndfile, short *ptr, size_t len)
  874. { SF_PRIVATE  *psf ;
  875. size_t count ;
  876. VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile,psf) ;
  877. if (psf->mode != SF_MODE_WRITE)
  878. { psf->error = SFE_NOT_WRITEMODE ;
  879. return (size_t) -1 ;
  880. } ;
  881. if (len % psf->sf.channels)
  882. { psf->error = SFE_BAD_WRITE_ALIGN ;
  883. return (size_t) -1 ;
  884. } ;
  885. if (! psf->write_short)
  886. { psf->error = SFE_UNIMPLEMENTED ;
  887. return (size_t) -1 ;
  888. } ;
  889. count = psf->write_short (sndfile, ptr, len) ;
  890. psf->current += count / psf->sf.channels ;
  891. return count ;
  892. } /* sf_write_short */
  893. size_t sf_writef_short (SNDFILE *sndfile, short *ptr, size_t frames)
  894. { SF_PRIVATE  *psf ;
  895. size_t count ;
  896. VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile,psf) ;
  897. if (psf->mode != SF_MODE_WRITE)
  898. { psf->error = SFE_NOT_WRITEMODE ;
  899. return (size_t) -1 ;
  900. } ;
  901. if (! psf->write_short)
  902. { psf->error = SFE_UNIMPLEMENTED ;
  903. return (size_t) -1 ;
  904. } ;
  905. count = psf->write_short (sndfile, ptr, frames * psf->sf.channels) ;
  906. psf->current += count / psf->sf.channels ;
  907. return count / psf->sf.channels ;
  908. } /* sf_writef_short */
  909. /*------------------------------------------------------------------------------
  910. */
  911. size_t sf_write_int (SNDFILE *sndfile, int *ptr, size_t len)
  912. { SF_PRIVATE  *psf ;
  913. size_t count ;
  914. VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile,psf) ;
  915. if (psf->mode != SF_MODE_WRITE)
  916. { psf->error = SFE_NOT_WRITEMODE ;
  917. return (size_t) -1 ;
  918. } ;
  919. if (len % psf->sf.channels)
  920. { psf->error = SFE_BAD_WRITE_ALIGN ;
  921. return (size_t) -1 ;
  922. } ;
  923. if (! psf->write_int)
  924. { psf->error = SFE_UNIMPLEMENTED ;
  925. return (size_t) -1 ;
  926. } ;
  927. count = psf->write_int (sndfile, ptr, len) ;
  928. psf->current += count / psf->sf.channels ;
  929. return count ;
  930. } /* sf_write_int */
  931. size_t sf_writef_int (SNDFILE *sndfile, int *ptr, size_t frames)
  932. { SF_PRIVATE  *psf ;
  933. size_t count ;
  934. VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile,psf) ;
  935. if (psf->mode != SF_MODE_WRITE)
  936. { psf->error = SFE_NOT_WRITEMODE ;
  937. return (size_t) -1 ;
  938. } ;
  939. if (! psf->write_int)
  940. { psf->error = SFE_UNIMPLEMENTED ;
  941. return (size_t) -1 ;
  942. } ;
  943. count = psf->write_int (sndfile, ptr, frames * psf->sf.channels) ;
  944. psf->current += count / psf->sf.channels ;
  945. return count / psf->sf.channels ;
  946. } /* sf_writef_int */
  947. /*------------------------------------------------------------------------------
  948. */
  949. size_t sf_write_double (SNDFILE *sndfile, double *ptr, size_t len, int normalize)
  950. { SF_PRIVATE  *psf ;
  951. size_t count ;
  952. VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile,psf) ;
  953. if (psf->mode != SF_MODE_WRITE)
  954. { psf->error = SFE_NOT_WRITEMODE ;
  955. return (size_t) -1 ;
  956. } ;
  957. if (len % psf->sf.channels)
  958. { psf->error = SFE_BAD_WRITE_ALIGN ;
  959. return (size_t) -1 ;
  960. } ;
  961. if (! psf->write_double)
  962. { psf->error = SFE_UNIMPLEMENTED ;
  963. return (size_t) -1 ;
  964. } ;
  965. count = psf->write_double (sndfile, ptr, len, normalize) ;
  966. psf->current += count / psf->sf.channels ;
  967. return count ;
  968. } /* sf_write_double */
  969. size_t sf_writef_double (SNDFILE *sndfile, double *ptr, size_t frames, int normalize)
  970. { SF_PRIVATE  *psf ;
  971. size_t count ;
  972. VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile,psf) ;
  973. if (psf->mode != SF_MODE_WRITE)
  974. { psf->error = SFE_NOT_WRITEMODE ;
  975. return (size_t) -1 ;
  976. } ;
  977. if (! psf->write_double)
  978. { psf->error = SFE_UNIMPLEMENTED ;
  979. return (size_t) -1 ;
  980. } ;
  981. count = psf->write_double (sndfile, ptr, frames * psf->sf.channels, normalize) ;
  982. psf->current += count / psf->sf.channels ;
  983. return count / psf->sf.channels ;
  984. } /* sf_writef_double */
  985. /*------------------------------------------------------------------------------
  986. */
  987. int sf_close (SNDFILE *sndfile)
  988. { SF_PRIVATE  *psf ;
  989. int error ;
  990. VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile,psf) ;
  991. if (psf->close)
  992. error = psf->close (psf) ;
  993. fclose (psf->file) ;
  994. memset (psf, 0, sizeof (SF_PRIVATE)) ;
  995. free (psf) ;
  996. return 0 ;
  997. } /* sf_close */
  998. /*=========================================================================
  999. ** Private functions.
  1000. */