|
@@ -0,0 +1,259 @@
|
|
|
|
|
+/* Copyright (c) 2009, 2014 Richard Dobson
|
|
|
|
|
+
|
|
|
|
|
+Permission is hereby granted, free of charge, to any person
|
|
|
|
|
+obtaining a copy of this software and associated documentation
|
|
|
|
|
+files (the "Software"), to deal in the Software without
|
|
|
|
|
+restriction, including without limitation the rights to use,
|
|
|
|
|
+copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
|
+copies of the Software, and to permit persons to whom the
|
|
|
|
|
+Software is furnished to do so, subject to the following
|
|
|
|
|
+conditions:
|
|
|
|
|
+
|
|
|
|
|
+The above copyright notice and this permission notice shall be
|
|
|
|
|
+included in all copies or substantial portions of the Software.
|
|
|
|
|
+
|
|
|
|
|
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
|
|
|
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
|
|
|
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
|
|
|
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
|
|
|
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
|
|
|
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
|
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
|
|
|
+OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
|
+*/
|
|
|
|
|
+
|
|
|
|
|
+/* POST_BOOK!*/
|
|
|
|
|
+/* RWD Oct 2009: added MC_CUBE to listy of supported speaker layouts */
|
|
|
|
|
+/* corrected 7.1 speaker value (hex) */
|
|
|
|
|
+/* Aug 2012 corrected SPKRS_MONO value */
|
|
|
|
|
+/* Nov 2013: added SPKRS_6_1 and MC_SURR_6_1 to list */
|
|
|
|
|
+
|
|
|
|
|
+#ifndef __RIFFWAV_H_INCLUDED
|
|
|
|
|
+#define __RIFFWAV_H_INCLUDED
|
|
|
|
|
+
|
|
|
|
|
+/* Revision 16th September 2003: added TPDF dither support */
|
|
|
|
|
+/* revision Dec 2005: support new B-Format extensions */
|
|
|
|
|
+/* RWD Nov 1 2006: extended with double sread/write for research purposes! */
|
|
|
|
|
+/* July 2009: attempt portability with 64bit platforms */
|
|
|
|
|
+/* unable to test Win64 yet - but the symbol to check is simply _WIN64 */
|
|
|
|
|
+#ifdef __GNUC__
|
|
|
|
|
+# ifdef __LP64__
|
|
|
|
|
+# define CPLONG64
|
|
|
|
|
+# endif
|
|
|
|
|
+#endif
|
|
|
|
|
+/* failing that, manually define CPLONG64 in makefile or project setting */
|
|
|
|
|
+#ifdef CPLONG64
|
|
|
|
|
+// all this effort is for readPeaks() and ctime only!
|
|
|
|
|
+# define MYLONG int
|
|
|
|
|
+#else
|
|
|
|
|
+# define MYLONG long
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+#ifdef __cplusplus
|
|
|
|
|
+extern "C" {
|
|
|
|
|
+#endif
|
|
|
|
|
+/* compatible with <windows.h> */
|
|
|
|
|
+typedef unsigned MYLONG DWORD;
|
|
|
|
|
+typedef unsigned short WORD;
|
|
|
|
|
+
|
|
|
|
|
+/* NB: AIFF spec always illustrates chunksize as (signed) long;
|
|
|
|
|
+ even though nFrames is always unsigned long!
|
|
|
|
|
+ So we make everything DWORD here.
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+/* the file sample formats we could support */
|
|
|
|
|
+
|
|
|
|
|
+typedef enum {
|
|
|
|
|
+ PSF_SAMP_UNKNOWN = 0,
|
|
|
|
|
+ PSF_SAMP_8, /* not yet supported! */
|
|
|
|
|
+ PSF_SAMP_16,
|
|
|
|
|
+ PSF_SAMP_24,
|
|
|
|
|
+ PSF_SAMP_32,
|
|
|
|
|
+ PSF_SAMP_IEEE_FLOAT
|
|
|
|
|
+} psf_stype;
|
|
|
|
|
+
|
|
|
|
|
+/* the file format */
|
|
|
|
|
+/* currently based only on file extension.
|
|
|
|
|
+ To be friendly, we should parse the header to get the format.
|
|
|
|
|
+*/
|
|
|
|
|
+typedef enum {
|
|
|
|
|
+ PSF_FMT_UNKNOWN = 0, /* e.g if no extension given. This could also signify 'raw' */
|
|
|
|
|
+ PSF_STDWAVE,
|
|
|
|
|
+ PSF_WAVE_EX,
|
|
|
|
|
+ PSF_AIFF,
|
|
|
|
|
+ PSF_AIFC
|
|
|
|
|
+} psf_format;
|
|
|
|
|
+
|
|
|
|
|
+/* provisional stab at error codes */
|
|
|
|
|
+enum {
|
|
|
|
|
+ PSF_E_NOERROR = 0,
|
|
|
|
|
+ PSF_E_CANT_OPEN = -1,
|
|
|
|
|
+ PSF_E_CANT_CLOSE = -2,
|
|
|
|
|
+ PSF_E_CANT_WRITE = -3,
|
|
|
|
|
+ PSF_E_CANT_READ = -4,
|
|
|
|
|
+ PSF_E_NOT_WAVE = -5,
|
|
|
|
|
+ PSF_E_BAD_TYPE = -6,
|
|
|
|
|
+ PSF_E_BAD_FORMAT = -7,
|
|
|
|
|
+ PSF_E_UNSUPPORTED = -8,
|
|
|
|
|
+ PSF_E_NOMEM = -9,
|
|
|
|
|
+ PSF_E_BADARG = -10,
|
|
|
|
|
+ PSF_E_CANT_SEEK = -11,
|
|
|
|
|
+ PSF_E_TOOMANYFILES = -12,
|
|
|
|
|
+ PSF_E_FILE_READONLY = -13,
|
|
|
|
|
+ PSF_E_SEEK_BEYOND_EOF = -14
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+#define NUM_SPEAKER_POSITIONS (18)
|
|
|
|
|
+
|
|
|
|
|
+#define SPEAKER_FRONT_LEFT 0x1
|
|
|
|
|
+#define SPEAKER_FRONT_RIGHT 0x2
|
|
|
|
|
+#define SPEAKER_FRONT_CENTER 0x4
|
|
|
|
|
+#define SPEAKER_LOW_FREQUENCY 0x8
|
|
|
|
|
+#define SPEAKER_BACK_LEFT 0x10
|
|
|
|
|
+#define SPEAKER_BACK_RIGHT 0x20
|
|
|
|
|
+#define SPEAKER_FRONT_LEFT_OF_CENTER 0x40
|
|
|
|
|
+#define SPEAKER_FRONT_RIGHT_OF_CENTER 0x80
|
|
|
|
|
+#define SPEAKER_BACK_CENTER 0x100
|
|
|
|
|
+#define SPEAKER_SIDE_LEFT 0x200
|
|
|
|
|
+#define SPEAKER_SIDE_RIGHT 0x400
|
|
|
|
|
+#define SPEAKER_TOP_CENTER 0x800
|
|
|
|
|
+#define SPEAKER_TOP_FRONT_LEFT 0x1000
|
|
|
|
|
+#define SPEAKER_TOP_FRONT_CENTER 0x2000
|
|
|
|
|
+#define SPEAKER_TOP_FRONT_RIGHT 0x4000
|
|
|
|
|
+#define SPEAKER_TOP_BACK_LEFT 0x8000
|
|
|
|
|
+#define SPEAKER_TOP_BACK_CENTER 0x10000
|
|
|
|
|
+#define SPEAKER_TOP_BACK_RIGHT 0x20000
|
|
|
|
|
+/* RWD 2022 use latest version from MS */
|
|
|
|
|
+#define SPEAKER_RESERVED 0x7FFC0000
|
|
|
|
|
+#define SPEAKER_ALL 0x80000000
|
|
|
|
|
+
|
|
|
|
|
+/* my extras*/
|
|
|
|
|
+#define SPKRS_UNASSIGNED (0)
|
|
|
|
|
+#define SPKRS_MONO (0x00000004)
|
|
|
|
|
+#define SPKRS_STEREO (0x00000003)
|
|
|
|
|
+#define SPKRS_GENERIC_QUAD (0x00000033)
|
|
|
|
|
+#define SPKRS_SURROUND_LCRS (0x00000107)
|
|
|
|
|
+#define SPKRS_SURR_5_0 (0x00000037)
|
|
|
|
|
+#define SPKRS_DOLBY5_1 (0x0000003f)
|
|
|
|
|
+#define SPKRS_6_1 (0x0000013f)
|
|
|
|
|
+#define SPKRS_7_1 (0x000000ff)
|
|
|
|
|
+#define SPKRS_CUBE (SPKRS_GENERIC_QUAD | SPEAKER_TOP_FRONT_LEFT | SPEAKER_TOP_FRONT_RIGHT | SPEAKER_TOP_BACK_LEFT | SPEAKER_TOP_BACK_RIGHT)
|
|
|
|
|
+#define SPKRS_ACCEPT_ALL (0xffffffff) /*???? no use for a file*/
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+/* support for the PEAK chunk */
|
|
|
|
|
+typedef struct psf_chpeak {
|
|
|
|
|
+ float val;
|
|
|
|
|
+ DWORD pos; /* OK for all WAVE and AIFF <= 4GB */
|
|
|
|
|
+} PSF_CHPEAK;
|
|
|
|
|
+
|
|
|
|
|
+/* second two are speculative at present! */
|
|
|
|
|
+typedef enum {PSF_CREATE_RDWR,PSF_CREATE_TEMPORARY,PSF_CREATE_WRONLY} psf_create_mode;
|
|
|
|
|
+/* the speakerfeed format */
|
|
|
|
|
+/* MC_WAVE_EX is a possibly temporary one to cover abstruse infile formats! */
|
|
|
|
|
+typedef enum { STDWAVE,MC_STD,MC_MONO,MC_STEREO,MC_QUAD,MC_LCRS,MC_BFMT,MC_DOLBY_5_1,
|
|
|
|
|
+ MC_SURR_5_0,MC_SURR_6_1,MC_SURR_7_1,MC_CUBE,MC_WAVE_EX } psf_channelformat;
|
|
|
|
|
+
|
|
|
|
|
+/* read access support */
|
|
|
|
|
+/* for psf_sndSeek(); ~should~ map directly to fseek mode flags*/
|
|
|
|
|
+enum { PSF_SEEK_SET=0,PSF_SEEK_CUR,PSF_SEEK_END};
|
|
|
|
|
+
|
|
|
|
|
+enum {PSF_DITHER_OFF,PSF_DITHER_TPDF};
|
|
|
|
|
+
|
|
|
|
|
+/* main structure to define a soundile. Extended props must be asked for separately */
|
|
|
|
|
+typedef struct psf_props
|
|
|
|
|
+{
|
|
|
|
|
+ int srate;
|
|
|
|
|
+ int chans;
|
|
|
|
|
+ psf_stype samptype;
|
|
|
|
|
+ psf_format format;
|
|
|
|
|
+ psf_channelformat chformat;
|
|
|
|
|
+ /* probably add more stuff...esp for full WAVE-EX support */
|
|
|
|
|
+} PSF_PROPS;
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+/*************** PUBLIC FUNCS */
|
|
|
|
|
+
|
|
|
|
|
+/* init sfs system. return 0 for success */
|
|
|
|
|
+int psf_init(void);
|
|
|
|
|
+/* close sfs-system. Does auto cleanup of open files, etc. return 0 for success */
|
|
|
|
|
+int psf_finish(void);
|
|
|
|
|
+/* Create soundfile from props.
|
|
|
|
|
+ Supports clipping or non-clipping of floats to 0dbFS,
|
|
|
|
|
+ set minimum header (or use PEAK)
|
|
|
|
|
+ returns Sf descriptor >= 0, or some PSF_E_* on error.
|
|
|
|
|
+*/
|
|
|
|
|
+/* using WIN32, it is possible to share for reading, but not under ANSI */
|
|
|
|
|
+/* maybe we just abandon all that */
|
|
|
|
|
+/* TODO (?): enforce non-destructive creation */
|
|
|
|
|
+int psf_sndCreate(const char *path,const PSF_PROPS *props, int clip_floats,int minheader,int mode);
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+/* open existing soundfile. Receive format info in props. Supports auto rescale from PEAK
|
|
|
|
|
+ data, with floats files. Only RDONLY access supported.
|
|
|
|
|
+ Return sf descriptor >= 0, or some PSF_E_+ on error.
|
|
|
|
|
+ */
|
|
|
|
|
+int psf_sndOpen(const char *path,PSF_PROPS *props, int rescale);
|
|
|
|
|
+/*snd close. Updates PEAK data if used. return 0 for success, or some PSF_E_+ on error.*/
|
|
|
|
|
+int psf_sndClose(int sfd);
|
|
|
|
|
+
|
|
|
|
|
+/* all data read/write is counted in multi-channel sample 'frames', NOT in raw samples.*/
|
|
|
|
|
+
|
|
|
|
|
+/* get size of file, in m/c frames. Return size, or PSF_E_BADARG on bad sfd */
|
|
|
|
|
+int psf_sndSize(int sfd);
|
|
|
|
|
+
|
|
|
|
|
+/* write m/c frames of floats. this updates internal PEAK data automatically.
|
|
|
|
|
+ return num frames written, or some PSF_E_* on error.
|
|
|
|
|
+ */
|
|
|
|
|
+int psf_sndWriteFloatFrames(int sfd, const float *buf, DWORD nFrames);
|
|
|
|
|
+int psf_sndWriteDoubleFrames(int sfd, const double *buf, DWORD nFrames);
|
|
|
|
|
+/* as above, with 16bit data */
|
|
|
|
|
+int psf_sndWriteShortFrames(int sfd, const short *buf, DWORD nFrames);
|
|
|
|
|
+
|
|
|
|
|
+/* get current m/c frame position in file, or PSF_E_BADARG with bad sfd*/
|
|
|
|
|
+int psf_sndTell(int sfd);
|
|
|
|
|
+
|
|
|
|
|
+/* m/c frame wrapper for stdio fseek. return 0 for success. Offset counted in m/c frames.
|
|
|
|
|
+ seekmode must be one of PSF_SEEK_* options, to ensure correct mapping to SEEK_CUR, etc */
|
|
|
|
|
+int psf_sndSeek(int sfd,int offset,int seekmode);
|
|
|
|
|
+
|
|
|
|
|
+/* read m/c sample frames into floats buffer. return nFrames, or some PSF_E_*.
|
|
|
|
|
+ if file opened with rescale = 1, over-range floats data, as indicated by PEAK chunk,
|
|
|
|
|
+ is automatically scaled to 0dbFS.
|
|
|
|
|
+ NB we could add a facility to define 'headroom', as some level below 0dBFS.
|
|
|
|
|
+ */
|
|
|
|
|
+int psf_sndReadFloatFrames(int sfd, float *buf, DWORD nFrames);
|
|
|
|
|
+int psf_sndReadDoubleFrames(int sfd, double *buf, DWORD nFrames);
|
|
|
|
|
+/* can add ReadShortFrames if we really need it! */
|
|
|
|
|
+
|
|
|
|
|
+int psf_sndReadPeaks(int sfd,PSF_CHPEAK peakdata[],MYLONG *peaktime);
|
|
|
|
|
+
|
|
|
|
|
+/* find the soundfile format from the filename extension */
|
|
|
|
|
+/* currently supported: .wav, .aif, .aiff,.aifc,.afc, .amb */
|
|
|
|
|
+psf_format psf_getFormatExt(const char *path);
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+/* set/unset dither.
|
|
|
|
|
+ Returns 0 on success, -1 if error (unrecognised type, or read-only)
|
|
|
|
|
+ no-op for input files
|
|
|
|
|
+*/
|
|
|
|
|
+
|
|
|
|
|
+int psf_sndSetDither(int sfd,unsigned int dtype);
|
|
|
|
|
+/* get current dither setting */
|
|
|
|
|
+int psf_sndGetDither(int sfd);
|
|
|
|
|
+
|
|
|
|
|
+/* RWD NEW Nov 2009 */
|
|
|
|
|
+int psf_speakermask(int sfd);
|
|
|
|
|
+
|
|
|
|
|
+/* Feb 2010 */
|
|
|
|
|
+int psf_getWarning(int sfd,const char** warnstring);
|
|
|
|
|
+
|
|
|
|
|
+/* Sept 2010 return 1 for true, 0 for false */
|
|
|
|
|
+ /* NB tests up to 32bit size for now! */
|
|
|
|
|
+int is_legalsize(unsigned long nFrames, const PSF_PROPS *props);
|
|
|
|
|
+
|
|
|
|
|
+#ifdef __cplusplus
|
|
|
|
|
+}
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+#endif
|