static int ogg_close (SF_PRIVATE *psf) { OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ; VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ; if (odata == NULL || vdata == NULL) return 0 ; /* Clean up this logical bitstream ; before exit we shuld see if we're ** followed by another [chained]. */ if (psf->file.mode == SFM_WRITE) { if (psf->write_current <= 0) ogg_write_header (psf, 0) ; vorbis_analysis_wrote (&vdata->vd, 0) ; while (vorbis_analysis_blockout (&vdata->vd, &vdata->vb) == 1) { /* analysis, assume we want to use bitrate management */ vorbis_analysis (&vdata->vb, NULL) ; vorbis_bitrate_addblock (&vdata->vb) ; while (vorbis_bitrate_flushpacket (&vdata->vd, &odata->op)) { /* weld the packet into the bitstream */ ogg_stream_packetin (&odata->os, &odata->op) ; /* write out pages (if any) */ while (!odata->eos) { int result = ogg_stream_pageout (&odata->os, &odata->og) ; if (result == 0) break ; psf_fwrite (odata->og.header, 1, odata->og.header_len, psf) ; psf_fwrite (odata->og.body, 1, odata->og.body_len, psf) ; /* this could be set above, but for illustrative purposes, I do it here (to show that vorbis does know where the stream ends) */ if (ogg_page_eos (&odata->og)) odata->eos = 1 ; } } } } /* ogg_page and ogg_packet structs always point to storage in libvorbis. They are never freed or manipulated directly */ vorbis_block_clear (&vdata->vb) ; vorbis_dsp_clear (&vdata->vd) ; vorbis_comment_clear (&vdata->vc) ; vorbis_info_clear (&vdata->vi) ; /* must be called last */ /* should look here to reopen if chained */ /* OK, clean up the framer */ ogg_sync_clear (&odata->oy) ; ogg_stream_clear (&odata->os) ; return 0 ; } /* ogg_close */
static int voc_close (SF_PRIVATE *psf) { if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { /* Now we know for certain the length of the file we can re-write ** correct values for the FORM, 8SVX and BODY chunks. */ unsigned byte = VOC_TERMINATOR ; psf_fseek (psf, 0, SEEK_END) ; /* Write terminator */ psf_fwrite (&byte, 1, 1, psf) ; psf->filelength = psf_ftell (psf) ; psf_fseek (psf, 0, SEEK_SET) ; psf->datalength = psf->filelength - psf->dataoffset ; psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; voc_write_header (psf, SF_FALSE) ; } ; return 0 ; } /* voc_close */
static int caf_write_tailer (SF_PRIVATE *psf) { /* Reset the current header buffer length to zero. */ psf->header [0] = 0 ; psf->headindex = 0 ; if (psf->bytewidth > 0 && psf->sf.seekable == SF_TRUE) { psf->datalength = psf->sf.frames * psf->bytewidth * psf->sf.channels ; psf->dataend = psf->dataoffset + psf->datalength ; } ; if (psf->dataend > 0) psf_fseek (psf, psf->dataend, SEEK_SET) ; else psf->dataend = psf_fseek (psf, 0, SEEK_END) ; if (psf->dataend & 1) psf_binheader_writef (psf, "z", 1) ; if (psf->strings.flags & SF_STR_LOCATE_END) caf_write_strings (psf, SF_STR_LOCATE_END) ; /* Write the tailer. */ if (psf->headindex > 0) psf_fwrite (psf->header, psf->headindex, 1, psf) ; return 0 ; } /* caf_write_tailer */
static int pvf_write_header (SF_PRIVATE *psf, int UNUSED (calc_length)) { sf_count_t current ; if (psf->pipeoffset > 0) return 0 ; current = psf_ftell (psf) ; /* Reset the current header length to zero. */ psf->header [0] = 0 ; psf->headindex = 0 ; if (psf->is_pipe == SF_FALSE) psf_fseek (psf, 0, SEEK_SET) ; snprintf ((char*) psf->header, sizeof (psf->header), "PVF1\n%d %d %d\n", psf->sf.channels, psf->sf.samplerate, psf->bytewidth * 8) ; psf->headindex = strlen ((char*) psf->header) ; /* 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 > 0) psf_fseek (psf, current, SEEK_SET) ; return psf->error ; } /* pvf_write_header */
static int mat4_write_header (SF_PRIVATE *psf, int calc_length) { sf_count_t current ; int encoding ; double samplerate ; current = psf_ftell (psf) ; if (calc_length) { psf->filelength = psf_get_filelen (psf) ; psf->datalength = psf->filelength - psf->dataoffset ; if (psf->dataend) psf->datalength -= psf->filelength - psf->dataend ; psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; } ; encoding = mat4_format_to_encoding (SF_CODEC (psf->sf.format), psf->endian) ; if (encoding == -1) 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) ; /* Need sample rate as a double for writing to the header. */ samplerate = psf->sf.samplerate ; if (psf->endian == SF_ENDIAN_BIG) { psf_binheader_writef (psf, "Em444", MAT4_BE_DOUBLE, 1, 1, 0) ; psf_binheader_writef (psf, "E4bd", 11, "samplerate", make_size_t (11), samplerate) ; psf_binheader_writef (psf, "tEm484", encoding, psf->sf.channels, psf->sf.frames, 0) ; psf_binheader_writef (psf, "E4b", 9, "wavedata", make_size_t (9)) ; } else if (psf->endian == SF_ENDIAN_LITTLE) { psf_binheader_writef (psf, "em444", MAT4_LE_DOUBLE, 1, 1, 0) ; psf_binheader_writef (psf, "e4bd", 11, "samplerate", make_size_t (11), samplerate) ; psf_binheader_writef (psf, "tem484", encoding, psf->sf.channels, psf->sf.frames, 0) ; psf_binheader_writef (psf, "e4b", 9, "wavedata", make_size_t (9)) ; } else return SFE_BAD_OPEN_FORMAT ; /* 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 > 0) psf_fseek (psf, current, SEEK_SET) ; return psf->error ; } /* mat4_write_header */
static int avr_write_header (SF_PRIVATE *psf, int calc_length) { sf_count_t current ; int sign, datalength ; if (psf->pipeoffset > 0) return 0 ; current = psf_ftell (psf) ; if (calc_length) { psf->filelength = psf_get_filelen (psf) ; psf->datalength = psf->filelength - psf->dataoffset ; if (psf->dataend) psf->datalength -= psf->filelength - psf->dataend ; psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; } ; /* Reset the current header length to zero. */ psf->header [0] = 0 ; psf->headindex = 0 ; /* ** Only attempt to seek if we are not writng to a pipe. If we are ** writing to a pipe we shouldn't be here anyway. */ if (psf->is_pipe == SF_FALSE) psf_fseek (psf, 0, SEEK_SET) ; datalength = (int) (psf->datalength & 0x7FFFFFFF) ; psf_binheader_writef (psf, "Emz22", TWOBIT_MARKER, (size_t) 8, psf->sf.channels == 2 ? 0xFFFF : 0, psf->bytewidth * 8) ; sign = ((psf->sf.format & SF_FORMAT_SUBMASK) == SF_FORMAT_PCM_U8) ? 0 : 0xFFFF ; psf_binheader_writef (psf, "E222", sign, 0, 0xFFFF) ; psf_binheader_writef (psf, "E4444", psf->sf.samplerate, psf->sf.frames, 0, 0) ; psf_binheader_writef (psf, "E222zz", 0, 0, 0, (size_t) 20, (size_t) 64) ; /* 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 > 0) psf_fseek (psf, current, SEEK_SET) ; return psf->error ; } /* avr_write_header */
static int ircam_write_header (SF_PRIVATE *psf, int UNUSED (calc_length)) { int encoding ; float samplerate ; sf_count_t current ; if (psf->pipeoffset > 0) return 0 ; current = psf_ftell (psf) ; /* This also sets psf->endian. */ encoding = get_encoding (SF_CODEC (psf->sf.format)) ; if (encoding == 0) return SFE_BAD_OPEN_FORMAT ; /* Reset the current header length to zero. */ psf->header [0] = 0 ; psf->headindex = 0 ; if (psf->is_pipe == SF_FALSE) psf_fseek (psf, 0, SEEK_SET) ; samplerate = psf->sf.samplerate ; switch (psf->endian) { case SF_ENDIAN_BIG : psf_binheader_writef (psf, "Emf", IRCAM_02B_MARKER, samplerate) ; psf_binheader_writef (psf, "E44", psf->sf.channels, encoding) ; break ; case SF_ENDIAN_LITTLE : psf_binheader_writef (psf, "emf", IRCAM_03L_MARKER, samplerate) ; psf_binheader_writef (psf, "e44", psf->sf.channels, encoding) ; break ; default : return SFE_BAD_OPEN_FORMAT ; } ; psf_binheader_writef (psf, "z", (size_t) (IRCAM_DATA_OFFSET - psf->headindex)) ; /* Header construction complete so write it out. */ psf_fwrite (psf->header, psf->headindex, 1, psf) ; if (psf->error) return psf->error ; if (current > 0) psf_fseek (psf, current, SEEK_SET) ; return psf->error ; } /* ircam_write_header */
static void ogg_write_samples (SF_PRIVATE *psf, OGG_PRIVATE *odata, VORBIS_PRIVATE *vdata, int in_frames) { vorbis_analysis_wrote (&vdata->vd, in_frames) ; /* ** Vorbis does some data preanalysis, then divvies up blocks for ** more involved (potentially parallel) processing. Get a single ** block for encoding now. */ while (vorbis_analysis_blockout (&vdata->vd, &vdata->vb) == 1) { /* analysis, assume we want to use bitrate management */ vorbis_analysis (&vdata->vb, NULL) ; vorbis_bitrate_addblock (&vdata->vb) ; while (vorbis_bitrate_flushpacket (&vdata->vd, &odata->op)) { /* weld the packet into the bitstream */ ogg_stream_packetin (&odata->os, &odata->op) ; /* write out pages (if any) */ while (!odata->eos) { int result = ogg_stream_pageout (&odata->os, &odata->og) ; if (result == 0) break ; psf_fwrite (odata->og.header, 1, odata->og.header_len, psf) ; psf_fwrite (odata->og.body, 1, odata->og.body_len, psf) ; /* This could be set above, but for illustrative purposes, I do ** it here (to show that vorbis does know where the stream ends) */ if (ogg_page_eos (&odata->og)) odata->eos = 1 ; } ; } ; } ; vdata->loc += in_frames ; } /* ogg_write_data */
static int ircam_write_header (SF_PRIVATE *psf, int calc_length) { int encoding ; float samplerate ; sf_count_t current ; current = psf_ftell (psf) ; calc_length = calc_length ; /* This also sets psf->endian. */ encoding = get_encoding (psf->sf.format & SF_FORMAT_SUBMASK) ; if (! encoding) 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) ; samplerate = psf->sf.samplerate ; if (psf->endian == SF_ENDIAN_BIG) { psf_binheader_writef (psf, "Emf", IRCAM_02B_MARKER, samplerate) ; psf_binheader_writef (psf, "E44", psf->sf.channels, encoding) ; } else if (psf->endian == SF_ENDIAN_LITTLE) { psf_binheader_writef (psf, "emf", IRCAM_03L_MARKER, samplerate) ; psf_binheader_writef (psf, "e44", psf->sf.channels, encoding) ; } else return SFE_BAD_OPEN_FORMAT ; psf_binheader_writef (psf, "z", IRCAM_DATA_OFFSET - psf->headindex) ; /* Header construction complete so write it out. */ psf_fwrite (psf->header, psf->headindex, 1, psf) ; if (psf->error) return psf->error ; if (current > 0) psf_fseek (psf, current, SEEK_SET) ; return psf->error ; } /* ircam_write_header */
static void test_write_or_die (SF_PRIVATE *psf, void *data, sf_count_t bytes, sf_count_t items, sf_count_t new_position, int linenum) { sf_count_t retval ; retval = psf_fwrite (data, bytes, items, psf) ; if (retval != items) { printf ("\n\nLine %d: psf_write() returned %ld (should be %ld)\n\n", linenum, (long) retval, (long) items) ; exit (1) ; } ; if ((retval = psf_ftell (psf)) != new_position) { printf ("\n\nLine %d: file length after write is not correct. (%ld should be %ld)\n\n", linenum, (long) retval, (long) new_position) ; exit (1) ; } ; return ; } /* test_write_or_die */
static int voc_close (SF_PRIVATE *psf) { if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR) { /* Now we know for certain the length of the file we can re-write ** correct values for the FORM, 8SVX and BODY chunks. */ unsigned char byte = VOC_TERMINATOR ; psf_fseek (psf, 0, SEEK_END) ; /* Write terminator */ psf_fwrite (&byte, 1, 1, psf) ; voc_write_header (psf, SF_TRUE) ; } ; return 0 ; } /* voc_close */
static int wve_write_header (SF_PRIVATE *psf, int calc_length) { sf_count_t current ; unsigned datalen ; current = psf_ftell (psf) ; if (calc_length) { psf->filelength = psf_get_filelen (psf) ; psf->datalength = psf->filelength - psf->dataoffset ; if (psf->dataend) psf->datalength -= psf->filelength - psf->dataend ; psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; } ; /* Reset the current header length to zero. */ psf->header [0] = 0 ; psf->headindex = 0 ; psf_fseek (psf, 0, SEEK_SET) ; /* Write header. */ datalen = psf->datalength ; psf_binheader_writef (psf, "Emmmm", ALAW_MARKER, SOUN_MARKER, DFIL_MARKER, ESSN_MARKER) ; psf_binheader_writef (psf, "E2422222", PSION_VERSION, datalen, 0, 0, 0, 0, 0) ; psf_fwrite (psf->header, psf->headindex, 1, psf) ; if (psf->sf.channels != 1) return SFE_CHANNEL_COUNT ; if (psf->error) return psf->error ; psf->dataoffset = psf->headindex ; if (current > 0) psf_fseek (psf, current, SEEK_SET) ; return psf->error ; } /* wve_write_header */
static int htk_write_header (SF_PRIVATE *psf, int calc_length) { sf_count_t current ; int sample_count, sample_period ; current = psf_ftell (psf) ; if (calc_length) psf->filelength = psf_get_filelen (psf) ; /* Reset the current header length to zero. */ psf->header.ptr [0] = 0 ; psf->header.indx = 0 ; psf_fseek (psf, 0, SEEK_SET) ; if (psf->filelength > 12) sample_count = (psf->filelength - 12) / 2 ; else sample_count = 0 ; sample_period = 10000000 / psf->sf.samplerate ; psf_binheader_writef (psf, "E444", sample_count, sample_period, 0x20000) ; /* Header construction complete so write it out. */ psf_fwrite (psf->header.ptr, psf->header.indx, 1, psf) ; if (psf->error) return psf->error ; psf->dataoffset = psf->header.indx ; if (current > 0) psf_fseek (psf, current, SEEK_SET) ; return psf->error ; } /* htk_write_header */
static int vorbis_write_header (SF_PRIVATE *psf, int UNUSED (calc_length)) { OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ; VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ; int k, ret ; vorbis_info_init (&vdata->vinfo) ; /* The style of encoding should be selectable here, VBR quality mode. */ ret = vorbis_encode_init_vbr (&vdata->vinfo, psf->sf.channels, psf->sf.samplerate, vdata->quality) ; #if 0 ret = vorbis_encode_init (&vdata->vinfo, psf->sf.channels, psf->sf.samplerate, -1, 128000, -1) ; /* average bitrate mode */ ret = ( vorbis_encode_setup_managed (&vdata->vinfo, psf->sf.channels, psf->sf.samplerate, -1, 128000, -1) || vorbis_encode_ctl (&vdata->vinfo, OV_ECTL_RATEMANAGE_AVG, NULL) || vorbis_encode_setup_init (&vdata->vinfo) ) ; #endif if (ret) return SFE_BAD_OPEN_FORMAT ; vdata->loc = 0 ; /* add a comment */ vorbis_comment_init (&vdata->vcomment) ; vorbis_comment_add_tag (&vdata->vcomment, "ENCODER", "libsndfile") ; for (k = 0 ; k < SF_MAX_STRINGS ; k++) { const char * name ; if (psf->strings.data [k].type == 0) break ; switch (psf->strings.data [k].type) { case SF_STR_TITLE : name = "TITLE" ; break ; case SF_STR_COPYRIGHT : name = "COPYRIGHT" ; break ; case SF_STR_SOFTWARE : name = "SOFTWARE" ; break ; case SF_STR_ARTIST : name = "ARTIST" ; break ; case SF_STR_COMMENT : name = "COMMENT" ; break ; case SF_STR_DATE : name = "DATE" ; break ; case SF_STR_ALBUM : name = "ALBUM" ; break ; case SF_STR_LICENSE : name = "LICENSE" ; break ; case SF_STR_TRACKNUMBER : name = "Tracknumber" ; break ; case SF_STR_GENRE : name = "Genre" ; break ; default : continue ; } ; vorbis_comment_add_tag (&vdata->vcomment, name, psf->strings.storage + psf->strings.data [k].offset) ; } ; /* set up the analysis state and auxiliary encoding storage */ vorbis_analysis_init (&vdata->vdsp, &vdata->vinfo) ; vorbis_block_init (&vdata->vdsp, &vdata->vblock) ; /* ** Set up our packet->stream encoder. ** Pick a random serial number ; that way we can more likely build ** chained streams just by concatenation. */ ogg_stream_init (&odata->ostream, psf_rand_int32 ()) ; /* Vorbis streams begin with three headers ; the initial header (with most of the codec setup parameters) which is mandated by the Ogg bitstream spec. The second header holds any comment fields. The third header holds the bitstream codebook. We merely need to make the headers, then pass them to libvorbis one at a time ; libvorbis handles the additional Ogg bitstream constraints */ { ogg_packet header ; ogg_packet header_comm ; ogg_packet header_code ; int result ; vorbis_analysis_headerout (&vdata->vdsp, &vdata->vcomment, &header, &header_comm, &header_code) ; ogg_stream_packetin (&odata->ostream, &header) ; /* automatically placed in its own page */ ogg_stream_packetin (&odata->ostream, &header_comm) ; ogg_stream_packetin (&odata->ostream, &header_code) ; /* This ensures the actual * audio data will start on a new page, as per spec */ while ((result = ogg_stream_flush (&odata->ostream, &odata->opage)) != 0) { psf_fwrite (odata->opage.header, 1, odata->opage.header_len, psf) ; psf_fwrite (odata->opage.body, 1, odata->opage.body_len, psf) ; } ; } return 0 ; } /* vorbis_write_header */
static int voc_write_header (SF_PRIVATE *psf, int calc_length) { sf_count_t current ; int rate_const, subformat ; current = psf_ftell (psf) ; if (calc_length) { psf->filelength = psf_get_filelen (psf) ; psf->datalength = psf->filelength - psf->dataoffset ; if (psf->dataend) psf->datalength -= psf->filelength - psf->dataend ; psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; } ; subformat = SF_CODEC (psf->sf.format) ; /* Reset the current header length to zero. */ psf->header [0] = 0 ; psf->headindex = 0 ; psf_fseek (psf, 0, SEEK_SET) ; /* VOC marker and 0x1A byte. */ psf_binheader_writef (psf, "eb1", "Creative Voice File", make_size_t (19), 0x1A) ; /* Data offset, version and other. */ psf_binheader_writef (psf, "e222", 26, 0x0114, 0x111F) ; /* Use same logic as SOX. ** If the file is mono 8 bit data, use VOC_SOUND_DATA. ** If the file is mono 16 bit data, use VOC_EXTENED. ** Otherwise use VOC_EXTENED_2. */ if (subformat == SF_FORMAT_PCM_U8 && psf->sf.channels == 1) { /* samplerate = 1000000 / (256 - rate_const) ; */ rate_const = 256 - 1000000 / psf->sf.samplerate ; /* First type marker, length, rate_const and compression */ psf_binheader_writef (psf, "e1311", VOC_SOUND_DATA, (int) (psf->datalength + 1), rate_const, 0) ; } else if (subformat == SF_FORMAT_PCM_U8 && psf->sf.channels == 2) { /* sample_rate = 128000000 / (65536 - rate_short) ; */ rate_const = 65536 - 128000000 / psf->sf.samplerate ; /* First write the VOC_EXTENDED section ** marker, length, rate_const and compression */ psf_binheader_writef (psf, "e13211", VOC_EXTENDED, 4, rate_const, 0, 1) ; /* samplerate = 1000000 / (256 - rate_const) ; */ rate_const = 256 - 1000000 / psf->sf.samplerate ; /* Now write the VOC_SOUND_DATA section ** marker, length, rate_const and compression */ psf_binheader_writef (psf, "e1311", VOC_SOUND_DATA, (int) (psf->datalength + 1), rate_const, 0) ; } else { int length ; if (psf->sf.channels < 1 || psf->sf.channels > 2) return SFE_CHANNEL_COUNT ; switch (subformat) { case SF_FORMAT_PCM_U8 : psf->bytewidth = 1 ; length = psf->sf.frames * psf->sf.channels * psf->bytewidth + 12 ; /* Marker, length, sample rate, bitwidth, stereo flag, encoding and fourt zero bytes. */ psf_binheader_writef (psf, "e1341124", VOC_EXTENDED_II, length, psf->sf.samplerate, 16, psf->sf.channels, 4, 0) ; break ; case SF_FORMAT_PCM_16 : psf->bytewidth = 2 ; length = psf->sf.frames * psf->sf.channels * psf->bytewidth + 12 ; /* Marker, length, sample rate, bitwidth, stereo flag, encoding and fourt zero bytes. */ psf_binheader_writef (psf, "e1341124", VOC_EXTENDED_II, length, psf->sf.samplerate, 16, psf->sf.channels, 4, 0) ; break ; case SF_FORMAT_ALAW : psf->bytewidth = 1 ; length = psf->sf.frames * psf->sf.channels * psf->bytewidth + 12 ; psf_binheader_writef (psf, "e1341124", VOC_EXTENDED_II, length, psf->sf.samplerate, 8, psf->sf.channels, 6, 0) ; break ; case SF_FORMAT_ULAW : psf->bytewidth = 1 ; length = psf->sf.frames * psf->sf.channels * psf->bytewidth + 12 ; psf_binheader_writef (psf, "e1341124", VOC_EXTENDED_II, length, psf->sf.samplerate, 8, psf->sf.channels, 7, 0) ; break ; default : return SFE_UNIMPLEMENTED ; } ; } ; psf_fwrite (psf->header, psf->headindex, 1, psf) ; if (psf->error) return psf->error ; psf->dataoffset = psf->headindex ; if (current > 0) psf_fseek (psf, current, SEEK_SET) ; return psf->error ; } /* voc_write_header */
static int w64_write_header (SF_PRIVATE *psf, int calc_length) { sf_count_t fmt_size, current ; size_t fmt_pad = 0 ; int subformat, add_fact_chunk = SF_FALSE ; current = psf_ftell (psf) ; if (calc_length) { psf->filelength = psf_get_filelen (psf) ; psf->datalength = psf->filelength - psf->dataoffset ; if (psf->dataend) psf->datalength -= psf->filelength - psf->dataend ; if (psf->bytewidth) psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; } ; /* Reset the current header length to zero. */ psf->header [0] = 0 ; psf->headindex = 0 ; psf_fseek (psf, 0, SEEK_SET) ; /* riff marker, length, wave and 'fmt ' markers. */ psf_binheader_writef (psf, "eh8hh", riff_MARKER16, psf->filelength, wave_MARKER16, fmt_MARKER16) ; subformat = SF_CODEC (psf->sf.format) ; switch (subformat) { case SF_FORMAT_PCM_U8 : case SF_FORMAT_PCM_16 : case SF_FORMAT_PCM_24 : case SF_FORMAT_PCM_32 : fmt_size = 24 + 2 + 2 + 4 + 4 + 2 + 2 ; fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ; fmt_size += fmt_pad ; /* fmt : format, channels, samplerate */ psf_binheader_writef (psf, "e8224", fmt_size, WAVE_FORMAT_PCM, psf->sf.channels, psf->sf.samplerate) ; /* fmt : bytespersec */ psf_binheader_writef (psf, "e4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ; /* fmt : blockalign, bitwidth */ psf_binheader_writef (psf, "e22", psf->bytewidth * psf->sf.channels, psf->bytewidth * 8) ; break ; case SF_FORMAT_FLOAT : case SF_FORMAT_DOUBLE : fmt_size = 24 + 2 + 2 + 4 + 4 + 2 + 2 ; fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ; fmt_size += fmt_pad ; /* fmt : format, channels, samplerate */ psf_binheader_writef (psf, "e8224", fmt_size, WAVE_FORMAT_IEEE_FLOAT, psf->sf.channels, psf->sf.samplerate) ; /* fmt : bytespersec */ psf_binheader_writef (psf, "e4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ; /* fmt : blockalign, bitwidth */ psf_binheader_writef (psf, "e22", psf->bytewidth * psf->sf.channels, psf->bytewidth * 8) ; add_fact_chunk = SF_TRUE ; break ; case SF_FORMAT_ULAW : fmt_size = 24 + 2 + 2 + 4 + 4 + 2 + 2 ; fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ; fmt_size += fmt_pad ; /* fmt : format, channels, samplerate */ psf_binheader_writef (psf, "e8224", fmt_size, WAVE_FORMAT_MULAW, psf->sf.channels, psf->sf.samplerate) ; /* fmt : bytespersec */ psf_binheader_writef (psf, "e4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ; /* fmt : blockalign, bitwidth */ psf_binheader_writef (psf, "e22", psf->bytewidth * psf->sf.channels, 8) ; add_fact_chunk = SF_TRUE ; break ; case SF_FORMAT_ALAW : fmt_size = 24 + 2 + 2 + 4 + 4 + 2 + 2 ; fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ; fmt_size += fmt_pad ; /* fmt : format, channels, samplerate */ psf_binheader_writef (psf, "e8224", fmt_size, WAVE_FORMAT_ALAW, psf->sf.channels, psf->sf.samplerate) ; /* fmt : bytespersec */ psf_binheader_writef (psf, "e4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ; /* fmt : blockalign, bitwidth */ psf_binheader_writef (psf, "e22", psf->bytewidth * psf->sf.channels, 8) ; add_fact_chunk = SF_TRUE ; break ; /* Lite remove start */ case SF_FORMAT_IMA_ADPCM : { int blockalign, framesperblock, bytespersec ; blockalign = wav_w64_srate2blocksize (psf->sf.samplerate * psf->sf.channels) ; framesperblock = 2 * (blockalign - 4 * psf->sf.channels) / psf->sf.channels + 1 ; bytespersec = (psf->sf.samplerate * blockalign) / framesperblock ; /* fmt chunk. */ fmt_size = 24 + 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 ; fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ; fmt_size += fmt_pad ; /* fmt : size, WAV format type, channels. */ psf_binheader_writef (psf, "e822", fmt_size, WAVE_FORMAT_IMA_ADPCM, psf->sf.channels) ; /* fmt : samplerate, bytespersec. */ psf_binheader_writef (psf, "e44", psf->sf.samplerate, bytespersec) ; /* fmt : blockalign, bitwidth, extrabytes, framesperblock. */ psf_binheader_writef (psf, "e2222", blockalign, 4, 2, framesperblock) ; } ; add_fact_chunk = SF_TRUE ; break ; case SF_FORMAT_MS_ADPCM : { int blockalign, framesperblock, bytespersec, extrabytes ; blockalign = wav_w64_srate2blocksize (psf->sf.samplerate * psf->sf.channels) ; framesperblock = 2 + 2 * (blockalign - 7 * psf->sf.channels) / psf->sf.channels ; bytespersec = (psf->sf.samplerate * blockalign) / framesperblock ; /* fmt chunk. */ extrabytes = 2 + 2 + MSADPCM_ADAPT_COEFF_COUNT * (2 + 2) ; fmt_size = 24 + 2 + 2 + 4 + 4 + 2 + 2 + 2 + extrabytes ; fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ; fmt_size += fmt_pad ; /* fmt : size, W64 format type, channels. */ psf_binheader_writef (psf, "e822", fmt_size, WAVE_FORMAT_MS_ADPCM, psf->sf.channels) ; /* fmt : samplerate, bytespersec. */ psf_binheader_writef (psf, "e44", psf->sf.samplerate, bytespersec) ; /* fmt : blockalign, bitwidth, extrabytes, framesperblock. */ psf_binheader_writef (psf, "e22222", blockalign, 4, extrabytes, framesperblock, 7) ; msadpcm_write_adapt_coeffs (psf) ; } ; add_fact_chunk = SF_TRUE ; break ; /* Lite remove end */ case SF_FORMAT_GSM610 : { int bytespersec ; bytespersec = (psf->sf.samplerate * WAV_W64_GSM610_BLOCKSIZE) / WAV_W64_GSM610_SAMPLES ; /* fmt chunk. */ fmt_size = 24 + 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 ; fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ; fmt_size += fmt_pad ; /* fmt : size, WAV format type, channels. */ psf_binheader_writef (psf, "e822", fmt_size, WAVE_FORMAT_GSM610, psf->sf.channels) ; /* fmt : samplerate, bytespersec. */ psf_binheader_writef (psf, "e44", psf->sf.samplerate, bytespersec) ; /* fmt : blockalign, bitwidth, extrabytes, framesperblock. */ psf_binheader_writef (psf, "e2222", WAV_W64_GSM610_BLOCKSIZE, 0, 2, WAV_W64_GSM610_SAMPLES) ; } ; add_fact_chunk = SF_TRUE ; break ; default : return SFE_UNIMPLEMENTED ; } ; /* Pad to 8 bytes with zeros. */ if (fmt_pad > 0) psf_binheader_writef (psf, "z", fmt_pad) ; if (add_fact_chunk) psf_binheader_writef (psf, "eh88", fact_MARKER16, (sf_count_t) (16 + 8 + 8), psf->sf.frames) ; psf_binheader_writef (psf, "eh8", data_MARKER16, psf->datalength + 24) ; psf_fwrite (psf->header, psf->headindex, 1, psf) ; if (psf->error) return psf->error ; psf->dataoffset = psf->headindex ; if (current > 0) psf_fseek (psf, current, SEEK_SET) ; return psf->error ; } /* w64_write_header */
static int nist_write_header (SF_PRIVATE *psf, int calc_length) { char *end_str ; long samples ; sf_count_t current ; current = psf_ftell (psf->filedes) ; /* Prevent compiler warning. */ calc_length = calc_length ; if (psf->endian == SF_ENDIAN_BIG) end_str = "10" ; else if (psf->endian == SF_ENDIAN_LITTLE) end_str = "01" ; else end_str = "error" ; /* Clear the whole header. */ memset (psf->header, 0, sizeof (psf->header)) ; psf->headindex = 0 ; psf_fseek (psf->filedes, 0, SEEK_SET) ; psf_asciiheader_printf (psf, "NIST_1A\n 1024\n") ; psf_asciiheader_printf (psf, "channel_count -i %d\n", psf->sf.channels) ; psf_asciiheader_printf (psf, "sample_rate -i %d\n", psf->sf.samplerate) ; switch (psf->sf.format & SF_FORMAT_SUBMASK) { case SF_FORMAT_PCM_S8 : psf_asciiheader_printf (psf, "sample_coding -s3 pcm\n") ; psf_asciiheader_printf (psf, "sample_n_bytes -i 1\n" "sample_sig_bits -i 8\n") ; break ; case SF_FORMAT_PCM_16 : case SF_FORMAT_PCM_24 : case SF_FORMAT_PCM_32 : psf_asciiheader_printf (psf, "sample_n_bytes -i %d\n", psf->bytewidth) ; psf_asciiheader_printf (psf, "sample_sig_bits -i %d\n", psf->bytewidth * 8) ; psf_asciiheader_printf (psf, "sample_coding -s3 pcm\n" "sample_byte_format -s%d %s\n", psf->bytewidth, end_str) ; break ; case SF_FORMAT_ALAW : psf_asciiheader_printf (psf, "sample_coding -s4 alaw\n") ; psf_asciiheader_printf (psf, "sample_n_bytes -s1 1\n") ; break ; case SF_FORMAT_ULAW : psf_asciiheader_printf (psf, "sample_coding -s4 ulaw\n") ; psf_asciiheader_printf (psf, "sample_n_bytes -s1 1\n") ; break ; default : return SFE_UNIMPLEMENTED ; } ; psf->dataoffset = NIST_HEADER_LENGTH ; /* Fix this */ samples = psf->sf.frames ; psf_asciiheader_printf (psf, "sample_count -i %ld\n", samples) ; psf_asciiheader_printf (psf, "end_head\n") ; /* Zero fill to dataoffset. */ psf_binheader_writef (psf, "z", NIST_HEADER_LENGTH - psf->headindex) ; psf_fwrite (psf->header, psf->headindex, 1, psf->filedes) ; if (current > 0) psf_fseek (psf->filedes, current, SEEK_SET) ; return 0 ; } /* nist_write_header */
static int au_write_header (SF_PRIVATE *psf, int calc_length) { sf_count_t current ; int encoding, datalength ; if (psf->pipeoffset > 0) return 0 ; current = psf_ftell (psf) ; if (calc_length) { psf->filelength = psf_get_filelen (psf) ; psf->datalength = psf->filelength - psf->dataoffset ; if (psf->dataend) psf->datalength -= psf->filelength - psf->dataend ; } ; encoding = au_format_to_encoding (SF_CODEC (psf->sf.format)) ; if (! encoding) return (psf->error = SFE_BAD_OPEN_FORMAT) ; /* Reset the current header length to zero. */ psf->header [0] = 0 ; psf->headindex = 0 ; /* ** Only attempt to seek if we are not writng to a pipe. If we are ** writing to a pipe we shouldn't be here anyway. */ if (psf->is_pipe == SF_FALSE) psf_fseek (psf, 0, SEEK_SET) ; /* ** AU format files allow a datalength value of -1 if the datalength ** is not know at the time the header is written. ** Also use this value of -1 if the datalength > 2 gigabytes. */ if (psf->datalength < 0 || psf->datalength > 0x7FFFFFFF) datalength = -1 ; else datalength = (int) (psf->datalength & 0x7FFFFFFF) ; if (psf->endian == SF_ENDIAN_BIG) { psf_binheader_writef (psf, "Em4", DOTSND_MARKER, AU_DATA_OFFSET) ; psf_binheader_writef (psf, "E4444", datalength, encoding, psf->sf.samplerate, psf->sf.channels) ; } else if (psf->endian == SF_ENDIAN_LITTLE) { psf_binheader_writef (psf, "em4", DNSDOT_MARKER, AU_DATA_OFFSET) ; psf_binheader_writef (psf, "e4444", datalength, encoding, psf->sf.samplerate, psf->sf.channels) ; } else return (psf->error = SFE_BAD_OPEN_FORMAT) ; /* 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 > 0) psf_fseek (psf, current, SEEK_SET) ; return psf->error ; } /* au_write_header */
static int mat5_write_header (SF_PRIVATE *psf, int calc_length) { static const char *sr_name = "samplerate\0\0\0\0\0\0\0\0\0\0\0" ; static const char *wd_name = "wavedata\0" ; sf_count_t current, datasize ; int encoding ; current = psf_ftell (psf) ; if (calc_length) { psf_fseek (psf, 0, SEEK_END) ; psf->filelength = psf_ftell (psf) ; psf_fseek (psf, 0, SEEK_SET) ; psf->datalength = psf->filelength - psf->dataoffset ; if (psf->dataend) psf->datalength -= psf->filelength - psf->dataend ; psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; } ; switch (psf->sf.format & SF_FORMAT_SUBMASK) { case SF_FORMAT_PCM_U8 : encoding = MAT5_TYPE_UCHAR ; break ; case SF_FORMAT_PCM_16 : encoding = MAT5_TYPE_INT16 ; break ; case SF_FORMAT_PCM_32 : encoding = MAT5_TYPE_INT32 ; break ; case SF_FORMAT_FLOAT : encoding = MAT5_TYPE_FLOAT ; break ; case SF_FORMAT_DOUBLE : encoding = MAT5_TYPE_DOUBLE ; 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, "S", "MATLAB 5.0 MAT-file, written by " PACKAGE "-" VERSION ", ") ; psf_get_date_str (psf->u.scbuf, sizeof (psf->u.scbuf)) ; psf_binheader_writef (psf, "jS", -1, psf->u.scbuf) ; memset (psf->u.scbuf, ' ', 124 - psf->headindex) ; psf_binheader_writef (psf, "b", psf->u.scbuf, 124 - psf->headindex) ; psf->rwf_endian = psf->endian ; if (psf->rwf_endian == SF_ENDIAN_BIG) psf_binheader_writef (psf, "2b", 0x0100, "MI", 2) ; else psf_binheader_writef (psf, "2b", 0x0100, "IM", 2) ; psf_binheader_writef (psf, "444444", MAT5_TYPE_ARRAY, 64, MAT5_TYPE_UINT32, 8, 6, 0) ; psf_binheader_writef (psf, "4444", MAT5_TYPE_INT32, 8, 1, 1) ; psf_binheader_writef (psf, "44b", MAT5_TYPE_SCHAR, strlen (sr_name), sr_name, 16) ; if (psf->sf.samplerate > 0xFFFF) psf_binheader_writef (psf, "44", MAT5_TYPE_COMP_UINT, psf->sf.samplerate) ; else { unsigned short samplerate = psf->sf.samplerate ; psf_binheader_writef (psf, "422", MAT5_TYPE_COMP_USHORT, samplerate, 0) ; } ; datasize = psf->sf.frames * psf->sf.channels * psf->bytewidth ; psf_binheader_writef (psf, "t484444", MAT5_TYPE_ARRAY, datasize + 64, MAT5_TYPE_UINT32, 8, 6, 0) ; psf_binheader_writef (psf, "t4448", MAT5_TYPE_INT32, 8, psf->sf.channels, psf->sf.frames) ; psf_binheader_writef (psf, "44b", MAT5_TYPE_SCHAR, strlen (wd_name), wd_name, strlen (wd_name)) ; datasize = psf->sf.frames * psf->sf.channels * psf->bytewidth ; if (datasize > 0x7FFFFFFF) datasize = 0x7FFFFFFF ; psf_binheader_writef (psf, "t48", encoding, datasize) ; /* 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 > 0) psf_fseek (psf, current, SEEK_SET) ; return psf->error ; } /* mat5_write_header */
static int nist_write_header (SF_PRIVATE *psf, int calc_length) { const char *end_str ; long samples ; sf_count_t current ; current = psf_ftell (psf) ; if (calc_length) { psf->filelength = psf_get_filelen (psf) ; psf->datalength = psf->filelength - psf->dataoffset ; if (psf->dataend) psf->datalength -= psf->filelength - psf->dataend ; if (psf->bytewidth > 0) psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; } ; if (psf->endian == SF_ENDIAN_BIG) end_str = "10" ; else if (psf->endian == SF_ENDIAN_LITTLE) end_str = "01" ; else end_str = "error" ; /* Clear the whole header. */ memset (psf->header.ptr, 0, psf->header.len) ; psf->header.indx = 0 ; psf_fseek (psf, 0, SEEK_SET) ; psf_asciiheader_printf (psf, "NIST_1A\n 1024\n") ; psf_asciiheader_printf (psf, "channel_count -i %d\n", psf->sf.channels) ; psf_asciiheader_printf (psf, "sample_rate -i %d\n", psf->sf.samplerate) ; switch (SF_CODEC (psf->sf.format)) { case SF_FORMAT_PCM_S8 : psf_asciiheader_printf (psf, "sample_coding -s3 pcm\n") ; psf_asciiheader_printf (psf, "sample_n_bytes -i 1\n" "sample_sig_bits -i 8\n") ; break ; case SF_FORMAT_PCM_16 : case SF_FORMAT_PCM_24 : case SF_FORMAT_PCM_32 : psf_asciiheader_printf (psf, "sample_n_bytes -i %d\n", psf->bytewidth) ; psf_asciiheader_printf (psf, "sample_sig_bits -i %d\n", psf->bytewidth * 8) ; psf_asciiheader_printf (psf, "sample_coding -s3 pcm\n" "sample_byte_format -s%d %s\n", psf->bytewidth, end_str) ; break ; case SF_FORMAT_ALAW : psf_asciiheader_printf (psf, "sample_coding -s4 alaw\n") ; psf_asciiheader_printf (psf, "sample_n_bytes -s1 1\n") ; break ; case SF_FORMAT_ULAW : psf_asciiheader_printf (psf, "sample_coding -s4 ulaw\n") ; psf_asciiheader_printf (psf, "sample_n_bytes -s1 1\n") ; break ; default : return SFE_UNIMPLEMENTED ; } ; psf->dataoffset = NIST_HEADER_LENGTH ; /* Fix this */ samples = psf->sf.frames ; psf_asciiheader_printf (psf, "sample_count -i %ld\n", samples) ; psf_asciiheader_printf (psf, "end_head\n") ; /* Zero fill to dataoffset. */ psf_binheader_writef (psf, "z", BHWz ((size_t) (NIST_HEADER_LENGTH - psf->header.indx))) ; psf_fwrite (psf->header.ptr, psf->header.indx, 1, psf) ; if (psf->error) return psf->error ; if (current > 0) psf_fseek (psf, current, SEEK_SET) ; return psf->error ; } /* nist_write_header */
static int caf_write_header (SF_PRIVATE *psf, int calc_length) { BUF_UNION ubuf ; CAF_PRIVATE *pcaf ; DESC_CHUNK desc ; sf_count_t current, free_len ; uint32_t uk ; int subformat, append_free_block = SF_TRUE ; if ((pcaf = psf->container_data) == NULL) return SFE_INTERNAL ; memset (&desc, 0, sizeof (desc)) ; current = psf_ftell (psf) ; if (calc_length) { psf->filelength = psf_get_filelen (psf) ; psf->datalength = psf->filelength - psf->dataoffset ; if (psf->dataend) psf->datalength -= psf->filelength - psf->dataend ; if (psf->bytewidth > 0) psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; } ; /* Reset the current header length to zero. */ psf->header [0] = 0 ; psf->headindex = 0 ; psf_fseek (psf, 0, SEEK_SET) ; /* 'caff' marker, version and flags. */ psf_binheader_writef (psf, "Em22", caff_MARKER, 1, 0) ; /* 'desc' marker and chunk size. */ psf_binheader_writef (psf, "Em8", desc_MARKER, (sf_count_t) (sizeof (DESC_CHUNK))) ; double64_be_write (1.0 * psf->sf.samplerate, ubuf.ucbuf) ; psf_binheader_writef (psf, "b", ubuf.ucbuf, make_size_t (8)) ; subformat = SF_CODEC (psf->sf.format) ; psf->endian = SF_ENDIAN (psf->sf.format) ; if (CPU_IS_BIG_ENDIAN && (psf->endian == 0 || psf->endian == SF_ENDIAN_CPU)) psf->endian = SF_ENDIAN_BIG ; else if (CPU_IS_LITTLE_ENDIAN && (psf->endian == SF_ENDIAN_LITTLE || psf->endian == SF_ENDIAN_CPU)) psf->endian = SF_ENDIAN_LITTLE ; if (psf->endian == SF_ENDIAN_LITTLE) desc.fmt_flags = 2 ; else psf->endian = SF_ENDIAN_BIG ; /* initial section (same for all, it appears) */ switch (subformat) { case SF_FORMAT_PCM_S8 : desc.fmt_id = lpcm_MARKER ; psf->bytewidth = 1 ; desc.pkt_bytes = psf->bytewidth * psf->sf.channels ; desc.frames_per_packet = 1 ; desc.channels_per_frame = psf->sf.channels ; desc.bits_per_chan = 8 ; break ; case SF_FORMAT_PCM_16 : desc.fmt_id = lpcm_MARKER ; psf->bytewidth = 2 ; desc.pkt_bytes = psf->bytewidth * psf->sf.channels ; desc.frames_per_packet = 1 ; desc.channels_per_frame = psf->sf.channels ; desc.bits_per_chan = 16 ; break ; case SF_FORMAT_PCM_24 : psf->bytewidth = 3 ; desc.pkt_bytes = psf->bytewidth * psf->sf.channels ; desc.frames_per_packet = 1 ; desc.channels_per_frame = psf->sf.channels ; desc.bits_per_chan = 24 ; desc.fmt_id = lpcm_MARKER ; break ; case SF_FORMAT_PCM_32 : desc.fmt_id = lpcm_MARKER ; psf->bytewidth = 4 ; desc.pkt_bytes = psf->bytewidth * psf->sf.channels ; desc.frames_per_packet = 1 ; desc.channels_per_frame = psf->sf.channels ; desc.bits_per_chan = 32 ; break ; case SF_FORMAT_FLOAT : desc.fmt_id = lpcm_MARKER ; desc.fmt_flags |= 1 ; psf->bytewidth = 4 ; desc.pkt_bytes = psf->bytewidth * psf->sf.channels ; desc.frames_per_packet = 1 ; desc.channels_per_frame = psf->sf.channels ; desc.bits_per_chan = 32 ; break ; case SF_FORMAT_DOUBLE : desc.fmt_id = lpcm_MARKER ; desc.fmt_flags |= 1 ; psf->bytewidth = 8 ; desc.pkt_bytes = psf->bytewidth * psf->sf.channels ; desc.frames_per_packet = 1 ; desc.channels_per_frame = psf->sf.channels ; desc.bits_per_chan = 64 ; break ; case SF_FORMAT_ALAW : desc.fmt_id = alaw_MARKER ; psf->bytewidth = 1 ; desc.pkt_bytes = psf->bytewidth * psf->sf.channels ; desc.frames_per_packet = 1 ; desc.channels_per_frame = psf->sf.channels ; desc.bits_per_chan = 8 ; break ; case SF_FORMAT_ULAW : desc.fmt_id = ulaw_MARKER ; psf->bytewidth = 1 ; desc.pkt_bytes = psf->bytewidth * psf->sf.channels ; desc.frames_per_packet = 1 ; desc.channels_per_frame = psf->sf.channels ; desc.bits_per_chan = 8 ; break ; case SF_FORMAT_ALAC_16 : case SF_FORMAT_ALAC_20 : case SF_FORMAT_ALAC_24 : case SF_FORMAT_ALAC_32 : desc.fmt_id = alac_MARKER ; desc.pkt_bytes = psf->bytewidth * psf->sf.channels ; desc.channels_per_frame = psf->sf.channels ; alac_get_desc_chunk_items (subformat, &desc.fmt_flags, &desc.frames_per_packet) ; append_free_block = SF_FALSE ; break ; default : return SFE_UNIMPLEMENTED ; } ; psf_binheader_writef (psf, "mE44444", desc.fmt_id, desc.fmt_flags, desc.pkt_bytes, desc.frames_per_packet, desc.channels_per_frame, desc.bits_per_chan) ; caf_write_strings (psf, SF_STR_LOCATE_START) ; if (psf->peak_info != NULL) { int k ; psf_binheader_writef (psf, "Em84", peak_MARKER, (sf_count_t) CAF_PEAK_CHUNK_SIZE (psf->sf.channels), psf->peak_info->edit_number) ; for (k = 0 ; k < psf->sf.channels ; k++) psf_binheader_writef (psf, "Ef8", (float) psf->peak_info->peaks [k].value, psf->peak_info->peaks [k].position) ; } ; if (psf->channel_map && pcaf->chanmap_tag) psf_binheader_writef (psf, "Em8444", chan_MARKER, (sf_count_t) 12, pcaf->chanmap_tag, 0, 0) ; /* Write custom headers. */ for (uk = 0 ; uk < psf->wchunks.used ; uk++) psf_binheader_writef (psf, "m44b", (int) psf->wchunks.chunks [uk].mark32, 0, psf->wchunks.chunks [uk].len, psf->wchunks.chunks [uk].data, make_size_t (psf->wchunks.chunks [uk].len)) ; if (append_free_block) { /* Add free chunk so that the actual audio data starts at a multiple 0x1000. */ free_len = 0x1000 - psf->headindex - 16 - 12 ; while (free_len < 0) free_len += 0x1000 ; psf_binheader_writef (psf, "Em8z", free_MARKER, free_len, (int) free_len) ; } ; psf_binheader_writef (psf, "Em84", data_MARKER, psf->datalength + 4, 0) ; 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 ; } /* caf_write_header */