📄 aiff.c
字号:
error = pcm_read_init (psf) ; break ; case SF_FORMAT_FLOAT : error = float32_read_init (psf) ; break ; default : return SFE_UNIMPLEMENTED ; } ; return error ;} /* aiff_open_read *//*------------------------------------------------------------------------------ */intaiff_open_write (SF_PRIVATE *psf){ int error ; if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_AIFF) return SFE_BAD_OPEN_FORMAT ; psf->sf.seekable = SF_TRUE ; psf->error = 0 ; psf->bytewidth = BITWIDTH2BYTES (psf->sf.pcmbitwidth) ; psf->blockwidth = psf->bytewidth * psf->sf.channels ; /* Set sample count artifically high and fix later. */ psf->sf.samples = 0x7FFFFFFF / psf->blockwidth ; psf->datalength = psf->blockwidth * psf->sf.samples ; psf->filelength = 0x7FFFFFFF ; if ((error = aiff_write_header (psf))) return error ; psf->close = (func_close) aiff_close ; psf->write_header = (func_wr_hdr) aiff_write_header ; switch (psf->sf.format & SF_FORMAT_SUBMASK) { case SF_FORMAT_PCM : case SF_FORMAT_PCM_LE : case SF_FORMAT_PCM_BE : if (psf->bytewidth == 1) psf->chars = SF_CHARS_SIGNED ; error = pcm_write_init (psf) ; break ; case SF_FORMAT_FLOAT : error = float32_write_init (psf) ; break ; default : return SFE_UNIMPLEMENTED ; } ; return error ;} /* aiff_open_write *//*==========================================================================================** Private functions.*/static int aiff_close (SF_PRIVATE *psf){ if (psf->mode == SF_MODE_WRITE) { /* Now we know for certain the length of the file we can re-write ** correct values for the FORM, COMM and SSND chunks. */ aiff_write_tailer (psf) ; fseek (psf->file, 0, SEEK_END) ; psf->filelength = ftell (psf->file) ; fseek (psf->file, 0, SEEK_SET) ; psf->datalength = psf->filelength - psf->dataoffset ; psf->sf.samples = psf->datalength / (psf->bytewidth * psf->sf.channels) ; aiff_write_header (psf) ; } ; if (psf->fdata) free (psf->fdata) ; psf->fdata = NULL ; return 0 ;} /* aiff_close */static intaiff_read_comm_chunk (SF_PRIVATE *psf, COMM_CHUNK *comm_fmt){ int error = 0, bytesread ; bytesread = psf_binheader_readf (psf, "L", &(comm_fmt->size)) ; /* The COMM chunk has an int aligned to an odd word boundary. Some ** procesors are not able to deal with this (ie bus fault) so we have ** to take special care. */ bytesread += psf_binheader_readf (psf, "WLWB", &(comm_fmt->numChannels), &(comm_fmt->numSampleFrames), &(comm_fmt->sampleSize), &(comm_fmt->sampleRate), sizeof (comm_fmt->sampleRate)) ; if (comm_fmt->size == AIFF_COMM_SIZE) comm_fmt->encoding = NONE_MARKER ; else if (comm_fmt->size >= AIFC_COMM_SIZE) { bytesread += psf_binheader_readf (psf, "mB", &(comm_fmt->encoding), &(comm_fmt->zero_bytes), 2) ; psf_binheader_readf (psf, "B", psf->header, comm_fmt->size - AIFC_COMM_SIZE) ; } ; psf_log_printf (psf, " COMM : %d\n", comm_fmt->size) ; psf_log_printf (psf, " Sample Rate : %d\n", tenbytefloat2int (comm_fmt->sampleRate)) ; psf_log_printf (psf, " Samples : %d\n", comm_fmt->numSampleFrames) ; psf_log_printf (psf, " Channels : %d\n", comm_fmt->numChannels) ; /* Found some broken 'fl32' files with comm.samplesize == 16. Fix it here. */ if ((comm_fmt->encoding == fl32_MARKER || comm_fmt->encoding == FL32_MARKER) && comm_fmt->sampleSize != 32) { psf_log_printf (psf, " Sample Size : %d (should be 32)\n", comm_fmt->sampleSize) ; comm_fmt->sampleSize = 32 ; } else psf_log_printf (psf, " Sample Size : %d\n", comm_fmt->sampleSize) ; switch (comm_fmt->encoding) { case NONE_MARKER : psf->endian = SF_ENDIAN_BIG ; psf->sf.format = (SF_FORMAT_AIFF | SF_FORMAT_PCM) ; break ; case twos_MARKER : psf->endian = SF_ENDIAN_BIG ; psf->sf.format = (SF_FORMAT_AIFF | SF_FORMAT_PCM_BE) ; break ; case sowt_MARKER : psf->endian = SF_ENDIAN_LITTLE ; psf->sf.format = (SF_FORMAT_AIFF | SF_FORMAT_PCM_LE) ; break ; case fl32_MARKER : case FL32_MARKER : psf->endian = SF_ENDIAN_BIG ; psf->sf.format = (SF_FORMAT_AIFF | SF_FORMAT_FLOAT) ; break ; default : psf_log_printf (psf, "AIFC : Unimplemented format : %D\n", comm_fmt->encoding) ; error = SFE_UNIMPLEMENTED ; } ; psf_log_printf (psf, " Encoding : %D\n", comm_fmt->encoding) ; return error ;} /* aiff_read_comm_chunk */static intaiff_write_header (SF_PRIVATE *psf){ unsigned char comm_sample_rate [10], comm_zero_bytes [2] = { 0, 0 } ; unsigned int comm_type, comm_size, comm_encoding ; int k ; switch (psf->sf.format & SF_FORMAT_SUBMASK) { case SF_FORMAT_PCM : /* Standard big endian AIFF. */ psf->endian = SF_ENDIAN_BIG ; comm_type = AIFF_MARKER ; comm_size = AIFF_COMM_SIZE ; comm_encoding = 0 ; break ; case SF_FORMAT_PCM_BE : /* Big endian AIFC. */ psf->endian = SF_ENDIAN_BIG ; comm_type = AIFC_MARKER ; comm_size = AIFC_COMM_SIZE ; comm_encoding = twos_MARKER ; break ; case SF_FORMAT_PCM_LE : /* Little endian AIFC. */ psf->endian = SF_ENDIAN_LITTLE ; comm_type = AIFC_MARKER ; comm_size = AIFC_COMM_SIZE ; comm_encoding = sowt_MARKER ; break ; case SF_FORMAT_FLOAT : /* Big endian floating point. */ psf->endian = SF_ENDIAN_BIG ; comm_type = AIFC_MARKER ; comm_size = AIFC_COMM_SIZE ; comm_encoding = FL32_MARKER ; /* Use 'FL32' because its easier to read. */ psf->has_peak = SF_TRUE ; psf->peak_loc = SF_PEAK_START ; break ; default : return SFE_BAD_OPEN_FORMAT ; } ; /* Reset the current header length to zero. */ psf->header [0] = 0 ; psf->headindex = 0 ; fseek (psf->file, 0, SEEK_SET) ; psf_binheader_writef (psf, "mL", FORM_MARKER, psf->filelength - 8) ; /* Write COMM chunk. */ psf_binheader_writef (psf, "mmL", comm_type, COMM_MARKER, comm_size) ; uint2tenbytefloat (psf->sf.samplerate, comm_sample_rate) ; psf_binheader_writef (psf, "WLW", psf->sf.channels, psf->sf.samples, psf->sf.pcmbitwidth) ; psf_binheader_writef (psf, "B", comm_sample_rate, sizeof (comm_sample_rate)) ; /* AIFC chunks have some extra data. */ if (comm_type == AIFC_MARKER) psf_binheader_writef (psf, "mB", comm_encoding, comm_zero_bytes, sizeof (comm_zero_bytes)) ; if (psf->has_peak && psf->peak_loc == SF_PEAK_START) { psf_binheader_writef (psf, "mL", PEAK_MARKER, sizeof (psf->peak) - sizeof (psf->peak.peak) + psf->sf.channels * sizeof (PEAK_POS)) ; psf_binheader_writef (psf, "LL", 1, time (NULL)) ; for (k = 0 ; k < psf->sf.channels ; k++) psf_binheader_writef (psf, "FL", psf->peak.peak[k].value, psf->peak.peak[k].position) ; /* XXXXX */ } ; /* Write SSND chunk. */ psf_binheader_writef (psf, "mLLL", SSND_MARKER, psf->datalength + SSND_CHUNK_SIZE, 0, 0) ; /* Header cunstruction complete so write it out. */ fwrite (psf->header, psf->headindex, 1, psf->file) ; psf->dataoffset = psf->headindex ; return 0 ;} /* aiff_write_header */static intaiff_write_tailer (SF_PRIVATE *psf){ int k ; /* Reset the current header length to zero. */ psf->header [0] = 0 ; psf->headindex = 0 ; fseek (psf->file, 0, SEEK_SET) ; if (psf->has_peak && psf->peak_loc == SF_PEAK_END) { psf_binheader_writef (psf, "mL", PEAK_MARKER, sizeof (psf->peak) - sizeof (psf->peak.peak) + psf->sf.channels * sizeof (PEAK_POS)) ; psf_binheader_writef (psf, "LL", 1, time (NULL)) ; for (k = 0 ; k < psf->sf.channels ; k++) psf_binheader_writef (psf, "FL", psf->peak.peak[k].value, psf->peak.peak[k].position) ; /* XXXXX */ } ; if (psf->headindex) fwrite (psf->header, psf->headindex, 1, psf->file) ; return 0 ;} /* aiff_write_tailer *//*-static voidendswap_comm_fmt (COMM_CHUNK *comm){ comm->size = ENDSWAP_INT (comm->size) ; comm->numChannels = ENDSWAP_SHORT (comm->numChannels) ; comm->numSampleFrames = ENDSWAP_INT (comm->numSampleFrames) ; comm->sampleSize = ENDSWAP_SHORT (comm->sampleSize) ;} /+* endswap_comm_fmt *+/static voidendswap_ssnd_fmt (SSND_CHUNK *ssnd){ ssnd->offset = ENDSWAP_INT (ssnd->offset) ; ssnd->blocksize = ENDSWAP_INT (ssnd->blocksize) ;} /+* endswap_ssnd_fmt *+/-*//*==========================================================================================** Rough hack at converting from 80 bit IEEE float in AIFF header to an int and** back again. It assumes that all sample rates are between 1 and 800MHz, which ** should be OK as other sound file formats use a 32 bit integer to store sample ** rate.** There is another (probably better) version in the source code to the SoX but it** has a copyright which probably prevents it from being allowable as GPL/LGPL.*/static inttenbytefloat2int (unsigned char *bytes){ int val = 3 ; if (bytes [0] & 0x80) /* Negative number. */ return 0 ; if (bytes [0] <= 0x3F) /* Less than 1. */ return 1 ; if (bytes [0] > 0x40) /* Way too big. */ return 0x4000000 ; if (bytes [0] == 0x40 && bytes [1] > 0x1C) /* Too big. */ return 800000000 ; /* Ok, can handle it. */ val = (bytes [2] << 23) | (bytes [3] << 15) | (bytes [4] << 7) | (bytes [5] >> 1) ; val >>= (29 - bytes [1]) ; return val ;} /* tenbytefloat2int */static voiduint2tenbytefloat (unsigned int num, unsigned char *bytes){ int count, mask = 0x40000000 ; memset (bytes, 0, 10) ; if (num <= 1) { bytes [0] = 0x3F ; bytes [1] = 0xFF ; bytes [2] = 0x80 ; return ; } ; bytes [0] = 0x40 ; if (num >= mask) { bytes [1] = 0x1D ; return ; } ; for (count = 0 ; count <= 32 ; count ++) { if (num & mask) break ; mask >>= 1 ; } ; num <<= count + 1 ; bytes [1] = 29 - count ; bytes [2] = (num >> 24) & 0xFF ; bytes [3] = (num >> 16) & 0xFF ; bytes [4] = (num >> 8) & 0xFF ; bytes [5] = num & 0xFF ; } /* uint2tenbytefloat */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -