1/* 2** Copyright (C) 2002-2012 Erik de Castro Lopo <erikd@mega-nerd.com> 3** 4** This program is free software; you can redistribute it and/or modify 5** it under the terms of the GNU Lesser General Public License as published by 6** the Free Software Foundation; either version 2.1 of the License, or 7** (at your option) any later version. 8** 9** This program is distributed in the hope that it will be useful, 10** but WITHOUT ANY WARRANTY; without even the implied warranty of 11** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12** GNU Lesser General Public License for more details. 13** 14** You should have received a copy of the GNU Lesser General Public License 15** along with this program; if not, write to the Free Software 16** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17*/ 18 19#include "sfconfig.h" 20 21#include <stdio.h> 22#include <fcntl.h> 23#include <string.h> 24#include <ctype.h> 25 26#include "sndfile.h" 27#include "sfendian.h" 28#include "common.h" 29 30#if (ENABLE_EXPERIMENTAL_CODE == 0) 31 32int 33dwd_open (SF_PRIVATE *psf) 34{ if (psf) 35 return SFE_UNIMPLEMENTED ; 36 return 0 ; 37} /* dwd_open */ 38 39#else 40 41/*------------------------------------------------------------------------------ 42** Macros to handle big/little endian issues. 43*/ 44 45#define SFE_DWD_NO_DWD 1666 46#define SFE_DWD_BAND_BIT_WIDTH 1667 47#define SFE_DWD_COMPRESSION 1668 48 49#define DWD_IDENTIFIER "DiamondWare Digitized\n\0\x1a" 50#define DWD_IDENTIFIER_LEN 24 51 52#define DWD_HEADER_LEN 57 53 54/*------------------------------------------------------------------------------ 55** Typedefs. 56*/ 57 58/*------------------------------------------------------------------------------ 59** Private static functions. 60*/ 61 62static int dwd_read_header (SF_PRIVATE *psf) ; 63 64static int dwd_close (SF_PRIVATE *psf) ; 65 66/*------------------------------------------------------------------------------ 67** Public function. 68*/ 69 70int 71dwd_open (SF_PRIVATE *psf) 72{ int error = 0 ; 73 74 if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0)) 75 { if ((error = dwd_read_header (psf))) 76 return error ; 77 } ; 78 79 if ((SF_CONTAINER (psf->sf.format)) != SF_FORMAT_DWD) 80 return SFE_BAD_OPEN_FORMAT ; 81 82 if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR) 83 { 84 /*-psf->endian = SF_ENDIAN (psf->sf.format) ; 85 if (CPU_IS_LITTLE_ENDIAN && psf->endian == SF_ENDIAN_CPU) 86 psf->endian = SF_ENDIAN_LITTLE ; 87 else if (psf->endian != SF_ENDIAN_LITTLE) 88 psf->endian = SF_ENDIAN_BIG ; 89 90 if (! (encoding = dwd_write_header (psf, SF_FALSE))) 91 return psf->error ; 92 93 psf->write_header = dwd_write_header ; 94 -*/ 95 } ; 96 97 psf->container_close = dwd_close ; 98 99 /*-psf->blockwidth = psf->bytewidth * psf->sf.channels ;-*/ 100 101 return error ; 102} /* dwd_open */ 103 104/*------------------------------------------------------------------------------ 105*/ 106 107static int 108dwd_close (SF_PRIVATE * UNUSED (psf)) 109{ 110 return 0 ; 111} /* dwd_close */ 112 113/* This struct contains all the fields of interest om the DWD header, but does not 114** do so in the same order and layout as the actual file, header. 115** No assumptions are made about the packing of this struct. 116*/ 117typedef struct 118{ uint8_t major, minor, compression, channels, bitwidth ; 119 uint16_t srate, maxval ; 120 uint32_t id, datalen, frames, offset ; 121} DWD_HEADER ; 122 123static int 124dwd_read_header (SF_PRIVATE *psf) 125{ BUF_UNION ubuf ; 126 DWD_HEADER dwdh ; 127 128 memset (ubuf.cbuf, 0, sizeof (ubuf.cbuf)) ; 129 /* Set position to start of file to begin reading header. */ 130 psf_binheader_readf (psf, "pb", 0, ubuf.cbuf, DWD_IDENTIFIER_LEN) ; 131 132 if (memcmp (ubuf.cbuf, DWD_IDENTIFIER, DWD_IDENTIFIER_LEN) != 0) 133 return SFE_DWD_NO_DWD ; 134 135 psf_log_printf (psf, "Read only : DiamondWare Digitized (.dwd)\n", ubuf.cbuf) ; 136 137 psf_binheader_readf (psf, "11", &dwdh.major, &dwdh.minor) ; 138 psf_binheader_readf (psf, "e4j1", &dwdh.id, 1, &dwdh.compression) ; 139 psf_binheader_readf (psf, "e211", &dwdh.srate, &dwdh.channels, &dwdh.bitwidth) ; 140 psf_binheader_readf (psf, "e24", &dwdh.maxval, &dwdh.datalen) ; 141 psf_binheader_readf (psf, "e44", &dwdh.frames, &dwdh.offset) ; 142 143 psf_log_printf (psf, " Version Major : %d\n Version Minor : %d\n Unique ID : %08X\n", 144 dwdh.major, dwdh.minor, dwdh.id) ; 145 psf_log_printf (psf, " Compression : %d => ", dwdh.compression) ; 146 147 if (dwdh.compression != 0) 148 { psf_log_printf (psf, "Unsupported compression\n") ; 149 return SFE_DWD_COMPRESSION ; 150 } 151 else 152 psf_log_printf (psf, "None\n") ; 153 154 psf_log_printf (psf, " Sample Rate : %d\n Channels : %d\n" 155 " Bit Width : %d\n", 156 dwdh.srate, dwdh.channels, dwdh.bitwidth) ; 157 158 switch (dwdh.bitwidth) 159 { case 8 : 160 psf->sf.format = SF_FORMAT_DWD | SF_FORMAT_PCM_S8 ; 161 psf->bytewidth = 1 ; 162 break ; 163 164 case 16 : 165 psf->sf.format = SF_FORMAT_DWD | SF_FORMAT_PCM_16 ; 166 psf->bytewidth = 2 ; 167 break ; 168 169 default : 170 psf_log_printf (psf, "*** Bad bit width %d\n", dwdh.bitwidth) ; 171 return SFE_DWD_BAND_BIT_WIDTH ; 172 } ; 173 174 if (psf->filelength != dwdh.offset + dwdh.datalen) 175 { psf_log_printf (psf, " Data Length : %d (should be %D)\n", dwdh.datalen, psf->filelength - dwdh.offset) ; 176 dwdh.datalen = (uint32_t) (psf->filelength - dwdh.offset) ; 177 } 178 else 179 psf_log_printf (psf, " Data Length : %d\n", dwdh.datalen) ; 180 181 psf_log_printf (psf, " Max Value : %d\n", dwdh.maxval) ; 182 psf_log_printf (psf, " Frames : %d\n", dwdh.frames) ; 183 psf_log_printf (psf, " Data Offset : %d\n", dwdh.offset) ; 184 185 psf->datalength = dwdh.datalen ; 186 psf->dataoffset = dwdh.offset ; 187 188 psf->endian = SF_ENDIAN_LITTLE ; 189 190 psf->sf.samplerate = dwdh.srate ; 191 psf->sf.channels = dwdh.channels ; 192 psf->sf.sections = 1 ; 193 194 return pcm_init (psf) ; 195} /* dwd_read_header */ 196 197/*------------------------------------------------------------------------------ 198*/ 199 200#endif 201 202