📄 sndfile.c
字号:
/*** Copyright (C) 1999-2004 Erik de Castro Lopo <erikd@mega-nerd.com>**** This program is free software; you can redistribute it and/or modify** it under the terms of the GNU Lesser General Public License as published by** the Free Software Foundation; either version 2.1 of the License, or** (at your option) any later version.**** This program is distributed in the hope that it will be useful,** but WITHOUT ANY WARRANTY; without even the implied warranty of** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the** GNU Lesser General Public License for more details.**** You should have received a copy of the GNU Lesser General Public License** along with this program; if not, write to the Free Software** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*/#include "config.h"#include <stdlib.h>#include <string.h>#include <ctype.h>#include "sndfile.h"#include "sfendian.h"#include "common.h"#define SNDFILE_MAGICK 0x1234C0DEtypedef struct{ int error ; const char *str ;} ErrorStruct ;staticErrorStruct SndfileErrors [] ={ /* Public error values and their associated strings. */ { SF_ERR_NO_ERROR , "No Error." }, { SF_ERR_UNRECOGNISED_FORMAT , "File opened for read. Format not recognised." }, { SF_ERR_SYSTEM , "System error." /* Often replaced. */ }, /* Private error values and their associated strings. */ { SFE_BAD_FILE , "File does not exist or is not a regular file (possibly a pipe?)." }, { SFE_BAD_FILE_READ , "File exists but no data could be read." }, { SFE_OPEN_FAILED , "Could not open file." }, { SFE_BAD_SNDFILE_PTR , "Not a valid SNDFILE* pointer." }, { SFE_BAD_SF_INFO_PTR , "NULL SF_INFO pointer passed to libsndfile." }, { SFE_BAD_SF_INCOMPLETE , "SF_PRIVATE struct incomplete and end of header parsing." }, { SFE_BAD_FILE_PTR , "Bad FILE pointer." }, { SFE_BAD_INT_PTR , "Internal error, Bad pointer." }, { SFE_BAD_STAT_SIZE , "Error : software was misconfigured at compile time (sizeof statbuf.st_size)." }, { SFE_MALLOC_FAILED , "Internal malloc () failed." }, { SFE_UNIMPLEMENTED , "File contains data in an unimplemented format." }, { SFE_BAD_READ_ALIGN , "Attempt to read a non-integer number of channels." }, { SFE_BAD_WRITE_ALIGN , "Attempt to write a non-integer number of channels." }, { SFE_UNKNOWN_FORMAT , "File contains data in an unknown format." }, { SFE_NOT_READMODE , "Read attempted on file currently open for write." }, { SFE_NOT_WRITEMODE , "Write attempted on file currently open for read." }, { SFE_BAD_MODE_RW , "This file format does not support read/write mode." }, { SFE_BAD_SF_INFO , "Internal error : SF_INFO struct incomplete." }, { SFE_BAD_OFFSET , "Error : supplied offset beyond end of file." }, { SFE_NO_EMBED_SUPPORT , "Error : embedding not supported for this file format." }, { SFE_NO_EMBEDDED_RDWR , "Error : cannot open embedded file read/write." }, { SFE_NO_PIPE_WRITE , "Error : this file format does not support pipe write." }, { SFE_BAD_RDWR_FORMAT , "Attempted to open read only format for RDWR." }, { SFE_INTERLEAVE_MODE , "Attempt to write to file with non-interleaved data." }, { SFE_INTERLEAVE_SEEK , "Bad karma in seek during interleave read operation." }, { SFE_INTERLEAVE_READ , "Bad karma in read during interleave read operation." }, { SFE_INTERNAL , "Unspecified internal error." }, { SFE_LOG_OVERRUN , "Log buffer has overrun. File probably broken." }, { SFE_BAD_CONTROL_CMD , "Bad command passed to function sf_command()." }, { SFE_BAD_ENDIAN , "Bad endian-ness. Try default endian-ness" }, { SFE_CHANNEL_COUNT , "Too many channels specified." }, { SFE_BAD_SEEK , "Internal psf_fseek() failed." }, { SFE_NOT_SEEKABLE , "Seek attempted on unseekable file type." }, { SFE_AMBIGUOUS_SEEK , "Error: combination of file open mode and seek command is ambiguous." }, { SFE_WRONG_SEEK , "Error: invalid seek parameters." }, { SFE_SEEK_FAILED , "Error: parameters OK, but psf_seek() failed." }, { SFE_BAD_OPEN_MODE , "Error: bad mode parameter for file open." }, { SFE_OPEN_PIPE_RDWR , "Error: attempt toopen a pipe in read/write mode." }, { SFE_RDWR_POSITION , "Error on RDWR position (cryptic)." }, { SFE_RDWR_BAD_HEADER , "Error : Cannot open file in read/write mode due to string data in header." }, { SFE_STR_NO_SUPPORT , "Error : File type does not support string data." }, { SFE_STR_NOT_WRITE , "Error : Trying to set a string when file is not in write mode." }, { SFE_STR_MAX_DATA , "Error : Maximum string data storage reached." }, { SFE_STR_MAX_COUNT , "Error : Maximum string data count reached." }, { SFE_STR_BAD_TYPE , "Error : Bad string data type." }, { SFE_STR_NO_ADD_END , "Error : file type does not support strings added at end of file." }, { SFE_STR_BAD_STRING , "Error : bad string." }, { SFE_STR_WEIRD , "Error : Weird string error." }, { SFE_WAV_NO_RIFF , "Error in WAV file. No 'RIFF' chunk marker." }, { SFE_WAV_NO_WAVE , "Error in WAV file. No 'WAVE' chunk marker." }, { SFE_WAV_NO_FMT , "Error in WAV file. No 'fmt ' chunk marker." }, { SFE_WAV_FMT_SHORT , "Error in WAV file. Short 'fmt ' chunk." }, { SFE_WAV_FMT_TOO_BIG , "Error in WAV file. 'fmt ' chunk too large." }, { SFE_WAV_BAD_FACT , "Error in WAV file. 'fact' chunk out of place." }, { SFE_WAV_BAD_PEAK , "Error in WAV file. Bad 'PEAK' chunk." }, { SFE_WAV_PEAK_B4_FMT , "Error in WAV file. 'PEAK' chunk found before 'fmt ' chunk." }, { SFE_WAV_BAD_FORMAT , "Error in WAV file. Errors in 'fmt ' chunk." }, { SFE_WAV_BAD_BLOCKALIGN , "Error in WAV file. Block alignment in 'fmt ' chunk is incorrect." }, { SFE_WAV_NO_DATA , "Error in WAV file. No 'data' chunk marker." }, { SFE_WAV_UNKNOWN_CHUNK , "Error in WAV file. File contains an unknown chunk marker." }, { SFE_WAV_WVPK_DATA , "Error in WAV file. Data is in WAVPACK format." }, { SFE_WAV_ADPCM_NOT4BIT , "Error in ADPCM WAV file. Invalid bit width." }, { SFE_WAV_ADPCM_CHANNELS , "Error in ADPCM WAV file. Invalid number of channels." }, { SFE_WAV_GSM610_FORMAT , "Error in GSM610 WAV file. Invalid format chunk." }, { SFE_AIFF_NO_FORM , "Error in AIFF file, bad 'FORM' marker." }, { SFE_AIFF_AIFF_NO_FORM , "Error in AIFF file, 'AIFF' marker without 'FORM'." }, { SFE_AIFF_COMM_NO_FORM , "Error in AIFF file, 'COMM' marker without 'FORM'." }, { SFE_AIFF_SSND_NO_COMM , "Error in AIFF file, 'SSND' marker without 'COMM'." }, { SFE_AIFF_UNKNOWN_CHUNK , "Error in AIFF file, unknown chunk." }, { SFE_AIFF_COMM_CHUNK_SIZE, "Error in AIFF file, bad 'COMM' chunk size." }, { SFE_AIFF_BAD_COMM_CHUNK , "Error in AIFF file, bad 'COMM' chunk." }, { SFE_AIFF_PEAK_B4_COMM , "Error in AIFF file. 'PEAK' chunk found before 'COMM' chunk." }, { SFE_AIFF_BAD_PEAK , "Error in AIFF file. Bad 'PEAK' chunk." }, { SFE_AIFF_NO_SSND , "Error in AIFF file, bad 'SSND' chunk." }, { SFE_AIFF_NO_DATA , "Error in AIFF file, no sound data." }, { SFE_AIFF_RW_SSND_NOT_LAST, "Error in AIFF file, RDWR only possible if SSND chunk at end of file." }, { SFE_AU_UNKNOWN_FORMAT , "Error in AU file, unknown format." }, { SFE_AU_NO_DOTSND , "Error in AU file, missing '.snd' or 'dns.' marker." }, { SFE_AU_EMBED_BAD_LEN , "Embedded AU file with unknown length." }, { SFE_RAW_READ_BAD_SPEC , "Error while opening RAW file for read. Must specify format and channels.\n" "Possibly trying to open unsupported format." }, { SFE_RAW_BAD_BITWIDTH , "Error. RAW file bitwidth must be a multiple of 8." }, { SFE_RAW_BAD_FORMAT , "Error. Bad format field in SF_INFO struct when openning a RAW file for read." }, { SFE_PAF_NO_MARKER , "Error in PAF file, no marker." }, { SFE_PAF_VERSION , "Error in PAF file, bad version." }, { SFE_PAF_UNKNOWN_FORMAT , "Error in PAF file, unknown format." }, { SFE_PAF_SHORT_HEADER , "Error in PAF file. File shorter than minimal header." }, { SFE_SVX_NO_FORM , "Error in 8SVX / 16SV file, no 'FORM' marker." }, { SFE_SVX_NO_BODY , "Error in 8SVX / 16SV file, no 'BODY' marker." }, { SFE_SVX_NO_DATA , "Error in 8SVX / 16SV file, no sound data." }, { SFE_SVX_BAD_COMP , "Error in 8SVX / 16SV file, unsupported compression format." }, { SFE_SVX_BAD_NAME_LENGTH , "Error in 8SVX / 16SV file, NAME chunk too long." }, { SFE_NIST_BAD_HEADER , "Error in NIST file, bad header." }, { SFE_NIST_CRLF_CONVERISON, "Error : NIST file damaged by Windows CR -> CRLF conversion process." }, { SFE_NIST_BAD_ENCODING , "Error in NIST file, unsupported compression format." }, { SFE_VOC_NO_CREATIVE , "Error in VOC file, no 'Creative Voice File' marker." }, { SFE_VOC_BAD_FORMAT , "Error in VOC file, bad format." }, { SFE_VOC_BAD_VERSION , "Error in VOC file, bad version number." }, { SFE_VOC_BAD_MARKER , "Error in VOC file, bad marker in file." }, { SFE_VOC_BAD_SECTIONS , "Error in VOC file, incompatible VOC sections." }, { SFE_VOC_MULTI_SAMPLERATE, "Error in VOC file, more than one sample rate defined." }, { SFE_VOC_MULTI_SECTION , "Unimplemented VOC file feature, file contains multiple sound sections." }, { SFE_VOC_MULTI_PARAM , "Error in VOC file, file contains multiple bit or channel widths." }, { SFE_VOC_SECTION_COUNT , "Error in VOC file, too many sections." }, { SFE_VOC_NO_PIPE , "Error : not able to operate on VOC files over a pipe." }, { SFE_IRCAM_NO_MARKER , "Error in IRCAM file, bad IRCAM marker." }, { SFE_IRCAM_BAD_CHANNELS , "Error in IRCAM file, bad channel count." }, { SFE_IRCAM_UNKNOWN_FORMAT, "Error in IRCAM file, unknow encoding format." }, { SFE_W64_64_BIT , "Error in W64 file, file contains 64 bit offset." }, { SFE_W64_NO_RIFF , "Error in W64 file. No 'riff' chunk marker." }, { SFE_W64_NO_WAVE , "Error in W64 file. No 'wave' chunk marker." }, { SFE_W64_NO_FMT , "Error in W64 file. No 'fmt ' chunk marker." }, { SFE_W64_NO_DATA , "Error in W64 file. No 'data' chunk marker." }, { SFE_W64_FMT_SHORT , "Error in W64 file. Short 'fmt ' chunk." }, { SFE_W64_FMT_TOO_BIG , "Error in W64 file. 'fmt ' chunk too large." }, { SFE_W64_ADPCM_NOT4BIT , "Error in ADPCM W64 file. Invalid bit width." }, { SFE_W64_ADPCM_CHANNELS , "Error in ADPCM W64 file. Invalid number of channels." }, { SFE_W64_GSM610_FORMAT , "Error in GSM610 W64 file. Invalid format chunk." }, { SFE_MAT4_BAD_NAME , "Error in MAT4 file. No variable name." }, { SFE_MAT4_NO_SAMPLERATE , "Error in MAT4 file. No sample rate." }, { SFE_MAT4_ZERO_CHANNELS , "Error in MAT4 file. Channel count is zero." }, { SFE_MAT5_BAD_ENDIAN , "Error in MAT5 file. Not able to determine endian-ness." }, { SFE_MAT5_NO_BLOCK , "Error in MAT5 file. Bad block structure." }, { SFE_MAT5_SAMPLE_RATE , "Error in MAT5 file. Not able to determine sample rate." }, { SFE_MAT5_ZERO_CHANNELS , "Error in MAT5 file. Channel count is zero." }, { SFE_PVF_NO_PVF1 , "Error in PVF file. No PVF1 marker." }, { SFE_PVF_BAD_HEADER , "Error in PVF file. Bad header." }, { SFE_PVF_BAD_BITWIDTH , "Error in PVF file. Bad bit width." }, { SFE_XI_BAD_HEADER , "Error in XI file. Bad header." }, { SFE_XI_EXCESS_SAMPLES , "Error in XI file. Excess samples in file." }, { SFE_XI_NO_PIPE , "Error : not able to operate on XI files over a pipe." }, { SFE_HTK_NO_PIPE , "Error : not able to operate on HTK files over a pipe." }, { SFE_SDS_NOT_SDS , "Error : not an SDS file." }, { SFE_SDS_BAD_BIT_WIDTH , "Error : bad bit width for SDS file." }, { SFE_SD2_FD_DISALLOWED , "Error : cannot open SD2 file without a file name." }, { SFE_SD2_BAD_DATA_OFFSET , "Error : bad data offset." }, { SFE_SD2_BAD_MAP_OFFSET , "Error : bad map offset." }, { SFE_SD2_BAD_DATA_LENGTH , "Error : bad data length." }, { SFE_SD2_BAD_MAP_LENGTH , "Error : bad map length." }, { SFE_SD2_BAD_RSRC , "Error : bad resource fork." }, { SFE_SD2_BAD_SAMPLE_SIZE , "Error : bad sample size." }, { SFE_DWVW_BAD_BITWIDTH , "Error : Bad bit width for DWVW encoding. Must be 12, 16 or 24." }, { SFE_G72X_NOT_MONO , "Error : G72x encoding does not support more than 1 channel." }, { SFE_MAX_ERROR , "Maximum error number." }, { SFE_MAX_ERROR + 1 , NULL }} ;/*------------------------------------------------------------------------------*/static int format_from_extension (const char *filename) ;static int guess_file_type (SF_PRIVATE *psf, const char *filename) ;static int validate_sfinfo (SF_INFO *sfinfo) ;static int validate_psf (SF_PRIVATE *psf) ;static void save_header_info (SF_PRIVATE *psf) ;static void copy_filename (SF_PRIVATE *psf, const char *path) ;static int psf_close (SF_PRIVATE *psf) ;static int psf_open_file (SF_PRIVATE *psf, int mode, SF_INFO *sfinfo) ;static int try_resource_fork (SF_PRIVATE * psf, int mode) ;/*------------------------------------------------------------------------------** Private (static) variables.*/static int sf_errno = 0 ;static char sf_logbuffer [SF_BUFFER_LEN] = { 0 } ;static char sf_syserr [SF_SYSERR_LEN] = { 0 } ;/*------------------------------------------------------------------------------*/#define VALIDATE_SNDFILE_AND_ASSIGN_PSF(a,b,c) \ { if (! (a)) \ { sf_errno = SFE_BAD_SNDFILE_PTR ; \ return 0 ; \ } ; \ (b) = (SF_PRIVATE*) (a) ; \ if (psf_filedes_valid (b) == 0) \ { (b)->error = SFE_BAD_FILE_PTR ; \ return 0 ; \ } ; \ if ((b)->Magick != SNDFILE_MAGICK) \ { (b)->error = SFE_BAD_SNDFILE_PTR ; \ return 0 ; \ } ; \ if (c) (b)->error = 0 ; \ }/*------------------------------------------------------------------------------** Public functions.*/SNDFILE*sf_open (const char *path, int mode, SF_INFO *sfinfo){ SF_PRIVATE *psf ; int error = 0 ; if ((psf = calloc (1, sizeof (SF_PRIVATE))) == NULL) { sf_errno = SFE_MALLOC_FAILED ; return NULL ; } ; memset (psf, 0, sizeof (SF_PRIVATE)) ; psf->rsrcdes = -1 ; psf_log_printf (psf, "File : %s\n", path) ; copy_filename (psf, path) ; if (strcmp (path, "-") == 0) error = psf_set_stdio (psf, mode) ; else error = psf_fopen (psf, path, mode) ; if (error == 0) error = psf_open_file (psf, mode, sfinfo) ; if (error) { sf_errno = error ; if (error == SFE_SYSTEM) LSF_SNPRINTF (sf_syserr, sizeof (sf_syserr), "%s", psf->syserr) ; LSF_SNPRINTF (sf_logbuffer, sizeof (sf_logbuffer), "%s", psf->logbuffer) ; psf_close (psf) ; return NULL ; } ; memcpy (sfinfo, &(psf->sf), sizeof (SF_INFO)) ; return (SNDFILE*) psf ;} /* sf_open */SNDFILE*sf_open_fd (int fd, int mode, SF_INFO *sfinfo, int close_desc){ SF_PRIVATE *psf ; int error ; if ((sfinfo->format & SF_FORMAT_TYPEMASK) == SF_FORMAT_SD2) { sf_errno = SFE_SD2_FD_DISALLOWED ; return NULL ; } ; if ((psf = calloc (1, sizeof (SF_PRIVATE))) == NULL) { sf_errno = SFE_MALLOC_FAILED ; return NULL ; } ; psf_set_file (psf, fd) ; psf->rsrcdes = -1 ; psf->is_pipe = psf_is_pipe (psf) ; psf->fileoffset = psf_ftell (psf) ; if (! close_desc) psf->do_not_close_descriptor = SF_TRUE ; error = psf_open_file (psf, mode, sfinfo) ; if (error) { sf_errno = error ; if (error == SFE_SYSTEM) LSF_SNPRINTF (sf_syserr, sizeof (sf_syserr), "%s", psf->syserr) ; LSF_SNPRINTF (sf_logbuffer, sizeof (sf_logbuffer), "%s", psf->logbuffer) ; psf_close (psf) ; return NULL ; } ; memcpy (sfinfo, &(psf->sf), sizeof (SF_INFO)) ; return (SNDFILE*) psf ;} /* sf_open_fd *//*------------------------------------------------------------------------------*/intsf_close (SNDFILE *sndfile){ SF_PRIVATE *psf ; VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; return psf_close (psf) ;} /* sf_close *//*==============================================================================*/const char*sf_error_number (int errnum){ static const char *bad_errnum = "No error defined for this error number. This is a bug in libsndfile." ; int k ; if (errnum == SFE_MAX_ERROR) return SndfileErrors [0].str ; if (errnum < 0 || errnum > SFE_MAX_ERROR) { /* This really shouldn't happen in release versions. */ printf ("Not a valid error number (%d).\n", errnum) ; return bad_errnum ; } ; for (k = 0 ; SndfileErrors [k].str ; k++) if (errnum == SndfileErrors [k].error) return SndfileErrors [k].str ; return bad_errnum ;} /* sf_error_number */const char*sf_strerror (SNDFILE *sndfile){ SF_PRIVATE *psf = NULL ; int errnum ; if (! sndfile) { errnum = sf_errno ; if (errnum == SFE_SYSTEM && sf_syserr [0]) return sf_syserr ; } else { psf = (SF_PRIVATE *) sndfile ; if (psf->Magick != SNDFILE_MAGICK) return "sf_strerror : Bad magic number." ; errnum = psf->error ; if (errnum == SFE_SYSTEM && psf->syserr [0]) return psf->syserr ; } ; return sf_error_number (errnum) ;} /* sf_strerror *//*------------------------------------------------------------------------------*/intsf_error (SNDFILE *sndfile){ SF_PRIVATE *psf ; if (! sndfile) { if (sf_error != 0) return 1 ; return 0 ; } ; VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 0) ; if (psf->error) return 1 ; return 0 ;} /* sf_error *//*------------------------------------------------------------------------------*/intsf_perror (SNDFILE *sndfile){ SF_PRIVATE *psf ; int errnum ; if (! sndfile) { errnum = sf_errno ; } else { VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 0) ; errnum = psf->error ; } ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -