📄 aiff.c
字号:
** needs to be corrected for new data length. That means that we ** only change the length fields of the FORM and SSND chunks; ** everything else can be skipped over. */ /* First write new FORM chunk. */ psf->headindex = 0 ; psf_fseek (psf, 0, SEEK_SET) ; psf_binheader_writef (psf, "Etm8", FORM_MARKER, psf->filelength - 8) ; psf_fwrite (psf->header, psf->headindex, 1, psf) ; /* Now write frame count field of COMM chunk header. */ psf->headindex = 0 ; psf_fseek (psf, 22, SEEK_SET) ; psf_binheader_writef (psf, "Et8", psf->sf.frames) ; psf_fwrite (psf->header, psf->headindex, 1, psf) ; /* Now write new SSND chunk header. */ psf->headindex = 0 ; psf_fseek (psf, psf->dataoffset - 16, SEEK_SET) ; psf_binheader_writef (psf, "Etm8", SSND_MARKER, psf->datalength + SIZEOF_SSND_CHUNK) ; psf_fwrite (psf->header, psf->headindex, 1, psf) ; if (current < psf->dataoffset) psf_fseek (psf, psf->dataoffset, SEEK_SET) ; else if (current > 0) psf_fseek (psf, current, SEEK_SET) ; return 0 ; } ; endian = psf->sf.format & SF_FORMAT_ENDMASK ; if (CPU_IS_LITTLE_ENDIAN && endian == SF_ENDIAN_CPU) endian = SF_ENDIAN_LITTLE ; /* Standard value here. */ bit_width = psf->bytewidth * 8 ; comm_frames = (psf->sf.frames > 0xFFFFFFFF) ? 0xFFFFFFFF : psf->sf.frames ; switch (psf->sf.format & SF_FORMAT_SUBMASK) { case SF_FORMAT_PCM_S8 : case SF_FORMAT_PCM_16 : case SF_FORMAT_PCM_24 : case SF_FORMAT_PCM_32 : switch (endian) { case SF_ENDIAN_BIG : psf->endian = SF_ENDIAN_BIG ; comm_type = AIFC_MARKER ; comm_size = SIZEOF_AIFC_COMM ; comm_encoding = twos_MARKER ; break ; case SF_ENDIAN_LITTLE : psf->endian = SF_ENDIAN_LITTLE ; comm_type = AIFC_MARKER ; comm_size = SIZEOF_AIFC_COMM ; comm_encoding = sowt_MARKER ; break ; default : /* SF_ENDIAN_FILE */ psf->endian = SF_ENDIAN_BIG ; comm_type = AIFF_MARKER ; comm_size = SIZEOF_AIFF_COMM ; comm_encoding = 0 ; break ; } ; break ; case SF_FORMAT_FLOAT : /* Big endian floating point. */ psf->endian = SF_ENDIAN_BIG ; comm_type = AIFC_MARKER ; comm_size = SIZEOF_AIFC_COMM ; comm_encoding = FL32_MARKER ; /* Use 'FL32' because its easier to read. */ break ; case SF_FORMAT_DOUBLE : /* Big endian double precision floating point. */ psf->endian = SF_ENDIAN_BIG ; comm_type = AIFC_MARKER ; comm_size = SIZEOF_AIFC_COMM ; comm_encoding = FL64_MARKER ; /* Use 'FL64' because its easier to read. */ break ; case SF_FORMAT_ULAW : psf->endian = SF_ENDIAN_BIG ; comm_type = AIFC_MARKER ; comm_size = SIZEOF_AIFC_COMM ; comm_encoding = ulaw_MARKER ; break ; case SF_FORMAT_ALAW : psf->endian = SF_ENDIAN_BIG ; comm_type = AIFC_MARKER ; comm_size = SIZEOF_AIFC_COMM ; comm_encoding = alaw_MARKER ; break ; case SF_FORMAT_PCM_U8 : psf->endian = SF_ENDIAN_BIG ; comm_type = AIFC_MARKER ; comm_size = SIZEOF_AIFC_COMM ; comm_encoding = raw_MARKER ; break ; case SF_FORMAT_DWVW_12 : psf->endian = SF_ENDIAN_BIG ; comm_type = AIFC_MARKER ; comm_size = SIZEOF_AIFC_COMM ; comm_encoding = DWVW_MARKER ; /* Override standard value here.*/ bit_width = 12 ; break ; case SF_FORMAT_DWVW_16 : psf->endian = SF_ENDIAN_BIG ; comm_type = AIFC_MARKER ; comm_size = SIZEOF_AIFC_COMM ; comm_encoding = DWVW_MARKER ; /* Override standard value here.*/ bit_width = 16 ; break ; case SF_FORMAT_DWVW_24 : psf->endian = SF_ENDIAN_BIG ; comm_type = AIFC_MARKER ; comm_size = SIZEOF_AIFC_COMM ; comm_encoding = DWVW_MARKER ; /* Override standard value here.*/ bit_width = 24 ; break ; case SF_FORMAT_GSM610 : psf->endian = SF_ENDIAN_BIG ; comm_type = AIFC_MARKER ; comm_size = SIZEOF_AIFC_COMM ; comm_encoding = GSM_MARKER ; /* Override standard value here.*/ bit_width = 16 ; break ; case SF_FORMAT_IMA_ADPCM : psf->endian = SF_ENDIAN_BIG ; comm_type = AIFC_MARKER ; comm_size = SIZEOF_AIFC_COMM ; comm_encoding = ima4_MARKER ; /* Override standard value here.*/ bit_width = 16 ; comm_frames = psf->sf.frames / AIFC_IMA4_SAMPLES_PER_BLOCK ; break ; default : return SFE_BAD_OPEN_FORMAT ; } ; /* Reset the current header length to zero. */ psf->header [0] = 0 ; psf->headindex = 0 ; psf_fseek (psf, 0, SEEK_SET) ; psf_binheader_writef (psf, "Etm8", FORM_MARKER, psf->filelength - 8) ; /* Write COMM chunk. */ psf_binheader_writef (psf, "Emm4", comm_type, COMM_MARKER, comm_size) ; uint2tenbytefloat (psf->sf.samplerate, comm_sample_rate) ; psf_binheader_writef (psf, "Et242", psf->sf.channels, comm_frames, bit_width) ; 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->str_flags & SF_STR_LOCATE_START) aiff_write_strings (psf, SF_STR_LOCATE_START) ; if (psf->has_peak && psf->peak_loc == SF_PEAK_START) { psf_binheader_writef (psf, "Em4", PEAK_MARKER, sizeof (PEAK_CHUNK) + psf->sf.channels * sizeof (PEAK_POS)) ; psf_binheader_writef (psf, "E44", 1, time (NULL)) ; for (k = 0 ; k < psf->sf.channels ; k++) psf_binheader_writef (psf, "Ef4", psf->pchunk->peaks [k].value, psf->pchunk->peaks [k].position) ; /* XXXXX */ } ; /* Write SSND chunk. */ psf_binheader_writef (psf, "Etm844", SSND_MARKER, psf->datalength + SIZEOF_SSND_CHUNK, 0, 0) ; /* Header construction complete so write it out. */ psf_fwrite (psf->header, psf->headindex, 1, psf) ; if (psf->error) return psf->error ; psf->dataoffset = psf->headindex ; if (current < psf->dataoffset) psf_fseek (psf, psf->dataoffset, SEEK_SET) ; else if (current > 0) psf_fseek (psf, current, SEEK_SET) ; return psf->error ;} /* 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 ; psf->dataend = psf_fseek (psf, 0, SEEK_END) ; if (psf->has_peak && psf->peak_loc == SF_PEAK_END) { psf_binheader_writef (psf, "Em4", PEAK_MARKER, sizeof (PEAK_CHUNK) + psf->sf.channels * sizeof (PEAK_POS)) ; psf_binheader_writef (psf, "E44", 1, time (NULL)) ; for (k = 0 ; k < psf->sf.channels ; k++) psf_binheader_writef (psf, "Ef4", psf->pchunk->peaks [k].value, psf->pchunk->peaks [k].position) ; /* XXXXX */ } ; if (psf->str_flags & SF_STR_LOCATE_END) aiff_write_strings (psf, SF_STR_LOCATE_END) ; /* Write the tailer. */ if (psf->headindex) psf_fwrite (psf->header, psf->headindex, 1, psf) ; return 0 ;} /* aiff_write_tailer */static voidaiff_write_strings (SF_PRIVATE *psf, int location){ int k ; for (k = 0 ; k < SF_MAX_STRINGS ; k++) { if (psf->strings [k].type == 0) break ; if (psf->strings [k].flags != location) continue ; switch (psf->strings [k].type) { case SF_STR_SOFTWARE : psf_binheader_writef (psf, "Ems", APPL_MARKER, psf->strings [k].str) ; break ; case SF_STR_TITLE : psf_binheader_writef (psf, "Ems", NAME_MARKER, psf->strings [k].str) ; break ; case SF_STR_COPYRIGHT : psf_binheader_writef (psf, "Ems", c_MARKER, psf->strings [k].str) ; break ; case SF_STR_ARTIST : psf_binheader_writef (psf, "Ems", AUTH_MARKER, psf->strings [k].str) ; break ; case SF_STR_COMMENT : psf_binheader_writef (psf, "Ems", ANNO_MARKER, psf->strings [k].str) ; break ; /* case SF_STR_DATE : psf_binheader_writef (psf, "Ems", ICRD_MARKER, psf->strings [k].str) ; break ; */ } ; } ; return ;} /* aiff_write_strings */static intaiff_command (SF_PRIVATE *psf, int command, void *data, int datasize){ /* Avoid compiler warnings. */ psf = psf ; data = data ; datasize = datasize ; switch (command) { default : break ; } ; return 0 ;} /* aiff_command */static const char*get_loop_mode_str (short mode){ switch (mode) { case 0 : return "none" ; case 1 : return "forward" ; case 2 : return "backward" ; } ; return "*** unknown" ;} /* get_loop_mode_str *//*==========================================================================================** 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){ unsigned int mask = 0x40000000 ; int count ; 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 */static intaiff_read_basc_chunk (SF_PRIVATE * psf){ const char * type_str ; basc_CHUNK bc ; psf_binheader_readf (psf, "E442", &bc.version, &bc.numBeats, &bc.rootNote) ; psf_binheader_readf (psf, "E222", &bc.scaleType, &bc.sigNumerator, &bc.sigDenominator) ; psf_binheader_readf (psf, "E2b", &bc.loopType, &bc.zero_bytes, SIZEOF_basc_CHUNK_PADDING) ; psf_log_printf (psf, " Version ? : %u\n Num Beats : %u\n Root Note : 0x%x\n", bc.version, bc.numBeats, bc.rootNote) ; switch (bc.scaleType) { case basc_SCALE_MINOR : type_str = "MINOR" ; break ; case basc_SCALE_MAJOR : type_str = "MAJOR" ; break ; case basc_SCALE_NEITHER : type_str = "NEITHER" ; break ; case basc_SCALE_BOTH : type_str = "BOTH" ; break ; default : type_str = "!!WRONG!!" ; break ; } ; psf_log_printf (psf, " ScaleType : 0x%x (%s)\n", bc.scaleType, type_str) ; psf_log_printf (psf, " Time Sig : %d/%d\n", bc.sigNumerator, bc.sigDenominator) ; switch (bc.loopType) { case basc_TYPE_ONE_SHOT : type_str = "One Shot" ; break ; case basc_TYPE_LOOP : type_str = "Loop" ; break ; default: type_str = "!!WRONG!!" ; break ; } ; psf_log_printf (psf, " Loop Type : 0x%x (%s)\n", bc.loopType, type_str) ; if ((psf->loop_info = calloc (1, sizeof (SF_LOOP_INFO))) == NULL) return SFE_MALLOC_FAILED ; psf->loop_info->time_sig_num = bc.sigNumerator ; psf->loop_info->time_sig_den = bc.sigDenominator ; psf->loop_info->loop_mode = (bc.loopType == basc_TYPE_ONE_SHOT) ? SF_LOOP_NONE : SF_LOOP_FORWARD ; psf->loop_info->num_beats = bc.numBeats ; /* Can always be recalculated from other known fields. */ psf->loop_info->bpm = (1.0 / psf->sf.frames) * psf->sf.samplerate * ((bc.numBeats * 4.0) / bc.sigDenominator) * 60.0 ; psf->loop_info->root_key = bc.rootNote ; return 0 ;} /* aiff_read_basc_chunk *//*** Do not edit or modify anything in this comment block.** The arch-tag line is a file identity tag for the GNU Arch** revision control system.**** arch-tag: 7dec56ca-d6f2-48cf-863b-a72e7e17a5d9*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -