📄 sd2.c
字号:
/*** Copyright (C) 2001-2004 Erik de Castro Lopo <erikd@mega-nerd.com>** Copyright (C) 2004 Paavo Jumppanen**** 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.*//*** The sd2 support implemented in this file was partially sponsored** (financially) by Paavo Jumppanen.*//*** Documentation on the Mac resource fork was obtained here :** http://developer.apple.com/documentation/mac/MoreToolbox/MoreToolbox-99.html*/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include "sndfile.h"#include "config.h"#include "sfendian.h"#include "common.h"/*------------------------------------------------------------------------------ * Markers.*/#define Sd2f_MARKER MAKE_MARKER ('S', 'd', '2', 'f')#define Sd2a_MARKER MAKE_MARKER ('S', 'd', '2', 'a')#define ALCH_MARKER MAKE_MARKER ('A', 'L', 'C', 'H')#define lsf1_MARKER MAKE_MARKER ('l', 's', 'f', '1')#define STR_MARKER MAKE_MARKER ('S', 'T', 'R', ' ')#define sdML_MARKER MAKE_MARKER ('s', 'd', 'M', 'L')enum{ RSRC_STR = 111, RSRC_BIN} ;typedef struct{ unsigned char * rsrc_data ; int rsrc_len ; int data_offset, data_length ; int map_offset, map_length ; int type_count, type_offset ; int item_offset ; int str_index, str_count ; int string_offset ; /* All the above just to get these three. */ int sample_size, sample_rate, channels ;} SD2_RSRC ;typedef struct{ int type ; int id ; char name [32] ; char value [32] ; int value_len ;} STR_RSRC ;/*------------------------------------------------------------------------------ * Private static functions.*/static int sd2_close (SF_PRIVATE *psf) ;static int sd2_parse_rsrc_fork (SF_PRIVATE *psf) ;static int parse_str_rsrc (SF_PRIVATE *psf, SD2_RSRC * rsrc) ;static int sd2_write_rsrc_fork (SF_PRIVATE *psf, int calc_length) ;/*------------------------------------------------------------------------------** Public functions.*/intsd2_open (SF_PRIVATE *psf){ int saved_filedes, subformat, error = 0 ; /* SD2 is always big endian. */ psf->endian = SF_ENDIAN_BIG ; if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->rsrclength > 0)) { if (psf->rsrcdes < 0) { psf_log_printf (psf, "sd2_open : psf->rsrcdes < 0\n") ; return SFE_SD2_BAD_RSRC ; } ; saved_filedes = psf->filedes ; psf->filedes = psf->rsrcdes ; error = sd2_parse_rsrc_fork (psf) ; psf->filedes = saved_filedes ; if (error) goto error_cleanup ; } ; if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_SD2) { error = SFE_BAD_OPEN_FORMAT ; goto error_cleanup ; } ; subformat = psf->sf.format & SF_FORMAT_SUBMASK ; psf->dataoffset = 0 ; /* Only open and write the resource in RDWR mode is its current length is zero. */ if (psf->mode == SFM_WRITE || (psf->mode == SFM_RDWR && psf->rsrclength == 0)) { psf_open_rsrc (psf, psf->mode) ; saved_filedes = psf->filedes ; psf->filedes = psf->rsrcdes ; error = sd2_write_rsrc_fork (psf, SF_FALSE) ; psf->filedes = saved_filedes ; if (error) goto error_cleanup ; /* Not needed. */ psf->write_header = NULL ; } ; psf->close = sd2_close ; psf->blockwidth = psf->bytewidth * psf->sf.channels ; switch (subformat) { case SF_FORMAT_PCM_S8 : /* 8-bit linear PCM. */ case SF_FORMAT_PCM_16 : /* 16-bit linear PCM. */ case SF_FORMAT_PCM_24 : /* 24-bit linear PCM */ error = pcm_init (psf) ; break ; default : error = SFE_UNIMPLEMENTED ; break ; } ; psf_fseek (psf, psf->dataoffset, SEEK_SET) ;error_cleanup: /* Close the resource fork regardless. We won't need it again. */ psf_close_rsrc (psf) ; return error ;} /* sd2_open *//*------------------------------------------------------------------------------*/static intsd2_close (SF_PRIVATE *psf){ if (psf->mode == SFM_WRITE) { /* Now we know for certain the audio_length of the file we can re-write ** correct values for the FORM, 8SVX and BODY chunks. */ } ; return 0 ;} /* sd2_close *//*------------------------------------------------------------------------------*/static inline voidwrite_char (unsigned char * data, int offset, char value){ data [offset] = value ;} /* write_char */static inline voidwrite_short (unsigned char * data, int offset, short value){ data [offset] = value >> 8 ; data [offset + 1] = value ;} /* write_char */static inline voidwrite_int (unsigned char * data, int offset, int value){ data [offset] = value >> 24 ; data [offset + 1] = value >> 16 ; data [offset + 2] = value >> 8 ; data [offset + 3] = value ;} /* write_int */static voidwrite_str (unsigned char * data, int offset, char * buffer, int buffer_len){ memcpy (data + offset, buffer, buffer_len) ;} /* write_str */static intsd2_write_rsrc_fork (SF_PRIVATE *psf, int UNUSED (calc_length)){ SD2_RSRC rsrc ; STR_RSRC str_rsrc [] = { { RSRC_STR, 1000, "_sample-size", "", 0 }, { RSRC_STR, 1001, "_sample-rate", "", 0 }, { RSRC_STR, 1002, "_channels", "", 0 }, { RSRC_BIN, 1000, "_Markers", "", 8 } } ; int k, str_offset, data_offset, next_str ; memset (&rsrc, 0, sizeof (rsrc)) ; rsrc.sample_rate = psf->sf.samplerate ; rsrc.sample_size = psf->bytewidth ; rsrc.channels = psf->sf.channels ; rsrc.rsrc_data = psf->header ; rsrc.rsrc_len = sizeof (psf->header) ; memset (rsrc.rsrc_data, 0xea, rsrc.rsrc_len) ; LSF_SNPRINTF (str_rsrc [0].value, sizeof (str_rsrc [0].value), "_%d", rsrc.sample_size) ; LSF_SNPRINTF (str_rsrc [1].value, sizeof (str_rsrc [1].value), "_%d.000000", rsrc.sample_rate) ; LSF_SNPRINTF (str_rsrc [2].value, sizeof (str_rsrc [2].value), "_%d", rsrc.channels) ; for (k = 0 ; k < ARRAY_LEN (str_rsrc) ; k++) { if (str_rsrc [k].value_len == 0) { str_rsrc [k].value_len = strlen (str_rsrc [k].value) ; str_rsrc [k].value [0] = str_rsrc [k].value_len - 1 ; } ; /* Turn name string into a pascal string. */ str_rsrc [k].name [0] = strlen (str_rsrc [k].name) - 1 ; } ; rsrc.data_offset = 0x100 ; /* ** Calculate data length : ** length of strings, plus the length of the sdML chunk. */ rsrc.data_length = 0 ; for (k = 0 ; k < ARRAY_LEN (str_rsrc) ; k++) rsrc.data_length += str_rsrc [k].value_len + 4 ; rsrc.map_offset = rsrc.data_offset + rsrc.data_length ; /* Very start of resource fork. */ write_int (rsrc.rsrc_data, 0, rsrc.data_offset) ; write_int (rsrc.rsrc_data, 4, rsrc.map_offset) ; write_int (rsrc.rsrc_data, 8, rsrc.data_length) ; write_char (rsrc.rsrc_data, 0x30, strlen (psf->filename)) ; write_str (rsrc.rsrc_data, 0x31, psf->filename, strlen (psf->filename)) ; write_short (rsrc.rsrc_data, 0x50, 0) ; write_int (rsrc.rsrc_data, 0x52, Sd2f_MARKER) ; write_int (rsrc.rsrc_data, 0x56, lsf1_MARKER) ; /* Very start of resource map. */ write_int (rsrc.rsrc_data, rsrc.map_offset + 0, rsrc.data_offset) ; write_int (rsrc.rsrc_data, rsrc.map_offset + 4, rsrc.map_offset) ; write_int (rsrc.rsrc_data, rsrc.map_offset + 8, rsrc.data_length) ; /* These I don't currently understand. */ if (1) { write_char (rsrc.rsrc_data, rsrc.map_offset+ 16, 1) ; /* Next resource map. */ write_int (rsrc.rsrc_data, rsrc.map_offset + 17, 0x12345678) ; /* File ref number. */ write_short (rsrc.rsrc_data, rsrc.map_offset + 21, 0xabcd) ; /* Fork attributes. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -