Bug Summary

File:libs/libsndfile/src/wav.c
Location:line 1865, column 3
Description:Value stored to 'bytes' is never read

Annotated Source Code

1/*
2** Copyright (C) 1999-2013 Erik de Castro Lopo <erikd@mega-nerd.com>
3** Copyright (C) 2004-2005 David Viens <davidv@plogue.com>
4**
5** This program is free software; you can redistribute it and/or modify
6** it under the terms of the GNU Lesser General Public License as published by
7** the Free Software Foundation; either version 2.1 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU Lesser General Public License for more details.
14**
15** You should have received a copy of the GNU Lesser General Public License
16** along with this program; if not, write to the Free Software
17** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18*/
19
20#include "sfconfig.h"
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <ctype.h>
26#include <time.h>
27#ifdef HAVE_INTTYPES_H1
28#include <inttypes.h>
29#endif
30
31#include "sndfile.h"
32#include "sfendian.h"
33#include "common.h"
34#include "wav_w64.h"
35
36/*------------------------------------------------------------------------------
37 * Macros to handle big/little endian issues.
38 */
39
40#define RIFF_MARKER(((uint32_t) (('R') | (('I') << 8) | (('F') << 16
) | (((uint32_t) ('F')) << 24))))
(MAKE_MARKER ('R', 'I', 'F', 'F')((uint32_t) (('R') | (('I') << 8) | (('F') << 16)
| (((uint32_t) ('F')) << 24)))
)
41#define RIFX_MARKER(((uint32_t) (('R') | (('I') << 8) | (('F') << 16
) | (((uint32_t) ('X')) << 24))))
(MAKE_MARKER ('R', 'I', 'F', 'X')((uint32_t) (('R') | (('I') << 8) | (('F') << 16)
| (((uint32_t) ('X')) << 24)))
)
42#define WAVE_MARKER(((uint32_t) (('W') | (('A') << 8) | (('V') << 16
) | (((uint32_t) ('E')) << 24))))
(MAKE_MARKER ('W', 'A', 'V', 'E')((uint32_t) (('W') | (('A') << 8) | (('V') << 16)
| (((uint32_t) ('E')) << 24)))
)
43#define fmt_MARKER(((uint32_t) (('f') | (('m') << 8) | (('t') << 16
) | (((uint32_t) (' ')) << 24))))
(MAKE_MARKER ('f', 'm', 't', ' ')((uint32_t) (('f') | (('m') << 8) | (('t') << 16)
| (((uint32_t) (' ')) << 24)))
)
44#define data_MARKER(((uint32_t) (('d') | (('a') << 8) | (('t') << 16
) | (((uint32_t) ('a')) << 24))))
(MAKE_MARKER ('d', 'a', 't', 'a')((uint32_t) (('d') | (('a') << 8) | (('t') << 16)
| (((uint32_t) ('a')) << 24)))
)
45#define fact_MARKER(((uint32_t) (('f') | (('a') << 8) | (('c') << 16
) | (((uint32_t) ('t')) << 24))))
(MAKE_MARKER ('f', 'a', 'c', 't')((uint32_t) (('f') | (('a') << 8) | (('c') << 16)
| (((uint32_t) ('t')) << 24)))
)
46#define PEAK_MARKER(((uint32_t) (('P') | (('E') << 8) | (('A') << 16
) | (((uint32_t) ('K')) << 24))))
(MAKE_MARKER ('P', 'E', 'A', 'K')((uint32_t) (('P') | (('E') << 8) | (('A') << 16)
| (((uint32_t) ('K')) << 24)))
)
47
48#define cue_MARKER(((uint32_t) (('c') | (('u') << 8) | (('e') << 16
) | (((uint32_t) (' ')) << 24))))
(MAKE_MARKER ('c', 'u', 'e', ' ')((uint32_t) (('c') | (('u') << 8) | (('e') << 16)
| (((uint32_t) (' ')) << 24)))
)
49#define LIST_MARKER(((uint32_t) (('L') | (('I') << 8) | (('S') << 16
) | (((uint32_t) ('T')) << 24))))
(MAKE_MARKER ('L', 'I', 'S', 'T')((uint32_t) (('L') | (('I') << 8) | (('S') << 16)
| (((uint32_t) ('T')) << 24)))
)
50#define slnt_MARKER(((uint32_t) (('s') | (('l') << 8) | (('n') << 16
) | (((uint32_t) ('t')) << 24))))
(MAKE_MARKER ('s', 'l', 'n', 't')((uint32_t) (('s') | (('l') << 8) | (('n') << 16)
| (((uint32_t) ('t')) << 24)))
)
51#define wavl_MARKER(((uint32_t) (('w') | (('a') << 8) | (('v') << 16
) | (((uint32_t) ('l')) << 24))))
(MAKE_MARKER ('w', 'a', 'v', 'l')((uint32_t) (('w') | (('a') << 8) | (('v') << 16)
| (((uint32_t) ('l')) << 24)))
)
52#define INFO_MARKER(((uint32_t) (('I') | (('N') << 8) | (('F') << 16
) | (((uint32_t) ('O')) << 24))))
(MAKE_MARKER ('I', 'N', 'F', 'O')((uint32_t) (('I') | (('N') << 8) | (('F') << 16)
| (((uint32_t) ('O')) << 24)))
)
53#define plst_MARKER(((uint32_t) (('p') | (('l') << 8) | (('s') << 16
) | (((uint32_t) ('t')) << 24))))
(MAKE_MARKER ('p', 'l', 's', 't')((uint32_t) (('p') | (('l') << 8) | (('s') << 16)
| (((uint32_t) ('t')) << 24)))
)
54#define adtl_MARKER(((uint32_t) (('a') | (('d') << 8) | (('t') << 16
) | (((uint32_t) ('l')) << 24))))
(MAKE_MARKER ('a', 'd', 't', 'l')((uint32_t) (('a') | (('d') << 8) | (('t') << 16)
| (((uint32_t) ('l')) << 24)))
)
55#define labl_MARKER(((uint32_t) (('l') | (('a') << 8) | (('b') << 16
) | (((uint32_t) ('l')) << 24))))
(MAKE_MARKER ('l', 'a', 'b', 'l')((uint32_t) (('l') | (('a') << 8) | (('b') << 16)
| (((uint32_t) ('l')) << 24)))
)
56#define ltxt_MARKER(((uint32_t) (('l') | (('t') << 8) | (('x') << 16
) | (((uint32_t) ('t')) << 24))))
(MAKE_MARKER ('l', 't', 'x', 't')((uint32_t) (('l') | (('t') << 8) | (('x') << 16)
| (((uint32_t) ('t')) << 24)))
)
57#define note_MARKER(((uint32_t) (('n') | (('o') << 8) | (('t') << 16
) | (((uint32_t) ('e')) << 24))))
(MAKE_MARKER ('n', 'o', 't', 'e')((uint32_t) (('n') | (('o') << 8) | (('t') << 16)
| (((uint32_t) ('e')) << 24)))
)
58#define smpl_MARKER(((uint32_t) (('s') | (('m') << 8) | (('p') << 16
) | (((uint32_t) ('l')) << 24))))
(MAKE_MARKER ('s', 'm', 'p', 'l')((uint32_t) (('s') | (('m') << 8) | (('p') << 16)
| (((uint32_t) ('l')) << 24)))
)
59#define bext_MARKER(((uint32_t) (('b') | (('e') << 8) | (('x') << 16
) | (((uint32_t) ('t')) << 24))))
(MAKE_MARKER ('b', 'e', 'x', 't')((uint32_t) (('b') | (('e') << 8) | (('x') << 16)
| (((uint32_t) ('t')) << 24)))
)
60#define iXML_MARKER(((uint32_t) (('i') | (('X') << 8) | (('M') << 16
) | (((uint32_t) ('L')) << 24))))
(MAKE_MARKER ('i', 'X', 'M', 'L')((uint32_t) (('i') | (('X') << 8) | (('M') << 16)
| (((uint32_t) ('L')) << 24)))
)
61#define levl_MARKER(((uint32_t) (('l') | (('e') << 8) | (('v') << 16
) | (((uint32_t) ('l')) << 24))))
(MAKE_MARKER ('l', 'e', 'v', 'l')((uint32_t) (('l') | (('e') << 8) | (('v') << 16)
| (((uint32_t) ('l')) << 24)))
)
62#define MEXT_MARKER(((uint32_t) (('M') | (('E') << 8) | (('X') << 16
) | (((uint32_t) ('T')) << 24))))
(MAKE_MARKER ('M', 'E', 'X', 'T')((uint32_t) (('M') | (('E') << 8) | (('X') << 16)
| (((uint32_t) ('T')) << 24)))
)
63#define DISP_MARKER(((uint32_t) (('D') | (('I') << 8) | (('S') << 16
) | (((uint32_t) ('P')) << 24))))
(MAKE_MARKER ('D', 'I', 'S', 'P')((uint32_t) (('D') | (('I') << 8) | (('S') << 16)
| (((uint32_t) ('P')) << 24)))
)
64#define acid_MARKER(((uint32_t) (('a') | (('c') << 8) | (('i') << 16
) | (((uint32_t) ('d')) << 24))))
(MAKE_MARKER ('a', 'c', 'i', 'd')((uint32_t) (('a') | (('c') << 8) | (('i') << 16)
| (((uint32_t) ('d')) << 24)))
)
65#define strc_MARKER(((uint32_t) (('s') | (('t') << 8) | (('r') << 16
) | (((uint32_t) ('c')) << 24))))
(MAKE_MARKER ('s', 't', 'r', 'c')((uint32_t) (('s') | (('t') << 8) | (('r') << 16)
| (((uint32_t) ('c')) << 24)))
)
66#define PAD_MARKER(((uint32_t) (('P') | (('A') << 8) | (('D') << 16
) | (((uint32_t) (' ')) << 24))))
(MAKE_MARKER ('P', 'A', 'D', ' ')((uint32_t) (('P') | (('A') << 8) | (('D') << 16)
| (((uint32_t) (' ')) << 24)))
)
67#define afsp_MARKER(((uint32_t) (('a') | (('f') << 8) | (('s') << 16
) | (((uint32_t) ('p')) << 24))))
(MAKE_MARKER ('a', 'f', 's', 'p')((uint32_t) (('a') | (('f') << 8) | (('s') << 16)
| (((uint32_t) ('p')) << 24)))
)
68#define clm_MARKER(((uint32_t) (('c') | (('l') << 8) | (('m') << 16
) | (((uint32_t) (' ')) << 24))))
(MAKE_MARKER ('c', 'l', 'm', ' ')((uint32_t) (('c') | (('l') << 8) | (('m') << 16)
| (((uint32_t) (' ')) << 24)))
)
69#define elmo_MARKER(((uint32_t) (('e') | (('l') << 8) | (('m') << 16
) | (((uint32_t) ('o')) << 24))))
(MAKE_MARKER ('e', 'l', 'm', 'o')((uint32_t) (('e') | (('l') << 8) | (('m') << 16)
| (((uint32_t) ('o')) << 24)))
)
70#define cart_MARKER(((uint32_t) (('c') | (('a') << 8) | (('r') << 16
) | (((uint32_t) ('t')) << 24))))
(MAKE_MARKER ('c', 'a', 'r', 't')((uint32_t) (('c') | (('a') << 8) | (('r') << 16)
| (((uint32_t) ('t')) << 24)))
)
71#define FLLR_MARKER(((uint32_t) (('F') | (('L') << 8) | (('L') << 16
) | (((uint32_t) ('R')) << 24))))
(MAKE_MARKER ('F', 'L', 'L', 'R')((uint32_t) (('F') | (('L') << 8) | (('L') << 16)
| (((uint32_t) ('R')) << 24)))
)
72
73#define exif_MARKER(((uint32_t) (('e') | (('x') << 8) | (('i') << 16
) | (((uint32_t) ('f')) << 24))))
(MAKE_MARKER ('e', 'x', 'i', 'f')((uint32_t) (('e') | (('x') << 8) | (('i') << 16)
| (((uint32_t) ('f')) << 24)))
)
74#define ever_MARKER(((uint32_t) (('e') | (('v') << 8) | (('e') << 16
) | (((uint32_t) ('r')) << 24))))
(MAKE_MARKER ('e', 'v', 'e', 'r')((uint32_t) (('e') | (('v') << 8) | (('e') << 16)
| (((uint32_t) ('r')) << 24)))
)
75#define etim_MARKER(((uint32_t) (('e') | (('t') << 8) | (('i') << 16
) | (((uint32_t) ('m')) << 24))))
(MAKE_MARKER ('e', 't', 'i', 'm')((uint32_t) (('e') | (('t') << 8) | (('i') << 16)
| (((uint32_t) ('m')) << 24)))
)
76#define ecor_MARKER(((uint32_t) (('e') | (('c') << 8) | (('o') << 16
) | (((uint32_t) ('r')) << 24))))
(MAKE_MARKER ('e', 'c', 'o', 'r')((uint32_t) (('e') | (('c') << 8) | (('o') << 16)
| (((uint32_t) ('r')) << 24)))
)
77#define emdl_MARKER(((uint32_t) (('e') | (('m') << 8) | (('d') << 16
) | (((uint32_t) ('l')) << 24))))
(MAKE_MARKER ('e', 'm', 'd', 'l')((uint32_t) (('e') | (('m') << 8) | (('d') << 16)
| (((uint32_t) ('l')) << 24)))
)
78#define emnt_MARKER(((uint32_t) (('e') | (('m') << 8) | (('n') << 16
) | (((uint32_t) ('t')) << 24))))
(MAKE_MARKER ('e', 'm', 'n', 't')((uint32_t) (('e') | (('m') << 8) | (('n') << 16)
| (((uint32_t) ('t')) << 24)))
)
79#define erel_MARKER(((uint32_t) (('e') | (('r') << 8) | (('e') << 16
) | (((uint32_t) ('l')) << 24))))
(MAKE_MARKER ('e', 'r', 'e', 'l')((uint32_t) (('e') | (('r') << 8) | (('e') << 16)
| (((uint32_t) ('l')) << 24)))
)
80#define eucm_MARKER(((uint32_t) (('e') | (('u') << 8) | (('c') << 16
) | (((uint32_t) ('m')) << 24))))
(MAKE_MARKER ('e', 'u', 'c', 'm')((uint32_t) (('e') | (('u') << 8) | (('c') << 16)
| (((uint32_t) ('m')) << 24)))
)
81#define olym_MARKER(((uint32_t) (('o') | (('l') << 8) | (('y') << 16
) | (((uint32_t) ('m')) << 24))))
(MAKE_MARKER ('o', 'l', 'y', 'm')((uint32_t) (('o') | (('l') << 8) | (('y') << 16)
| (((uint32_t) ('m')) << 24)))
)
82#define minf_MARKER(((uint32_t) (('m') | (('i') << 8) | (('n') << 16
) | (((uint32_t) ('f')) << 24))))
(MAKE_MARKER ('m', 'i', 'n', 'f')((uint32_t) (('m') | (('i') << 8) | (('n') << 16)
| (((uint32_t) ('f')) << 24)))
)
83#define elm1_MARKER(((uint32_t) (('e') | (('l') << 8) | (('m') << 16
) | (((uint32_t) ('1')) << 24))))
(MAKE_MARKER ('e', 'l', 'm', '1')((uint32_t) (('e') | (('l') << 8) | (('m') << 16)
| (((uint32_t) ('1')) << 24)))
)
84#define regn_MARKER(((uint32_t) (('r') | (('e') << 8) | (('g') << 16
) | (((uint32_t) ('n')) << 24))))
(MAKE_MARKER ('r', 'e', 'g', 'n')((uint32_t) (('r') | (('e') << 8) | (('g') << 16)
| (((uint32_t) ('n')) << 24)))
)
85#define ovwf_MARKER(((uint32_t) (('o') | (('v') << 8) | (('w') << 16
) | (((uint32_t) ('f')) << 24))))
(MAKE_MARKER ('o', 'v', 'w', 'f')((uint32_t) (('o') | (('v') << 8) | (('w') << 16)
| (((uint32_t) ('f')) << 24)))
)
86#define umid_MARKER(((uint32_t) (('u') | (('m') << 8) | (('i') << 16
) | (((uint32_t) ('d')) << 24))))
(MAKE_MARKER ('u', 'm', 'i', 'd')((uint32_t) (('u') | (('m') << 8) | (('i') << 16)
| (((uint32_t) ('d')) << 24)))
)
87#define SyLp_MARKER(((uint32_t) (('S') | (('y') << 8) | (('L') << 16
) | (((uint32_t) ('p')) << 24))))
(MAKE_MARKER ('S', 'y', 'L', 'p')((uint32_t) (('S') | (('y') << 8) | (('L') << 16)
| (((uint32_t) ('p')) << 24)))
)
88#define Cr8r_MARKER(((uint32_t) (('C') | (('r') << 8) | (('8') << 16
) | (((uint32_t) ('r')) << 24))))
(MAKE_MARKER ('C', 'r', '8', 'r')((uint32_t) (('C') | (('r') << 8) | (('8') << 16)
| (((uint32_t) ('r')) << 24)))
)
89#define JUNK_MARKER(((uint32_t) (('J') | (('U') << 8) | (('N') << 16
) | (((uint32_t) ('K')) << 24))))
(MAKE_MARKER ('J', 'U', 'N', 'K')((uint32_t) (('J') | (('U') << 8) | (('N') << 16)
| (((uint32_t) ('K')) << 24)))
)
90#define PMX_MARKER(((uint32_t) (('_') | (('P') << 8) | (('M') << 16
) | (((uint32_t) ('X')) << 24))))
(MAKE_MARKER ('_', 'P', 'M', 'X')((uint32_t) (('_') | (('P') << 8) | (('M') << 16)
| (((uint32_t) ('X')) << 24)))
)
91#define inst_MARKER(((uint32_t) (('i') | (('n') << 8) | (('s') << 16
) | (((uint32_t) ('t')) << 24))))
(MAKE_MARKER ('i', 'n', 's', 't')((uint32_t) (('i') | (('n') << 8) | (('s') << 16)
| (((uint32_t) ('t')) << 24)))
)
92#define AFAn_MARKER(((uint32_t) (('A') | (('F') << 8) | (('A') << 16
) | (((uint32_t) ('n')) << 24))))
(MAKE_MARKER ('A', 'F', 'A', 'n')((uint32_t) (('A') | (('F') << 8) | (('A') << 16)
| (((uint32_t) ('n')) << 24)))
)
93
94
95#define ISFT_MARKER(((uint32_t) (('I') | (('S') << 8) | (('F') << 16
) | (((uint32_t) ('T')) << 24))))
(MAKE_MARKER ('I', 'S', 'F', 'T')((uint32_t) (('I') | (('S') << 8) | (('F') << 16)
| (((uint32_t) ('T')) << 24)))
)
96#define ICRD_MARKER(((uint32_t) (('I') | (('C') << 8) | (('R') << 16
) | (((uint32_t) ('D')) << 24))))
(MAKE_MARKER ('I', 'C', 'R', 'D')((uint32_t) (('I') | (('C') << 8) | (('R') << 16)
| (((uint32_t) ('D')) << 24)))
)
97#define ICOP_MARKER(((uint32_t) (('I') | (('C') << 8) | (('O') << 16
) | (((uint32_t) ('P')) << 24))))
(MAKE_MARKER ('I', 'C', 'O', 'P')((uint32_t) (('I') | (('C') << 8) | (('O') << 16)
| (((uint32_t) ('P')) << 24)))
)
98#define IARL_MARKER(((uint32_t) (('I') | (('A') << 8) | (('R') << 16
) | (((uint32_t) ('L')) << 24))))
(MAKE_MARKER ('I', 'A', 'R', 'L')((uint32_t) (('I') | (('A') << 8) | (('R') << 16)
| (((uint32_t) ('L')) << 24)))
)
99#define IART_MARKER(((uint32_t) (('I') | (('A') << 8) | (('R') << 16
) | (((uint32_t) ('T')) << 24))))
(MAKE_MARKER ('I', 'A', 'R', 'T')((uint32_t) (('I') | (('A') << 8) | (('R') << 16)
| (((uint32_t) ('T')) << 24)))
)
100#define INAM_MARKER(((uint32_t) (('I') | (('N') << 8) | (('A') << 16
) | (((uint32_t) ('M')) << 24))))
(MAKE_MARKER ('I', 'N', 'A', 'M')((uint32_t) (('I') | (('N') << 8) | (('A') << 16)
| (((uint32_t) ('M')) << 24)))
)
101#define IENG_MARKER(((uint32_t) (('I') | (('E') << 8) | (('N') << 16
) | (((uint32_t) ('G')) << 24))))
(MAKE_MARKER ('I', 'E', 'N', 'G')((uint32_t) (('I') | (('E') << 8) | (('N') << 16)
| (((uint32_t) ('G')) << 24)))
)
102#define IGNR_MARKER(((uint32_t) (('I') | (('G') << 8) | (('N') << 16
) | (((uint32_t) ('R')) << 24))))
(MAKE_MARKER ('I', 'G', 'N', 'R')((uint32_t) (('I') | (('G') << 8) | (('N') << 16)
| (((uint32_t) ('R')) << 24)))
)
103#define ICOP_MARKER(((uint32_t) (('I') | (('C') << 8) | (('O') << 16
) | (((uint32_t) ('P')) << 24))))
(MAKE_MARKER ('I', 'C', 'O', 'P')((uint32_t) (('I') | (('C') << 8) | (('O') << 16)
| (((uint32_t) ('P')) << 24)))
)
104#define IPRD_MARKER(((uint32_t) (('I') | (('P') << 8) | (('R') << 16
) | (((uint32_t) ('D')) << 24))))
(MAKE_MARKER ('I', 'P', 'R', 'D')((uint32_t) (('I') | (('P') << 8) | (('R') << 16)
| (((uint32_t) ('D')) << 24)))
)
105#define ISRC_MARKER(((uint32_t) (('I') | (('S') << 8) | (('R') << 16
) | (((uint32_t) ('C')) << 24))))
(MAKE_MARKER ('I', 'S', 'R', 'C')((uint32_t) (('I') | (('S') << 8) | (('R') << 16)
| (((uint32_t) ('C')) << 24)))
)
106#define ISBJ_MARKER(((uint32_t) (('I') | (('S') << 8) | (('B') << 16
) | (((uint32_t) ('J')) << 24))))
(MAKE_MARKER ('I', 'S', 'B', 'J')((uint32_t) (('I') | (('S') << 8) | (('B') << 16)
| (((uint32_t) ('J')) << 24)))
)
107#define ICMT_MARKER(((uint32_t) (('I') | (('C') << 8) | (('M') << 16
) | (((uint32_t) ('T')) << 24))))
(MAKE_MARKER ('I', 'C', 'M', 'T')((uint32_t) (('I') | (('C') << 8) | (('M') << 16)
| (((uint32_t) ('T')) << 24)))
)
108#define IAUT_MARKER(((uint32_t) (('I') | (('A') << 8) | (('U') << 16
) | (((uint32_t) ('T')) << 24))))
(MAKE_MARKER ('I', 'A', 'U', 'T')((uint32_t) (('I') | (('A') << 8) | (('U') << 16)
| (((uint32_t) ('T')) << 24)))
)
109#define ITRK_MARKER(((uint32_t) (('I') | (('T') << 8) | (('R') << 16
) | (((uint32_t) ('K')) << 24))))
(MAKE_MARKER ('I', 'T', 'R', 'K')((uint32_t) (('I') | (('T') << 8) | (('R') << 16)
| (((uint32_t) ('K')) << 24)))
)
110
111/* Weird WAVPACK marker which can show up at the start of the DATA section. */
112#define wvpk_MARKER(((uint32_t) (('w') | (('v') << 8) | (('p') << 16
) | (((uint32_t) ('k')) << 24))))
(MAKE_MARKER ('w', 'v', 'p', 'k')((uint32_t) (('w') | (('v') << 8) | (('p') << 16)
| (((uint32_t) ('k')) << 24)))
)
113#define OggS_MARKER(((uint32_t) (('O') | (('g') << 8) | (('g') << 16
) | (((uint32_t) ('S')) << 24))))
(MAKE_MARKER ('O', 'g', 'g', 'S')((uint32_t) (('O') | (('g') << 8) | (('g') << 16)
| (((uint32_t) ('S')) << 24)))
)
114
115#define WAV_PEAK_CHUNK_SIZE(ch)(2 * sizeof (int) + ch * (sizeof (float) + sizeof (int))) (2 * sizeof (int) + ch * (sizeof (float) + sizeof (int)))
116#define WAV_BEXT_MIN_CHUNK_SIZE602 602
117#define WAV_BEXT_MAX_CHUNK_SIZE(10 * 1024) (10 * 1024)
118
119#define WAV_CART_MIN_CHUNK_SIZE2048 2048
120#define WAV_CART_MAX_CHUNK_SIZE0xffffffff 0xffffffff
121
122
123enum
124{ HAVE_RIFF = 0x01,
125 HAVE_WAVE = 0x02,
126 HAVE_fmt = 0x04,
127 HAVE_fact = 0x08,
128 HAVE_PEAK = 0x10,
129 HAVE_data = 0x20,
130 HAVE_other = 0x80000000
131} ;
132
133
134
135/* known WAVEFORMATEXTENSIBLE GUIDS */
136static const EXT_SUBFORMAT MSGUID_SUBTYPE_PCM =
137{ 0x00000001, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }
138} ;
139
140static const EXT_SUBFORMAT MSGUID_SUBTYPE_MS_ADPCM =
141{ 0x00000002, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }
142} ;
143
144static const EXT_SUBFORMAT MSGUID_SUBTYPE_IEEE_FLOAT =
145{ 0x00000003, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }
146} ;
147
148static const EXT_SUBFORMAT MSGUID_SUBTYPE_ALAW =
149{ 0x00000006, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }
150} ;
151
152static const EXT_SUBFORMAT MSGUID_SUBTYPE_MULAW =
153{ 0x00000007, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }
154} ;
155
156/*
157** the next two are from
158** http://dream.cs.bath.ac.uk/researchdev/wave-ex/bformat.html
159*/
160static const EXT_SUBFORMAT MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_PCM =
161{ 0x00000001, 0x0721, 0x11d3, { 0x86, 0x44, 0xC8, 0xC1, 0xCA, 0x00, 0x00, 0x00 }
162} ;
163
164static const EXT_SUBFORMAT MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_IEEE_FLOAT =
165{ 0x00000003, 0x0721, 0x11d3, { 0x86, 0x44, 0xC8, 0xC1, 0xCA, 0x00, 0x00, 0x00 }
166} ;
167
168
169#if 0
170/* maybe interesting one day to read the following through sf_read_raw */
171/* http://www.bath.ac.uk/~masrwd/pvocex/pvocex.html */
172static const EXT_SUBFORMAT MSGUID_SUBTYPE_PVOCEX =
173{ 0x8312B9C2, 0x2E6E, 0x11d4, { 0xA8, 0x24, 0xDE, 0x5B, 0x96, 0xC3, 0xAB, 0x21 }
174} ;
175#endif
176
177/*------------------------------------------------------------------------------
178** Private static functions.
179*/
180
181static int wav_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock) ;
182static int wav_write_header (SF_PRIVATE *psf, int calc_length) ;
183
184static int wav_write_tailer (SF_PRIVATE *psf) ;
185static void wav_write_strings (SF_PRIVATE *psf, int location) ;
186static int wav_command (SF_PRIVATE *psf, int command, void *data, int datasize) ;
187static int wav_close (SF_PRIVATE *psf) ;
188
189static int wav_subchunk_parse (SF_PRIVATE *psf, int chunk, uint32_t length) ;
190static int exif_subchunk_parse (SF_PRIVATE *psf, uint32_t length) ;
191static int wav_read_smpl_chunk (SF_PRIVATE *psf, uint32_t chunklen) ;
192static int wav_read_acid_chunk (SF_PRIVATE *psf, uint32_t chunklen) ;
193
194static int wav_set_chunk (SF_PRIVATE *psf, const SF_CHUNK_INFO * chunk_info) ;
195static SF_CHUNK_ITERATOR * wav_next_chunk_iterator (SF_PRIVATE *psf, SF_CHUNK_ITERATOR * iterator) ;
196static int wav_get_chunk_size (SF_PRIVATE *psf, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info) ;
197static int wav_get_chunk_data (SF_PRIVATE *psf, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info) ;
198
199/*------------------------------------------------------------------------------
200** Public function.
201*/
202
203int
204wav_open (SF_PRIVATE *psf)
205{ WAV_PRIVATE * wpriv ;
206 int format, subformat, error, blockalign = 0, framesperblock = 0 ;
207
208 if ((wpriv = calloc (1, sizeof (WAV_PRIVATE))) == NULL((void*)0))
209 return SFE_MALLOC_FAILED ;
210 psf->container_data = wpriv ;
211
212 wpriv->wavex_ambisonic = SF_AMBISONIC_NONE ;
213 psf->strings.flags = SF_STR_ALLOW_START | SF_STR_ALLOW_END ;
214
215 if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
216 { if ((error = wav_read_header (psf, &blockalign, &framesperblock)))
217 return error ;
218
219 psf->next_chunk_iterator = wav_next_chunk_iterator ;
220 psf->get_chunk_size = wav_get_chunk_size ;
221 psf->get_chunk_data = wav_get_chunk_data ;
222 } ;
223
224 subformat = SF_CODEC (psf->sf.format)((psf->sf.format) & SF_FORMAT_SUBMASK) ;
225
226 if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
227 { if (psf->is_pipe)
228 return SFE_NO_PIPE_WRITE ;
229
230 wpriv->wavex_ambisonic = SF_AMBISONIC_NONE ;
231
232 format = SF_CONTAINER (psf->sf.format)((psf->sf.format) & SF_FORMAT_TYPEMASK) ;
233 if (format != SF_FORMAT_WAV && format != SF_FORMAT_WAVEX)
234 return SFE_BAD_OPEN_FORMAT ;
235
236 psf->blockwidth = psf->bytewidth * psf->sf.channels ;
237
238 /* RIFF WAVs are little-endian, RIFX WAVs are big-endian, default to little */
239 psf->endian = SF_ENDIAN (psf->sf.format)((psf->sf.format) & SF_FORMAT_ENDMASK) ;
240 if (CPU_IS_BIG_ENDIAN0 && psf->endian == SF_ENDIAN_CPU)
241 psf->endian = SF_ENDIAN_BIG ;
242 else if (psf->endian != SF_ENDIAN_BIG)
243 psf->endian = SF_ENDIAN_LITTLE ;
244
245 if (psf->file.mode != SFM_RDWR || psf->filelength < 44)
246 { psf->filelength = 0 ;
247 psf->datalength = 0 ;
248 psf->dataoffset = 0 ;
249 psf->sf.frames = 0 ;
250 } ;
251
252 if (subformat == SF_FORMAT_IMA_ADPCM || subformat == SF_FORMAT_MS_ADPCM)
253 { blockalign = wav_w64_srate2blocksize (psf->sf.samplerate * psf->sf.channels) ;
254 framesperblock = -1 ; /* Corrected later. */
255 } ;
256
257 /* By default, add the peak chunk to floating point files. Default behaviour
258 ** can be switched off using sf_command (SFC_SET_PEAK_CHUNK, SF_FALSE).
259 */
260 if (psf->file.mode == SFM_WRITE && (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE))
261 { if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL((void*)0))
262 return SFE_MALLOC_FAILED ;
263 psf->peak_info->peak_loc = SF_PEAK_START ;
264 } ;
265
266 psf->write_header = wav_write_header ;
267 psf->set_chunk = wav_set_chunk ;
268 } ;
269
270 psf->container_close = wav_close ;
271 psf->command = wav_command ;
272
273 switch (subformat)
274 { case SF_FORMAT_PCM_U8 :
275 case SF_FORMAT_PCM_16 :
276 case SF_FORMAT_PCM_24 :
277 case SF_FORMAT_PCM_32 :
278 error = pcm_init (psf) ;
279 break ;
280
281 case SF_FORMAT_ULAW :
282 error = ulaw_init (psf) ;
283 break ;
284
285 case SF_FORMAT_ALAW :
286 error = alaw_init (psf) ;
287 break ;
288
289 /* Lite remove start */
290 case SF_FORMAT_FLOAT :
291 error = float32_init (psf) ;
292 break ;
293
294 case SF_FORMAT_DOUBLE :
295 error = double64_init (psf) ;
296 break ;
297
298 case SF_FORMAT_IMA_ADPCM :
299 error = wav_w64_ima_init (psf, blockalign, framesperblock) ;
300 break ;
301
302 case SF_FORMAT_MS_ADPCM :
303 error = wav_w64_msadpcm_init (psf, blockalign, framesperblock) ;
304 break ;
305
306 case SF_FORMAT_G721_32 :
307 error = g72x_init (psf) ;
308 break ;
309 /* Lite remove end */
310
311 case SF_FORMAT_GSM610 :
312 error = gsm610_init (psf) ;
313 break ;
314
315 default : return SFE_UNIMPLEMENTED ;
316 } ;
317
318 if (psf->file.mode == SFM_WRITE || (psf->file.mode == SFM_RDWR && psf->filelength == 0))
319 return psf->write_header (psf, SF_FALSE) ;
320
321 return error ;
322} /* wav_open */
323
324/*=========================================================================
325** Private functions.
326*/
327
328static int
329wav_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock)
330{ WAV_PRIVATE *wpriv ;
331 WAV_FMT *wav_fmt ;
332 FACT_CHUNK fact_chunk ;
333 uint32_t marker, chunk_size = 0, RIFFsize = 0, done = 0, uk ;
334 int parsestage = 0, error, format = 0 ;
335 char buffer [256] ;
336
337 if (psf->filelength > SF_PLATFORM_S64 (0xffffffff)0xffffffffl)
338 psf_log_printf (psf, "Warning : filelength > 0xffffffff. This is bad!!!!\n") ;
339
340 if ((wpriv = psf->container_data) == NULL((void*)0))
341 return SFE_INTERNAL ;
342 wav_fmt = &wpriv->wav_fmt ;
343
344 /* Set position to start of file to begin reading header. */
345 psf_binheader_readf (psf, "pmj", 0, &marker, -4) ;
346 psf->headindex = 0 ;
347
348 /* RIFX signifies big-endian format for all header and data to prevent
349 ** lots of code copying here, we'll set the psf->rwf_endian flag once here,
350 ** and never specify endian-ness for all other header ops/
351 */
352 psf->rwf_endian = (marker == RIFF_MARKER(((uint32_t) (('R') | (('I') << 8) | (('F') << 16
) | (((uint32_t) ('F')) << 24))))
) ? SF_ENDIAN_LITTLE : SF_ENDIAN_BIG ;
353
354 while (! done)
355 { size_t jump = chunk_size & 1 ;
356
357 marker = chunk_size = 0 ;
358 psf_binheader_readf (psf, "jm4", jump, &marker, &chunk_size) ;
359 if (marker == 0)
360 { psf_log_printf (psf, "Have 0 marker.\n") ;
361 break ;
362 } ;
363
364 psf_store_read_chunk_u32 (&psf->rchunks, marker, psf_ftell (psf), chunk_size) ;
365
366 switch (marker)
367 { case RIFF_MARKER(((uint32_t) (('R') | (('I') << 8) | (('F') << 16
) | (((uint32_t) ('F')) << 24))))
:
368 case RIFX_MARKER(((uint32_t) (('R') | (('I') << 8) | (('F') << 16
) | (((uint32_t) ('X')) << 24))))
:
369 if (parsestage)
370 return SFE_WAV_NO_RIFF ;
371
372 parsestage |= HAVE_RIFF ;
373
374 RIFFsize = chunk_size ;
375
376 if (psf->fileoffset > 0 && psf->filelength > RIFFsize + 8)
377 { /* Set file length. */
378 psf->filelength = RIFFsize + 8 ;
379 if (marker == RIFF_MARKER(((uint32_t) (('R') | (('I') << 8) | (('F') << 16
) | (((uint32_t) ('F')) << 24))))
)
380 psf_log_printf (psf, "RIFF : %u\n", RIFFsize) ;
381 else
382 psf_log_printf (psf, "RIFX : %u\n", RIFFsize) ;
383 }
384 else if (psf->filelength < RIFFsize + 2 * SIGNED_SIZEOF (marker)((int) sizeof (marker)))
385 { if (marker == RIFF_MARKER(((uint32_t) (('R') | (('I') << 8) | (('F') << 16
) | (((uint32_t) ('F')) << 24))))
)
386 psf_log_printf (psf, "RIFF : %u (should be %D)\n", RIFFsize, psf->filelength - 2 * SIGNED_SIZEOF (marker)((int) sizeof (marker))) ;
387 else
388 psf_log_printf (psf, "RIFX : %u (should be %D)\n", RIFFsize, psf->filelength - 2 * SIGNED_SIZEOF (marker)((int) sizeof (marker))) ;
389
390 RIFFsize = psf->filelength - 2 * SIGNED_SIZEOF (RIFFsize)((int) sizeof (RIFFsize)) ;
391 }
392 else
393 { if (marker == RIFF_MARKER(((uint32_t) (('R') | (('I') << 8) | (('F') << 16
) | (((uint32_t) ('F')) << 24))))
)
394 psf_log_printf (psf, "RIFF : %u\n", RIFFsize) ;
395 else
396 psf_log_printf (psf, "RIFX : %u\n", RIFFsize) ;
397 } ;
398
399 psf_binheader_readf (psf, "m", &marker) ;
400 if (marker != WAVE_MARKER(((uint32_t) (('W') | (('A') << 8) | (('V') << 16
) | (((uint32_t) ('E')) << 24))))
)
401 return SFE_WAV_NO_WAVE ;
402 parsestage |= HAVE_WAVE ;
403 psf_log_printf (psf, "WAVE\n") ;
404 chunk_size = 0 ;
405 break ;
406
407 case fmt_MARKER(((uint32_t) (('f') | (('m') << 8) | (('t') << 16
) | (((uint32_t) (' ')) << 24))))
:
408 if ((parsestage & (HAVE_RIFF | HAVE_WAVE)) != (HAVE_RIFF | HAVE_WAVE))
409 return SFE_WAV_NO_FMT ;
410
411 /* If this file has a SECOND fmt chunk, I don't want to know about it. */
412 if (parsestage & HAVE_fmt)
413 break ;
414
415 parsestage |= HAVE_fmt ;
416
417 psf_log_printf (psf, "fmt : %d\n", chunk_size) ;
418
419 if ((error = wav_w64_read_fmt_chunk (psf, chunk_size)))
420 return error ;
421
422 format = wav_fmt->format ;
423 break ;
424
425 case data_MARKER(((uint32_t) (('d') | (('a') << 8) | (('t') << 16
) | (((uint32_t) ('a')) << 24))))
:
426 if ((parsestage & (HAVE_RIFF | HAVE_WAVE | HAVE_fmt)) != (HAVE_RIFF | HAVE_WAVE | HAVE_fmt))
427 return SFE_WAV_NO_DATA ;
428
429 if (psf->file.mode == SFM_RDWR && (parsestage & HAVE_other) != 0)
430 return SFE_RDWR_BAD_HEADER ;
431
432 parsestage |= HAVE_data ;
433
434 psf->datalength = chunk_size ;
435 psf->dataoffset = psf_ftell (psf) ;
436
437 if (psf->dataoffset > 0)
438 { if (chunk_size == 0 && RIFFsize == 8 && psf->filelength > 44)
439 { psf_log_printf (psf, "*** Looks like a WAV file which wasn't closed properly. Fixing it.\n") ;
440 psf->datalength = psf->filelength - psf->dataoffset ;
441 } ;
442
443 if (psf->datalength > psf->filelength - psf->dataoffset)
444 { psf_log_printf (psf, "data : %D (should be %D)\n", psf->datalength, psf->filelength - psf->dataoffset) ;
445 psf->datalength = psf->filelength - psf->dataoffset ;
446 }
447 else
448 psf_log_printf (psf, "data : %D\n", psf->datalength) ;
449
450 /* Only set dataend if there really is data at the end. */
451 if (psf->datalength + psf->dataoffset < psf->filelength)
452 psf->dataend = psf->datalength + psf->dataoffset ;
453
454 psf->datalength += chunk_size & 1 ;
455 chunk_size = 0 ;
456 } ;
457
458 if (! psf->sf.seekable || psf->dataoffset < 0)
459 break ;
460
461 /* Seek past data and continue reading header. */
462 psf_fseek (psf, psf->datalength, SEEK_CUR1) ;
463
464 if (psf_ftell (psf) != psf->datalength + psf->dataoffset)
465 psf_log_printf (psf, "*** psf_fseek past end error ***\n") ;
466 break ;
467
468 case fact_MARKER(((uint32_t) (('f') | (('a') << 8) | (('c') << 16
) | (((uint32_t) ('t')) << 24))))
:
469 if ((parsestage & (HAVE_RIFF | HAVE_WAVE)) != (HAVE_RIFF | HAVE_WAVE))
470 return SFE_WAV_BAD_FACT ;
471
472 parsestage |= HAVE_fact ;
473
474 if ((parsestage & HAVE_fmt) != HAVE_fmt)
475 psf_log_printf (psf, "*** Should have 'fmt ' chunk before 'fact'\n") ;
476
477 psf_binheader_readf (psf, "4", & (fact_chunk.frames)) ;
478
479 if (chunk_size > SIGNED_SIZEOF (fact_chunk)((int) sizeof (fact_chunk)))
480 psf_binheader_readf (psf, "j", (int) (chunk_size - SIGNED_SIZEOF (fact_chunk)((int) sizeof (fact_chunk)))) ;
481
482 if (chunk_size)
483 psf_log_printf (psf, "%M : %d\n", marker, chunk_size) ;
484 else
485 psf_log_printf (psf, "%M : %d (should not be zero)\n", marker, chunk_size) ;
486
487 psf_log_printf (psf, " frames : %d\n", fact_chunk.frames) ;
488 break ;
489
490 case PEAK_MARKER(((uint32_t) (('P') | (('E') << 8) | (('A') << 16
) | (((uint32_t) ('K')) << 24))))
:
491 if ((parsestage & (HAVE_RIFF | HAVE_WAVE | HAVE_fmt)) != (HAVE_RIFF | HAVE_WAVE | HAVE_fmt))
492 return SFE_WAV_PEAK_B4_FMT ;
493
494 parsestage |= HAVE_PEAK ;
495
496 psf_log_printf (psf, "%M : %d\n", marker, chunk_size) ;
497 if (chunk_size != WAV_PEAK_CHUNK_SIZE (psf->sf.channels)(2 * sizeof (int) + psf->sf.channels * (sizeof (float) + sizeof
(int)))
)
498 { psf_binheader_readf (psf, "j", chunk_size) ;
499 psf_log_printf (psf, "*** File PEAK chunk size doesn't fit with number of channels (%d).\n", psf->sf.channels) ;
500 return SFE_WAV_BAD_PEAK ;
501 } ;
502
503 if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL((void*)0))
504 return SFE_MALLOC_FAILED ;
505
506 /* read in rest of PEAK chunk. */
507 psf_binheader_readf (psf, "44", & (psf->peak_info->version), & (psf->peak_info->timestamp)) ;
508
509 if (psf->peak_info->version != 1)
510 psf_log_printf (psf, " version : %d *** (should be version 1)\n", psf->peak_info->version) ;
511 else
512 psf_log_printf (psf, " version : %d\n", psf->peak_info->version) ;
513
514 psf_log_printf (psf, " time stamp : %d\n", psf->peak_info->timestamp) ;
515 psf_log_printf (psf, " Ch Position Value\n") ;
516
517 for (uk = 0 ; uk < (uint32_t) psf->sf.channels ; uk++)
518 { float value ;
519 uint32_t position ;
520
521 psf_binheader_readf (psf, "f4", &value, &position) ;
522 psf->peak_info->peaks [uk].value = value ;
523 psf->peak_info->peaks [uk].position = position ;
524
525 snprintf (buffer, sizeof (buffer), " %2d %-12" PRId64 " %g\n",__builtin___snprintf_chk (buffer, sizeof (buffer), 2 - 1, __builtin_object_size
(buffer, 2 > 1), " %2d %-12" "l" "d" " %g\n", uk, psf
->peak_info->peaks [uk].position, psf->peak_info->
peaks [uk].value)
526 uk, psf->peak_info->peaks [uk].position, psf->peak_info->peaks [uk].value)__builtin___snprintf_chk (buffer, sizeof (buffer), 2 - 1, __builtin_object_size
(buffer, 2 > 1), " %2d %-12" "l" "d" " %g\n", uk, psf
->peak_info->peaks [uk].position, psf->peak_info->
peaks [uk].value)
;
527 buffer [sizeof (buffer) - 1] = 0 ;
528 psf_log_printf (psf, "%s", buffer) ;
529 } ;
530
531 psf->peak_info->peak_loc = ((parsestage & HAVE_data) == 0) ? SF_PEAK_START : SF_PEAK_END ;
532 break ;
533
534 case cue_MARKER(((uint32_t) (('c') | (('u') << 8) | (('e') << 16
) | (((uint32_t) (' ')) << 24))))
:
535 parsestage |= HAVE_other ;
536
537 { uint32_t bytesread, cue_count ;
538 int id, position, chunk_id, chunk_start, block_start, offset ;
539
540 bytesread = psf_binheader_readf (psf, "4", &cue_count) ;
541 psf_log_printf (psf, "%M : %u\n", marker, chunk_size) ;
542
543 if (cue_count > 10)
544 { psf_log_printf (psf, " Count : %d (skipping)\n", cue_count) ;
545 psf_binheader_readf (psf, "j", cue_count * 24) ;
546 break ;
547 } ;
548
549 psf_log_printf (psf, " Count : %d\n", cue_count) ;
550
551 while (cue_count)
552 { bytesread += psf_binheader_readf (psf, "444444", &id, &position,
553 &chunk_id, &chunk_start, &block_start, &offset) ;
554 psf_log_printf (psf, " Cue ID : %2d"
555 " Pos : %5u Chunk : %M"
556 " Chk Start : %d Blk Start : %d"
557 " Offset : %5d\n",
558 id, position, chunk_id, chunk_start, block_start, offset) ;
559 cue_count -- ;
560 } ;
561
562 if (bytesread != chunk_size)
563 { psf_log_printf (psf, "**** Chunk size weirdness (%d != %d)\n", chunk_size, bytesread) ;
564 psf_binheader_readf (psf, "j", chunk_size - bytesread) ;
565 } ;
566 } ;
567 break ;
568
569 case smpl_MARKER(((uint32_t) (('s') | (('m') << 8) | (('p') << 16
) | (((uint32_t) ('l')) << 24))))
:
570 parsestage |= HAVE_other ;
571
572 psf_log_printf (psf, "smpl : %u\n", chunk_size) ;
573
574 if ((error = wav_read_smpl_chunk (psf, chunk_size)))
575 return error ;
576 break ;
577
578 case acid_MARKER(((uint32_t) (('a') | (('c') << 8) | (('i') << 16
) | (((uint32_t) ('d')) << 24))))
:
579 parsestage |= HAVE_other ;
580
581 psf_log_printf (psf, "acid : %u\n", chunk_size) ;
582
583 if ((error = wav_read_acid_chunk (psf, chunk_size)))
584 return error ;
585 break ;
586
587 case INFO_MARKER(((uint32_t) (('I') | (('N') << 8) | (('F') << 16
) | (((uint32_t) ('O')) << 24))))
:
588 case LIST_MARKER(((uint32_t) (('L') | (('I') << 8) | (('S') << 16
) | (((uint32_t) ('T')) << 24))))
:
589 parsestage |= HAVE_other ;
590
591 if ((error = wav_subchunk_parse (psf, marker, chunk_size)) != 0)
592 return error ;
593 break ;
594
595 case bext_MARKER(((uint32_t) (('b') | (('e') << 8) | (('x') << 16
) | (((uint32_t) ('t')) << 24))))
:
596 /*
597 The 'bext' chunk can actually be updated, so don't need to set this.
598 parsestage |= HAVE_other ;
599 */
600 if ((error = wav_read_bext_chunk (psf, chunk_size)))
601 return error ;
602 break ;
603
604 case PAD_MARKER(((uint32_t) (('P') | (('A') << 8) | (('D') << 16
) | (((uint32_t) (' ')) << 24))))
:
605 /*
606 We can eat into a 'PAD ' chunk if we need to.
607 parsestage |= HAVE_other ;
608 */
609 psf_log_printf (psf, "%M : %u\n", marker, chunk_size) ;
610 psf_binheader_readf (psf, "j", chunk_size) ;
611 break ;
612
613 case cart_MARKER(((uint32_t) (('c') | (('a') << 8) | (('r') << 16
) | (((uint32_t) ('t')) << 24))))
:
614 if ((error = wav_read_cart_chunk (psf, chunk_size)))
615 return error ;
616 break ;
617
618 case iXML_MARKER(((uint32_t) (('i') | (('X') << 8) | (('M') << 16
) | (((uint32_t) ('L')) << 24))))
: /* See http://en.wikipedia.org/wiki/IXML */
619 case strc_MARKER(((uint32_t) (('s') | (('t') << 8) | (('r') << 16
) | (((uint32_t) ('c')) << 24))))
: /* Multiple of 32 bytes. */
620 case afsp_MARKER(((uint32_t) (('a') | (('f') << 8) | (('s') << 16
) | (((uint32_t) ('p')) << 24))))
:
621 case clm_MARKER(((uint32_t) (('c') | (('l') << 8) | (('m') << 16
) | (((uint32_t) (' ')) << 24))))
:
622 case elmo_MARKER(((uint32_t) (('e') | (('l') << 8) | (('m') << 16
) | (((uint32_t) ('o')) << 24))))
:
623 case levl_MARKER(((uint32_t) (('l') | (('e') << 8) | (('v') << 16
) | (((uint32_t) ('l')) << 24))))
:
624 case plst_MARKER(((uint32_t) (('p') | (('l') << 8) | (('s') << 16
) | (((uint32_t) ('t')) << 24))))
:
625 case minf_MARKER(((uint32_t) (('m') | (('i') << 8) | (('n') << 16
) | (((uint32_t) ('f')) << 24))))
:
626 case elm1_MARKER(((uint32_t) (('e') | (('l') << 8) | (('m') << 16
) | (((uint32_t) ('1')) << 24))))
:
627 case regn_MARKER(((uint32_t) (('r') | (('e') << 8) | (('g') << 16
) | (((uint32_t) ('n')) << 24))))
:
628 case ovwf_MARKER(((uint32_t) (('o') | (('v') << 8) | (('w') << 16
) | (((uint32_t) ('f')) << 24))))
:
629 case inst_MARKER(((uint32_t) (('i') | (('n') << 8) | (('s') << 16
) | (((uint32_t) ('t')) << 24))))
:
630 case AFAn_MARKER(((uint32_t) (('A') | (('F') << 8) | (('A') << 16
) | (((uint32_t) ('n')) << 24))))
:
631 case umid_MARKER(((uint32_t) (('u') | (('m') << 8) | (('i') << 16
) | (((uint32_t) ('d')) << 24))))
:
632 case SyLp_MARKER(((uint32_t) (('S') | (('y') << 8) | (('L') << 16
) | (((uint32_t) ('p')) << 24))))
:
633 case Cr8r_MARKER(((uint32_t) (('C') | (('r') << 8) | (('8') << 16
) | (((uint32_t) ('r')) << 24))))
:
634 case JUNK_MARKER(((uint32_t) (('J') | (('U') << 8) | (('N') << 16
) | (((uint32_t) ('K')) << 24))))
:
635 case PMX_MARKER(((uint32_t) (('_') | (('P') << 8) | (('M') << 16
) | (((uint32_t) ('X')) << 24))))
:
636 case DISP_MARKER(((uint32_t) (('D') | (('I') << 8) | (('S') << 16
) | (((uint32_t) ('P')) << 24))))
:
637 case MEXT_MARKER(((uint32_t) (('M') | (('E') << 8) | (('X') << 16
) | (((uint32_t) ('T')) << 24))))
:
638 case FLLR_MARKER(((uint32_t) (('F') | (('L') << 8) | (('L') << 16
) | (((uint32_t) ('R')) << 24))))
:
639 psf_log_printf (psf, "%M : %u\n", marker, chunk_size) ;
640 psf_binheader_readf (psf, "j", chunk_size) ;
641 break ;
642
643 default :
644 if (psf_isprint ((marker >> 24) & 0xFF) && psf_isprint ((marker >> 16) & 0xFF)
645 && psf_isprint ((marker >> 8) & 0xFF) && psf_isprint (marker & 0xFF))
646 { psf_log_printf (psf, "*** %M : %d (unknown marker)\n", marker, chunk_size) ;
647 psf_binheader_readf (psf, "j", chunk_size) ;
648 break ;
649 } ;
650 if (psf_ftell (psf) & 0x03)
651 { psf_log_printf (psf, " Unknown chunk marker at position %D. Resynching.\n", psf_ftell (psf) - 8) ;
652 psf_binheader_readf (psf, "j", -3) ;
653 /* File is too messed up so we prevent editing in RDWR mode here. */
654 parsestage |= HAVE_other ;
655 break ;
656 } ;
657 psf_log_printf (psf, "*** Unknown chunk marker (%X) at position %D. Exiting parser.\n", marker, psf_ftell (psf) - 8) ;
658 done = SF_TRUE ;
659 break ;
660 } ; /* switch (marker) */
661
662 if (! psf->sf.seekable && (parsestage & HAVE_data))
663 break ;
664
665 if (psf_ftell (psf) >= psf->filelength - SIGNED_SIZEOF (chunk_size)((int) sizeof (chunk_size)))
666 { psf_log_printf (psf, "End\n") ;
667 break ;
668 } ;
669 } ; /* while (1) */
670
671 if (psf->dataoffset <= 0)
672 return SFE_WAV_NO_DATA ;
673
674 /* WAVs can be little or big endian */
675 psf->endian = psf->rwf_endian ;
676
677 psf_fseek (psf, psf->dataoffset, SEEK_SET0) ;
678
679 if (psf->is_pipe == 0)
680 { /*
681 ** Check for 'wvpk' at the start of the DATA section. Not able to
682 ** handle this.
683 */
684 psf_binheader_readf (psf, "4", &marker) ;
685 if (marker == wvpk_MARKER(((uint32_t) (('w') | (('v') << 8) | (('p') << 16
) | (((uint32_t) ('k')) << 24))))
|| marker == OggS_MARKER(((uint32_t) (('O') | (('g') << 8) | (('g') << 16
) | (((uint32_t) ('S')) << 24))))
)
686 return SFE_WAV_WVPK_DATA ;
687 } ;
688
689 /* Seek to start of DATA section. */
690 psf_fseek (psf, psf->dataoffset, SEEK_SET0) ;
691
692 if (psf->blockwidth)
693 { if (psf->filelength - psf->dataoffset < psf->datalength)
694 psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ;
695 else
696 psf->sf.frames = psf->datalength / psf->blockwidth ;
697 } ;
698
699 switch (format)
700 { case WAVE_FORMAT_EXTENSIBLE :
701 if (psf->sf.format == (SF_FORMAT_WAVEX | SF_FORMAT_MS_ADPCM))
702 { *blockalign = wav_fmt->msadpcm.blockalign ;
703 *framesperblock = wav_fmt->msadpcm.samplesperblock ;
704 } ;
705 break ;
706
707 case WAVE_FORMAT_PCM :
708 psf->sf.format = SF_FORMAT_WAV | u_bitwidth_to_subformat (psf->bytewidth * 8) ;
709 break ;
710
711 case WAVE_FORMAT_MULAW :
712 case IBM_FORMAT_MULAW :
713 psf->sf.format = (SF_FORMAT_WAV | SF_FORMAT_ULAW) ;
714 break ;
715
716 case WAVE_FORMAT_ALAW :
717 case IBM_FORMAT_ALAW :
718 psf->sf.format = (SF_FORMAT_WAV | SF_FORMAT_ALAW) ;
719 break ;
720
721 case WAVE_FORMAT_MS_ADPCM :
722 psf->sf.format = (SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM) ;
723 *blockalign = wav_fmt->msadpcm.blockalign ;
724 *framesperblock = wav_fmt->msadpcm.samplesperblock ;
725 break ;
726
727 case WAVE_FORMAT_IMA_ADPCM :
728 psf->sf.format = (SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM) ;
729 *blockalign = wav_fmt->ima.blockalign ;
730 *framesperblock = wav_fmt->ima.samplesperblock ;
731 break ;
732
733 case WAVE_FORMAT_GSM610 :
734 psf->sf.format = (SF_FORMAT_WAV | SF_FORMAT_GSM610) ;
735 break ;
736
737 case WAVE_FORMAT_IEEE_FLOAT :
738 psf->sf.format = SF_FORMAT_WAV ;
739 psf->sf.format |= (psf->bytewidth == 8) ? SF_FORMAT_DOUBLE : SF_FORMAT_FLOAT ;
740 break ;
741
742 case WAVE_FORMAT_G721_ADPCM :
743 psf->sf.format = SF_FORMAT_WAV | SF_FORMAT_G721_32 ;
744 break ;
745
746 default : return SFE_UNIMPLEMENTED ;
747 } ;
748
749 if (wpriv->fmt_is_broken)
750 wav_w64_analyze (psf) ;
751
752 /* Only set the format endian-ness if its non-standard big-endian. */
753 if (psf->endian == SF_ENDIAN_BIG)
754 psf->sf.format |= SF_ENDIAN_BIG ;
755
756 return 0 ;
757} /* wav_read_header */
758
759static int
760wav_write_fmt_chunk (SF_PRIVATE *psf)
761{ int subformat, fmt_size, add_fact_chunk = 0 ;
762
763 subformat = SF_CODEC (psf->sf.format)((psf->sf.format) & SF_FORMAT_SUBMASK) ;
764
765 switch (subformat)
766 { case SF_FORMAT_PCM_U8 :
767 case SF_FORMAT_PCM_16 :
768 case SF_FORMAT_PCM_24 :
769 case SF_FORMAT_PCM_32 :
770 fmt_size = 2 + 2 + 4 + 4 + 2 + 2 ;
771
772 /* fmt : format, channels, samplerate */
773 psf_binheader_writef (psf, "4224", fmt_size, WAVE_FORMAT_PCM, psf->sf.channels, psf->sf.samplerate) ;
774 /* fmt : bytespersec */
775 psf_binheader_writef (psf, "4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ;
776 /* fmt : blockalign, bitwidth */
777 psf_binheader_writef (psf, "22", psf->bytewidth * psf->sf.channels, psf->bytewidth * 8) ;
778 break ;
779
780 case SF_FORMAT_FLOAT :
781 case SF_FORMAT_DOUBLE :
782 fmt_size = 2 + 2 + 4 + 4 + 2 + 2 ;
783
784 /* fmt : format, channels, samplerate */
785 psf_binheader_writef (psf, "4224", fmt_size, WAVE_FORMAT_IEEE_FLOAT, psf->sf.channels, psf->sf.samplerate) ;
786 /* fmt : bytespersec */
787 psf_binheader_writef (psf, "4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ;
788 /* fmt : blockalign, bitwidth */
789 psf_binheader_writef (psf, "22", psf->bytewidth * psf->sf.channels, psf->bytewidth * 8) ;
790
791 add_fact_chunk = SF_TRUE ;
792 break ;
793
794 case SF_FORMAT_ULAW :
795 fmt_size = 2 + 2 + 4 + 4 + 2 + 2 + 2 ;
796
797 /* fmt : format, channels, samplerate */
798 psf_binheader_writef (psf, "4224", fmt_size, WAVE_FORMAT_MULAW, psf->sf.channels, psf->sf.samplerate) ;
799 /* fmt : bytespersec */
800 psf_binheader_writef (psf, "4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ;
801 /* fmt : blockalign, bitwidth, extrabytes */
802 psf_binheader_writef (psf, "222", psf->bytewidth * psf->sf.channels, 8, 0) ;
803
804 add_fact_chunk = SF_TRUE ;
805 break ;
806
807 case SF_FORMAT_ALAW :
808 fmt_size = 2 + 2 + 4 + 4 + 2 + 2 + 2 ;
809
810 /* fmt : format, channels, samplerate */
811 psf_binheader_writef (psf, "4224", fmt_size, WAVE_FORMAT_ALAW, psf->sf.channels, psf->sf.samplerate) ;
812 /* fmt : bytespersec */
813 psf_binheader_writef (psf, "4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ;
814 /* fmt : blockalign, bitwidth, extrabytes */
815 psf_binheader_writef (psf, "222", psf->bytewidth * psf->sf.channels, 8, 0) ;
816
817 add_fact_chunk = SF_TRUE ;
818 break ;
819
820 /* Lite remove start */
821 case SF_FORMAT_IMA_ADPCM :
822 { int blockalign, framesperblock, bytespersec ;
823
824 blockalign = wav_w64_srate2blocksize (psf->sf.samplerate * psf->sf.channels) ;
825 framesperblock = 2 * (blockalign - 4 * psf->sf.channels) / psf->sf.channels + 1 ;
826 bytespersec = (psf->sf.samplerate * blockalign) / framesperblock ;
827
828 /* fmt chunk. */
829 fmt_size = 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 ;
830
831 /* fmt : size, WAV format type, channels, samplerate, bytespersec */
832 psf_binheader_writef (psf, "42244", fmt_size, WAVE_FORMAT_IMA_ADPCM,
833 psf->sf.channels, psf->sf.samplerate, bytespersec) ;
834
835 /* fmt : blockalign, bitwidth, extrabytes, framesperblock. */
836 psf_binheader_writef (psf, "2222", blockalign, 4, 2, framesperblock) ;
837 } ;
838
839 add_fact_chunk = SF_TRUE ;
840 break ;
841
842 case SF_FORMAT_MS_ADPCM :
843 { int blockalign, framesperblock, bytespersec, extrabytes ;
844
845 blockalign = wav_w64_srate2blocksize (psf->sf.samplerate * psf->sf.channels) ;
846 framesperblock = 2 + 2 * (blockalign - 7 * psf->sf.channels) / psf->sf.channels ;
847 bytespersec = (psf->sf.samplerate * blockalign) / framesperblock ;
848
849 /* fmt chunk. */
850 extrabytes = 2 + 2 + MSADPCM_ADAPT_COEFF_COUNT7 * (2 + 2) ;
851 fmt_size = 2 + 2 + 4 + 4 + 2 + 2 + 2 + extrabytes ;
852
853 /* fmt : size, WAV format type, channels. */
854 psf_binheader_writef (psf, "422", fmt_size, WAVE_FORMAT_MS_ADPCM, psf->sf.channels) ;
855
856 /* fmt : samplerate, bytespersec. */
857 psf_binheader_writef (psf, "44", psf->sf.samplerate, bytespersec) ;
858
859 /* fmt : blockalign, bitwidth, extrabytes, framesperblock. */
860 psf_binheader_writef (psf, "22222", blockalign, 4, extrabytes, framesperblock, 7) ;
861
862 msadpcm_write_adapt_coeffs (psf) ;
863 } ;
864
865 add_fact_chunk = SF_TRUE ;
866 break ;
867
868
869 case SF_FORMAT_G721_32 :
870 /* fmt chunk. */
871 fmt_size = 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 ;
872
873 /* fmt : size, WAV format type, channels, samplerate, bytespersec */
874 psf_binheader_writef (psf, "42244", fmt_size, WAVE_FORMAT_G721_ADPCM,
875 psf->sf.channels, psf->sf.samplerate, psf->sf.samplerate * psf->sf.channels / 2) ;
876
877 /* fmt : blockalign, bitwidth, extrabytes, auxblocksize. */
878 psf_binheader_writef (psf, "2222", 64, 4, 2, 0) ;
879
880 add_fact_chunk = SF_TRUE ;
881 break ;
882
883 /* Lite remove end */
884
885 case SF_FORMAT_GSM610 :
886 { int blockalign, framesperblock, bytespersec ;
887
888 blockalign = WAV_W64_GSM610_BLOCKSIZE65 ;
889 framesperblock = WAV_W64_GSM610_SAMPLES320 ;
890 bytespersec = (psf->sf.samplerate * blockalign) / framesperblock ;
891
892 /* fmt chunk. */
893 fmt_size = 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 ;
894
895 /* fmt : size, WAV format type, channels. */
896 psf_binheader_writef (psf, "422", fmt_size, WAVE_FORMAT_GSM610, psf->sf.channels) ;
897
898 /* fmt : samplerate, bytespersec. */
899 psf_binheader_writef (psf, "44", psf->sf.samplerate, bytespersec) ;
900
901 /* fmt : blockalign, bitwidth, extrabytes, framesperblock. */
902 psf_binheader_writef (psf, "2222", blockalign, 0, 2, framesperblock) ;
903 } ;
904
905 add_fact_chunk = SF_TRUE ;
906 break ;
907
908 default : return SFE_UNIMPLEMENTED ;
909 } ;
910
911 if (add_fact_chunk)
912 psf_binheader_writef (psf, "tm48", fact_MARKER(((uint32_t) (('f') | (('a') << 8) | (('c') << 16
) | (((uint32_t) ('t')) << 24))))
, 4, psf->sf.frames) ;
913
914 return 0 ;
915} /* wav_write_fmt_chunk */
916
917static int
918wavex_write_fmt_chunk (SF_PRIVATE *psf)
919{ WAV_PRIVATE *wpriv ;
920 int subformat, fmt_size, add_fact_chunk = 0 ;
921
922 if ((wpriv = psf->container_data) == NULL((void*)0))
923 return SFE_INTERNAL ;
924
925 subformat = SF_CODEC (psf->sf.format)((psf->sf.format) & SF_FORMAT_SUBMASK) ;
926
927 /* initial section (same for all, it appears) */
928 switch (subformat)
929 { case SF_FORMAT_PCM_U8 :
930 case SF_FORMAT_PCM_16 :
931 case SF_FORMAT_PCM_24 :
932 case SF_FORMAT_PCM_32 :
933 case SF_FORMAT_FLOAT :
934 case SF_FORMAT_DOUBLE :
935 case SF_FORMAT_ULAW :
936 case SF_FORMAT_ALAW :
937 fmt_size = 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 + 4 + 4 + 2 + 2 + 8 ;
938
939 /* fmt : format, channels, samplerate */
940 psf_binheader_writef (psf, "4224", fmt_size, WAVE_FORMAT_EXTENSIBLE, psf->sf.channels, psf->sf.samplerate) ;
941 /* fmt : bytespersec */
942 psf_binheader_writef (psf, "4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ;
943 /* fmt : blockalign, bitwidth */
944 psf_binheader_writef (psf, "22", psf->bytewidth * psf->sf.channels, psf->bytewidth * 8) ;
945
946 /* cbSize 22 is sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX) */
947 psf_binheader_writef (psf, "2", 22) ;
948
949 /* wValidBitsPerSample, for our use same as bitwidth as we use it fully */
950 psf_binheader_writef (psf, "2", psf->bytewidth * 8) ;
951
952 /* For an Ambisonic file set the channel mask to zero.
953 ** Otherwise use a default based on the channel count.
954 */
955 if (wpriv->wavex_ambisonic != SF_AMBISONIC_NONE)
956 psf_binheader_writef (psf, "4", 0) ;
957 else if (wpriv->wavex_channelmask != 0)
958 psf_binheader_writef (psf, "4", wpriv->wavex_channelmask) ;
959 else
960 { /*
961 ** Ok some liberty is taken here to use the most commonly used channel masks
962 ** instead of "no mapping". If you really want to use "no mapping" for 8 channels and less
963 ** please don't use wavex. (otherwise we'll have to create a new SF_COMMAND)
964 */
965 switch (psf->sf.channels)
966 { case 1 : /* center channel mono */
967 psf_binheader_writef (psf, "4", 0x4) ;
968 break ;
969
970 case 2 : /* front left and right */
971 psf_binheader_writef (psf, "4", 0x1 | 0x2) ;
972 break ;
973
974 case 4 : /* Quad */
975 psf_binheader_writef (psf, "4", 0x1 | 0x2 | 0x10 | 0x20) ;
976 break ;
977
978 case 6 : /* 5.1 */
979 psf_binheader_writef (psf, "4", 0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20) ;
980 break ;
981
982 case 8 : /* 7.1 */
983 psf_binheader_writef (psf, "4", 0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20 | 0x40 | 0x80) ;
984 break ;
985
986 default : /* 0 when in doubt , use direct out, ie NO mapping*/
987 psf_binheader_writef (psf, "4", 0x0) ;
988 break ;
989 } ;
990 } ;
991 break ;
992
993 case SF_FORMAT_MS_ADPCM : /* Todo, GUID exists might have different header as per wav_write_header */
994 default :
995 return SFE_UNIMPLEMENTED ;
996 } ;
997
998 /* GUID section, different for each */
999
1000 switch (subformat)
1001 { case SF_FORMAT_PCM_U8 :
1002 case SF_FORMAT_PCM_16 :
1003 case SF_FORMAT_PCM_24 :
1004 case SF_FORMAT_PCM_32 :
1005 wavex_write_guid (psf, wpriv->wavex_ambisonic == SF_AMBISONIC_NONE ?
1006 &MSGUID_SUBTYPE_PCM : &MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_PCM) ;
1007 break ;
1008
1009 case SF_FORMAT_FLOAT :
1010 case SF_FORMAT_DOUBLE :
1011 wavex_write_guid (psf, wpriv->wavex_ambisonic == SF_AMBISONIC_NONE ?
1012 &MSGUID_SUBTYPE_IEEE_FLOAT : &MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_IEEE_FLOAT) ;
1013 add_fact_chunk = SF_TRUE ;
1014 break ;
1015
1016 case SF_FORMAT_ULAW :
1017 wavex_write_guid (psf, &MSGUID_SUBTYPE_MULAW) ;
1018 add_fact_chunk = SF_TRUE ;
1019 break ;
1020
1021 case SF_FORMAT_ALAW :
1022 wavex_write_guid (psf, &MSGUID_SUBTYPE_ALAW) ;
1023 add_fact_chunk = SF_TRUE ;
1024 break ;
1025
1026#if 0
1027 /* This is dead code due to return in previous switch statement. */
1028 case SF_FORMAT_MS_ADPCM : /* todo, GUID exists */
1029 wavex_write_guid (psf, &MSGUID_SUBTYPE_MS_ADPCM) ;
1030 add_fact_chunk = SF_TRUE ;
1031 break ;
1032 return SFE_UNIMPLEMENTED ;
1033#endif
1034
1035 default : return SFE_UNIMPLEMENTED ;
1036 } ;
1037
1038 if (add_fact_chunk)
1039 psf_binheader_writef (psf, "tm48", fact_MARKER(((uint32_t) (('f') | (('a') << 8) | (('c') << 16
) | (((uint32_t) ('t')) << 24))))
, 4, psf->sf.frames) ;
1040
1041 return 0 ;
1042} /* wavex_write_fmt_chunk */
1043
1044
1045static int
1046wav_write_header (SF_PRIVATE *psf, int calc_length)
1047{ sf_count_t current ;
1048 uint32_t uk ;
1049 int k, error, has_data = SF_FALSE ;
1050
1051 current = psf_ftell (psf) ;
1052
1053 if (current > psf->dataoffset)
1054 has_data = SF_TRUE ;
1055
1056 if (calc_length)
1057 { psf->filelength = psf_get_filelen (psf) ;
1058
1059 psf->datalength = psf->filelength - psf->dataoffset ;
1060
1061 if (psf->dataend)
1062 psf->datalength -= psf->filelength - psf->dataend ;
1063 else if (psf->bytewidth > 0 && psf->sf.seekable == SF_TRUE)
1064 psf->datalength = psf->sf.frames * psf->bytewidth * psf->sf.channels ;
1065 } ;
1066
1067 /* Reset the current header length to zero. */
1068 psf->header [0] = 0 ;
1069 psf->headindex = 0 ;
1070 psf_fseek (psf, 0, SEEK_SET0) ;
1071
1072 /*
1073 ** RIFX signifies big-endian format for all header and data.
1074 ** To prevent lots of code copying here, we'll set the psf->rwf_endian flag
1075 ** once here, and never specify endian-ness for all other header operations.
1076 */
1077
1078 /* RIFF/RIFX marker, length, WAVE and 'fmt ' markers. */
1079
1080 if (psf->endian == SF_ENDIAN_LITTLE)
1081 psf_binheader_writef (psf, "etm8", RIFF_MARKER(((uint32_t) (('R') | (('I') << 8) | (('F') << 16
) | (((uint32_t) ('F')) << 24))))
, (psf->filelength < 8) ? 8 : psf->filelength - 8) ;
1082 else
1083 psf_binheader_writef (psf, "Etm8", RIFX_MARKER(((uint32_t) (('R') | (('I') << 8) | (('F') << 16
) | (((uint32_t) ('X')) << 24))))
, (psf->filelength < 8) ? 8 : psf->filelength - 8) ;
1084
1085 /* WAVE and 'fmt ' markers. */
1086 psf_binheader_writef (psf, "mm", WAVE_MARKER(((uint32_t) (('W') | (('A') << 8) | (('V') << 16
) | (((uint32_t) ('E')) << 24))))
, fmt_MARKER(((uint32_t) (('f') | (('m') << 8) | (('t') << 16
) | (((uint32_t) (' ')) << 24))))
) ;
1087
1088 /* Write the 'fmt ' chunk. */
1089 switch (SF_CONTAINER (psf->sf.format)((psf->sf.format) & SF_FORMAT_TYPEMASK))
1090 { case SF_FORMAT_WAV :
1091 if ((error = wav_write_fmt_chunk (psf)) != 0)
1092 return error ;
1093 break ;
1094
1095 case SF_FORMAT_WAVEX :
1096 if ((error = wavex_write_fmt_chunk (psf)) != 0)
1097 return error ;
1098 break ;
1099
1100 default :
1101 return SFE_UNIMPLEMENTED ;
1102 } ;
1103
1104 /* The LIST/INFO chunk. */
1105 if (psf->strings.flags & SF_STR_LOCATE_START)
1106 wav_write_strings (psf, SF_STR_LOCATE_START) ;
1107
1108 if (psf->peak_info != NULL((void*)0) && psf->peak_info->peak_loc == SF_PEAK_START)
1109 { psf_binheader_writef (psf, "m4", PEAK_MARKER(((uint32_t) (('P') | (('E') << 8) | (('A') << 16
) | (((uint32_t) ('K')) << 24))))
, WAV_PEAK_CHUNK_SIZE (psf->sf.channels)(2 * sizeof (int) + psf->sf.channels * (sizeof (float) + sizeof
(int)))
) ;
1110 psf_binheader_writef (psf, "44", 1, time (NULL((void*)0))) ;
1111 for (k = 0 ; k < psf->sf.channels ; k++)
1112 psf_binheader_writef (psf, "ft8", (float) psf->peak_info->peaks [k].value, psf->peak_info->peaks [k].position) ;
1113 } ;
1114
1115 if (psf->broadcast_16k != NULL((void*)0))
1116 wav_write_bext_chunk (psf) ;
1117
1118 if (psf->cart_16k != NULL((void*)0))
1119 wav_write_cart_chunk (psf) ;
1120
1121 if (psf->instrument != NULL((void*)0))
1122 { int tmp ;
1123 double dtune = (double) (0x40000000) / 25.0 ;
1124
1125 psf_binheader_writef (psf, "m4", smpl_MARKER(((uint32_t) (('s') | (('m') << 8) | (('p') << 16
) | (((uint32_t) ('l')) << 24))))
, 9 * 4 + psf->instrument->loop_count * 6 * 4) ;
1126 psf_binheader_writef (psf, "44", 0, 0) ; /* Manufacturer zero is everyone */
1127 tmp = (int) (1.0e9 / psf->sf.samplerate) ; /* Sample period in nano seconds */
1128 psf_binheader_writef (psf, "44", tmp, psf->instrument->basenote) ;
1129 tmp = (uint32_t) (psf->instrument->detune * dtune + 0.5) ;
1130 psf_binheader_writef (psf, "4", tmp) ;
1131 psf_binheader_writef (psf, "44", 0, 0) ; /* SMTPE format */
1132 psf_binheader_writef (psf, "44", psf->instrument->loop_count, 0) ;
1133
1134 for (tmp = 0 ; tmp < psf->instrument->loop_count ; tmp++)
1135 { int type ;
1136
1137 type = psf->instrument->loops [tmp].mode ;
1138 type = (type == SF_LOOP_FORWARD ? 0 : type == SF_LOOP_BACKWARD ? 2 : type == SF_LOOP_ALTERNATING ? 1 : 32) ;
1139
1140 psf_binheader_writef (psf, "44", tmp, type) ;
1141 psf_binheader_writef (psf, "44", psf->instrument->loops [tmp].start, psf->instrument->loops [tmp].end - 1) ;
1142 psf_binheader_writef (psf, "44", 0, psf->instrument->loops [tmp].count) ;
1143 } ;
1144 } ;
1145
1146 /* Write custom headers. */
1147 for (uk = 0 ; uk < psf->wchunks.used ; uk++)
1148 psf_binheader_writef (psf, "m4b", (int) psf->wchunks.chunks [uk].mark32, psf->wchunks.chunks [uk].len, psf->wchunks.chunks [uk].data, make_size_t (psf->wchunks.chunks [uk].len)) ;
1149
1150 if (psf->headindex + 16 < psf->dataoffset)
1151 { /* Add PAD data if necessary. */
1152 k = psf->dataoffset - (psf->headindex + 16) ;
1153 psf_binheader_writef (psf, "m4z", PAD_MARKER(((uint32_t) (('P') | (('A') << 8) | (('D') << 16
) | (((uint32_t) (' ')) << 24))))
, k, make_size_t (k)) ;
1154 } ;
1155
1156 psf_binheader_writef (psf, "tm8", data_MARKER(((uint32_t) (('d') | (('a') << 8) | (('t') << 16
) | (((uint32_t) ('a')) << 24))))
, psf->datalength) ;
1157 psf_fwrite (psf->header, psf->headindex, 1, psf) ;
1158 if (psf->error)
1159 return psf->error ;
1160
1161 if (has_data && psf->dataoffset != psf->headindex)
1162 { psf_log_printf (psf, "Oooops : has_data && psf->dataoffset != psf->headindex\n") ;
1163 return psf->error = SFE_INTERNAL ;
1164 } ;
1165
1166 psf->dataoffset = psf->headindex ;
1167
1168 if (! has_data)
1169 psf_fseek (psf, psf->dataoffset, SEEK_SET0) ;
1170 else if (current > 0)
1171 psf_fseek (psf, current, SEEK_SET0) ;
1172
1173 return psf->error ;
1174} /* wav_write_header */
1175
1176
1177static int
1178wav_write_tailer (SF_PRIVATE *psf)
1179{ int k ;
1180
1181 /* Reset the current header buffer length to zero. */
1182 psf->header [0] = 0 ;
1183 psf->headindex = 0 ;
1184
1185 if (psf->bytewidth > 0 && psf->sf.seekable == SF_TRUE)
1186 { psf->datalength = psf->sf.frames * psf->bytewidth * psf->sf.channels ;
1187 psf->dataend = psf->dataoffset + psf->datalength ;
1188 } ;
1189
1190 if (psf->dataend > 0)
1191 psf_fseek (psf, psf->dataend, SEEK_SET0) ;
1192 else
1193 psf->dataend = psf_fseek (psf, 0, SEEK_END2) ;
1194
1195 /* Add a PEAK chunk if requested. */
1196 if (psf->peak_info != NULL((void*)0) && psf->peak_info->peak_loc == SF_PEAK_END)
1197 { psf_binheader_writef (psf, "m4", PEAK_MARKER(((uint32_t) (('P') | (('E') << 8) | (('A') << 16
) | (((uint32_t) ('K')) << 24))))
, WAV_PEAK_CHUNK_SIZE (psf->sf.channels)(2 * sizeof (int) + psf->sf.channels * (sizeof (float) + sizeof
(int)))
) ;
1198 psf_binheader_writef (psf, "44", 1, time (NULL((void*)0))) ;
1199 for (k = 0 ; k < psf->sf.channels ; k++)
1200 psf_binheader_writef (psf, "f4", psf->peak_info->peaks [k].value, psf->peak_info->peaks [k].position) ;
1201 } ;
1202
1203 if (psf->strings.flags & SF_STR_LOCATE_END)
1204 wav_write_strings (psf, SF_STR_LOCATE_END) ;
1205
1206 /* Write the tailer. */
1207 if (psf->headindex > 0)
1208 psf_fwrite (psf->header, psf->headindex, 1, psf) ;
1209
1210 return 0 ;
1211} /* wav_write_tailer */
1212
1213static void
1214wav_write_strings (SF_PRIVATE *psf, int location)
1215{ int k, prev_head_index, saved_head_index ;
1216
1217 if (psf_location_string_count (psf, location) == 0)
1218 return ;
1219
1220 prev_head_index = psf->headindex + 4 ;
1221
1222 psf_binheader_writef (psf, "m4m", LIST_MARKER(((uint32_t) (('L') | (('I') << 8) | (('S') << 16
) | (((uint32_t) ('T')) << 24))))
, 0xBADBAD, INFO_MARKER(((uint32_t) (('I') | (('N') << 8) | (('F') << 16
) | (((uint32_t) ('O')) << 24))))
) ;
1223
1224 for (k = 0 ; k < SF_MAX_STRINGS(32) ; k++)
1225 { if (psf->strings.data [k].type == 0)
1226 break ;
1227 if (psf->strings.data [k].type < 0 || psf->strings.data [k].flags != location)
1228 continue ;
1229
1230 switch (psf->strings.data [k].type)
1231 { case SF_STR_SOFTWARE :
1232 psf_binheader_writef (psf, "ms", ISFT_MARKER(((uint32_t) (('I') | (('S') << 8) | (('F') << 16
) | (((uint32_t) ('T')) << 24))))
, psf->strings.storage + psf->strings.data [k].offset) ;
1233 break ;
1234
1235 case SF_STR_TITLE :
1236 psf_binheader_writef (psf, "ms", INAM_MARKER(((uint32_t) (('I') | (('N') << 8) | (('A') << 16
) | (((uint32_t) ('M')) << 24))))
, psf->strings.storage + psf->strings.data [k].offset) ;
1237 break ;
1238
1239 case SF_STR_COPYRIGHT :
1240 psf_binheader_writef (psf, "ms", ICOP_MARKER(((uint32_t) (('I') | (('C') << 8) | (('O') << 16
) | (((uint32_t) ('P')) << 24))))
, psf->strings.storage + psf->strings.data [k].offset) ;
1241 break ;
1242
1243 case SF_STR_ARTIST :
1244 psf_binheader_writef (psf, "ms", IART_MARKER(((uint32_t) (('I') | (('A') << 8) | (('R') << 16
) | (((uint32_t) ('T')) << 24))))
, psf->strings.storage + psf->strings.data [k].offset) ;
1245 break ;
1246
1247 case SF_STR_COMMENT :
1248 psf_binheader_writef (psf, "ms", ICMT_MARKER(((uint32_t) (('I') | (('C') << 8) | (('M') << 16
) | (((uint32_t) ('T')) << 24))))
, psf->strings.storage + psf->strings.data [k].offset) ;
1249 break ;
1250
1251 case SF_STR_DATE :
1252 psf_binheader_writef (psf, "ms", ICRD_MARKER(((uint32_t) (('I') | (('C') << 8) | (('R') << 16
) | (((uint32_t) ('D')) << 24))))
, psf->strings.storage + psf->strings.data [k].offset) ;
1253 break ;
1254
1255 case SF_STR_GENRE :
1256 psf_binheader_writef (psf, "ms", IGNR_MARKER(((uint32_t) (('I') | (('G') << 8) | (('N') << 16
) | (((uint32_t) ('R')) << 24))))
, psf->strings.storage + psf->strings.data [k].offset) ;
1257 break ;
1258
1259 case SF_STR_ALBUM :
1260 psf_binheader_writef (psf, "ms", IPRD_MARKER(((uint32_t) (('I') | (('P') << 8) | (('R') << 16
) | (((uint32_t) ('D')) << 24))))
, psf->strings.storage + psf->strings.data [k].offset) ;
1261 break ;
1262
1263 case SF_STR_TRACKNUMBER :
1264 psf_binheader_writef (psf, "ms", ITRK_MARKER(((uint32_t) (('I') | (('T') << 8) | (('R') << 16
) | (((uint32_t) ('K')) << 24))))
, psf->strings.storage + psf->strings.data [k].offset) ;
1265 break ;
1266
1267 default :
1268 break ;
1269 } ;
1270 } ;
1271
1272 saved_head_index = psf->headindex ;
1273 psf->headindex = prev_head_index ;
1274 psf_binheader_writef (psf, "4", saved_head_index - prev_head_index - 4) ;
1275 psf->headindex = saved_head_index ;
1276
1277} /* wav_write_strings */
1278
1279static int
1280wav_close (SF_PRIVATE *psf)
1281{
1282 if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
1283 { wav_write_tailer (psf) ;
1284
1285 if (psf->file.mode == SFM_RDWR)
1286 { sf_count_t current = psf_ftell (psf) ;
1287
1288 /*
1289 ** If the mode is RDWR and the current position is less than the
1290 ** filelength, truncate the file.
1291 */
1292
1293 if (current < psf->filelength)
1294 { psf_ftruncate (psf, current) ;
1295 psf->filelength = current ;
1296 } ;
1297 } ;
1298
1299 psf->write_header (psf, SF_TRUE) ;
1300 } ;
1301
1302 return 0 ;
1303} /* wav_close */
1304
1305static int
1306wav_command (SF_PRIVATE *psf, int command, void * UNUSED (data)UNUSED_data __attribute__ ((unused)), int datasize)
1307{ WAV_PRIVATE *wpriv ;
1308
1309 if ((wpriv = psf->container_data) == NULL((void*)0))
1310 return SFE_INTERNAL ;
1311
1312 switch (command)
1313 { case SFC_WAVEX_SET_AMBISONIC :
1314 if ((SF_CONTAINER (psf->sf.format)((psf->sf.format) & SF_FORMAT_TYPEMASK)) == SF_FORMAT_WAVEX)
1315 { if (datasize == SF_AMBISONIC_NONE)
1316 wpriv->wavex_ambisonic = SF_AMBISONIC_NONE ;
1317 else if (datasize == SF_AMBISONIC_B_FORMAT)
1318 wpriv->wavex_ambisonic = SF_AMBISONIC_B_FORMAT ;
1319 else
1320 return 0 ;
1321 } ;
1322 return wpriv->wavex_ambisonic ;
1323
1324 case SFC_WAVEX_GET_AMBISONIC :
1325 return wpriv->wavex_ambisonic ;
1326
1327 case SFC_SET_CHANNEL_MAP_INFO :
1328 wpriv->wavex_channelmask = wavex_gen_channel_mask (psf->channel_map, psf->sf.channels) ;
1329 return (wpriv->wavex_channelmask != 0) ;
1330
1331 default :
1332 break ;
1333 } ;
1334
1335 return 0 ;
1336} /* wav_command */
1337
1338static int
1339wav_subchunk_parse (SF_PRIVATE *psf, int chunk, uint32_t chunk_length)
1340{ sf_count_t current_pos ;
1341 char buffer [512] ;
1342 uint32_t dword, bytesread ;
1343
1344 current_pos = psf_fseek (psf, 0, SEEK_CUR1) - 4 ;
1345
1346 bytesread = sizeof (chunk_length) ;
1347
1348 if (chunk_length <= 8)
1349 { /* This case is for broken files generated by PEAK. */
1350 psf_log_printf (psf, "%M : %d (weird length)\n", chunk, chunk_length) ;
1351 psf_binheader_readf (psf, "mj", &chunk, chunk_length - 4) ;
1352 psf_log_printf (psf, " %M\n", chunk) ;
1353 return 0 ;
1354 } ;
1355
1356 if (psf->headindex + chunk_length > SIGNED_SIZEOF (psf->header)((int) sizeof (psf->header)))
1357 { psf_log_printf (psf, "%M : %d (too long)\n", chunk, chunk_length) ;
1358 psf_binheader_readf (psf, "j", chunk_length) ;
1359 return 0 ;
1360 } ;
1361
1362 if (current_pos + chunk_length > psf->filelength)
1363 { psf_log_printf (psf, "%M : %d (should be %d)\n", chunk, chunk_length, (int) (psf->filelength - current_pos)) ;
1364 chunk_length = psf->filelength - current_pos ;
1365 }
1366 else
1367 psf_log_printf (psf, "%M : %d\n", chunk, chunk_length) ;
1368
1369 while (bytesread < chunk_length)
1370 { bytesread += psf_binheader_readf (psf, "m", &chunk) ;
1371
1372 switch (chunk)
1373 { case adtl_MARKER(((uint32_t) (('a') | (('d') << 8) | (('t') << 16
) | (((uint32_t) ('l')) << 24))))
:
1374 case INFO_MARKER(((uint32_t) (('I') | (('N') << 8) | (('F') << 16
) | (((uint32_t) ('O')) << 24))))
:
1375 /* These markers don't contain anything, not even a chunk lebgth. */
1376 psf_log_printf (psf, " %M\n", chunk) ;
1377 continue ;
1378
1379 case exif_MARKER(((uint32_t) (('e') | (('x') << 8) | (('i') << 16
) | (((uint32_t) ('f')) << 24))))
:
1380 psf_log_printf (psf, " %M\n", chunk) ;
1381 bytesread += exif_subchunk_parse (psf, chunk_length - bytesread) ;
1382 continue ;
1383
1384 case data_MARKER(((uint32_t) (('d') | (('a') << 8) | (('t') << 16
) | (((uint32_t) ('a')) << 24))))
:
1385 psf_log_printf (psf, " %M inside a LIST block??? Backing out.\n", chunk) ;
1386 /* Jump back four bytes and return to caller. */
1387 psf_binheader_readf (psf, "j", -4) ;
1388 return 0 ;
1389
1390 case 0 :
1391 /*
1392 ** Four zero bytes where a marker was expected. Assume this means
1393 ** the rest of the chunk is garbage.
1394 */
1395 psf_log_printf (psf, " *** Found weird-ass zero marker. Jumping to end of chunk.\n") ;
1396 if (bytesread < chunk_length)
1397 bytesread += psf_binheader_readf (psf, "j", chunk_length - bytesread + 4) ;
1398 psf_log_printf (psf, " *** Offset is now : 0x%X\n", psf_fseek (psf, 0, SEEK_CUR1)) ;
1399 return 0 ;
1400
1401 default :
1402 break ;
1403 } ;
1404
1405 switch (chunk)
1406 { case ISFT_MARKER(((uint32_t) (('I') | (('S') << 8) | (('F') << 16
) | (((uint32_t) ('T')) << 24))))
:
1407 case ICOP_MARKER(((uint32_t) (('I') | (('C') << 8) | (('O') << 16
) | (((uint32_t) ('P')) << 24))))
:
1408 case IARL_MARKER(((uint32_t) (('I') | (('A') << 8) | (('R') << 16
) | (((uint32_t) ('L')) << 24))))
:
1409 case IART_MARKER(((uint32_t) (('I') | (('A') << 8) | (('R') << 16
) | (((uint32_t) ('T')) << 24))))
:
1410 case ICMT_MARKER(((uint32_t) (('I') | (('C') << 8) | (('M') << 16
) | (((uint32_t) ('T')) << 24))))
:
1411 case ICRD_MARKER(((uint32_t) (('I') | (('C') << 8) | (('R') << 16
) | (((uint32_t) ('D')) << 24))))
:
1412 case IENG_MARKER(((uint32_t) (('I') | (('E') << 8) | (('N') << 16
) | (((uint32_t) ('G')) << 24))))
:
1413 case IGNR_MARKER(((uint32_t) (('I') | (('G') << 8) | (('N') << 16
) | (((uint32_t) ('R')) << 24))))
:
1414 case INAM_MARKER(((uint32_t) (('I') | (('N') << 8) | (('A') << 16
) | (((uint32_t) ('M')) << 24))))
:
1415 case IPRD_MARKER(((uint32_t) (('I') | (('P') << 8) | (('R') << 16
) | (((uint32_t) ('D')) << 24))))
:
1416 case ISBJ_MARKER(((uint32_t) (('I') | (('S') << 8) | (('B') << 16
) | (((uint32_t) ('J')) << 24))))
:
1417 case ISRC_MARKER(((uint32_t) (('I') | (('S') << 8) | (('R') << 16
) | (((uint32_t) ('C')) << 24))))
:
1418 case IAUT_MARKER(((uint32_t) (('I') | (('A') << 8) | (('U') << 16
) | (((uint32_t) ('T')) << 24))))
:
1419 case ITRK_MARKER(((uint32_t) (('I') | (('T') << 8) | (('R') << 16
) | (((uint32_t) ('K')) << 24))))
:
1420 bytesread += psf_binheader_readf (psf, "4", &dword) ;
1421 dword += (dword & 1) ;
1422 if (dword >= SIGNED_SIZEOF (buffer)((int) sizeof (buffer)))
1423 { psf_log_printf (psf, " *** %M : %d (too big)\n", chunk, dword) ;
1424 psf_binheader_readf (psf, "j", dword) ;
1425 break ;
1426 } ;
1427
1428 bytesread += psf_binheader_readf (psf, "b", buffer, dword) ;
1429 buffer [dword] = 0 ;
1430 psf_log_printf (psf, " %M : %s\n", chunk, buffer) ;
1431 break ;
1432
1433 case labl_MARKER(((uint32_t) (('l') | (('a') << 8) | (('b') << 16
) | (((uint32_t) ('l')) << 24))))
:
1434 { int mark_id ;
1435
1436 bytesread += psf_binheader_readf (psf, "44", &dword, &mark_id) ;
1437 dword -= 4 ;
1438 dword += (dword & 1) ;
1439 if (dword < 1 || dword >= SIGNED_SIZEOF (buffer)((int) sizeof (buffer)))
1440 { psf_log_printf (psf, " *** %M : %d (too big)\n", chunk, dword) ;
1441 psf_binheader_readf (psf, "j", dword) ;
1442 break ;
1443 } ;
1444
1445 bytesread += psf_binheader_readf (psf, "b", buffer, dword) ;
1446 buffer [dword] = 0 ;
1447 psf_log_printf (psf, " %M : %d : %s\n", chunk, mark_id, buffer) ;
1448 } ;
1449 break ;
1450
1451
1452 case DISP_MARKER(((uint32_t) (('D') | (('I') << 8) | (('S') << 16
) | (((uint32_t) ('P')) << 24))))
:
1453 case ltxt_MARKER(((uint32_t) (('l') | (('t') << 8) | (('x') << 16
) | (((uint32_t) ('t')) << 24))))
:
1454 case note_MARKER(((uint32_t) (('n') | (('o') << 8) | (('t') << 16
) | (((uint32_t) ('e')) << 24))))
:
1455 bytesread += psf_binheader_readf (psf, "4", &dword) ;
1456 dword += (dword & 1) ;
1457 bytesread += psf_binheader_readf (psf, "j", dword) ;
1458 psf_log_printf (psf, " %M : %d\n", chunk, dword) ;
1459 break ;
1460
1461 default :
1462 bytesread += psf_binheader_readf (psf, "4", &dword) ;
1463 dword += (dword & 1) ;
1464 psf_log_printf (psf, " *** %M : %d\n", chunk, dword) ;
1465 if (bytesread + dword > chunk_length)
1466 { bytesread += psf_binheader_readf (psf, "j", chunk_length - bytesread + 4) ;
1467 continue ;
1468 }
1469 else
1470 bytesread += psf_binheader_readf (psf, "j", dword) ;
1471
1472 if (dword >= chunk_length)
1473 return 0 ;
1474 break ;
1475 } ;
1476
1477 switch (chunk)
1478 { case ISFT_MARKER(((uint32_t) (('I') | (('S') << 8) | (('F') << 16
) | (((uint32_t) ('T')) << 24))))
:
1479 psf_store_string (psf, SF_STR_SOFTWARE, buffer) ;
1480 break ;
1481 case ICOP_MARKER(((uint32_t) (('I') | (('C') << 8) | (('O') << 16
) | (((uint32_t) ('P')) << 24))))
:
1482 psf_store_string (psf, SF_STR_COPYRIGHT, buffer) ;
1483 break ;
1484 case INAM_MARKER(((uint32_t) (('I') | (('N') << 8) | (('A') << 16
) | (((uint32_t) ('M')) << 24))))
:
1485 psf_store_string (psf, SF_STR_TITLE, buffer) ;
1486 break ;
1487 case IART_MARKER(((uint32_t) (('I') | (('A') << 8) | (('R') << 16
) | (((uint32_t) ('T')) << 24))))
:
1488 psf_store_string (psf, SF_STR_ARTIST, buffer) ;
1489 break ;
1490 case ICMT_MARKER(((uint32_t) (('I') | (('C') << 8) | (('M') << 16
) | (((uint32_t) ('T')) << 24))))
:
1491 psf_store_string (psf, SF_STR_COMMENT, buffer) ;
1492 break ;
1493 case ICRD_MARKER(((uint32_t) (('I') | (('C') << 8) | (('R') << 16
) | (((uint32_t) ('D')) << 24))))
:
1494 psf_store_string (psf, SF_STR_DATE, buffer) ;
1495 break ;
1496 case IGNR_MARKER(((uint32_t) (('I') | (('G') << 8) | (('N') << 16
) | (((uint32_t) ('R')) << 24))))
:
1497 psf_store_string (psf, SF_STR_GENRE, buffer) ;
1498 break ;
1499 case IPRD_MARKER(((uint32_t) (('I') | (('P') << 8) | (('R') << 16
) | (((uint32_t) ('D')) << 24))))
:
1500 psf_store_string (psf, SF_STR_ALBUM, buffer) ;
1501 break ;
1502 case ITRK_MARKER(((uint32_t) (('I') | (('T') << 8) | (('R') << 16
) | (((uint32_t) ('K')) << 24))))
:
1503 psf_store_string (psf, SF_STR_TRACKNUMBER, buffer) ;
1504 break ;
1505 } ;
1506 } ;
1507
1508 current_pos = psf_fseek (psf, 0, SEEK_CUR1) - current_pos ;
1509
1510 if (current_pos - 4 != chunk_length)
1511 psf_log_printf (psf, "**** Bad chunk length %d sbould be %D\n", chunk_length, current_pos - 4) ;
1512
1513 return 0 ;
1514} /* wav_subchunk_parse */
1515
1516static int
1517wav_read_smpl_chunk (SF_PRIVATE *psf, uint32_t chunklen)
1518{ char buffer [512] ;
1519 uint32_t bytesread = 0, dword, sampler_data, loop_count ;
1520 uint32_t note, start, end, type = -1, count ;
1521 int j, k ;
1522
1523 chunklen += (chunklen & 1) ;
1524
1525 bytesread += psf_binheader_readf (psf, "4", &dword) ;
1526 psf_log_printf (psf, " Manufacturer : %X\n", dword) ;
1527
1528 bytesread += psf_binheader_readf (psf, "4", &dword) ;
1529 psf_log_printf (psf, " Product : %u\n", dword) ;
1530
1531 bytesread += psf_binheader_readf (psf, "4", &dword) ;
1532 psf_log_printf (psf, " Period : %u nsec\n", dword) ;
1533
1534 bytesread += psf_binheader_readf (psf, "4", &note) ;
1535 psf_log_printf (psf, " Midi Note : %u\n", note) ;
1536
1537 bytesread += psf_binheader_readf (psf, "4", &dword) ;
1538 if (dword != 0)
1539 { snprintf (buffer, sizeof (buffer), "%f",__builtin___snprintf_chk (buffer, sizeof (buffer), 2 - 1, __builtin_object_size
(buffer, 2 > 1), "%f", (1.0 * 0x80000000) / ((uint32_t) dword
))
1540 (1.0 * 0x80000000) / ((uint32_t) dword))__builtin___snprintf_chk (buffer, sizeof (buffer), 2 - 1, __builtin_object_size
(buffer, 2 > 1), "%f", (1.0 * 0x80000000) / ((uint32_t) dword
))
;
1541 psf_log_printf (psf, " Pitch Fract. : %s\n", buffer) ;
1542 }
1543 else
1544 psf_log_printf (psf, " Pitch Fract. : 0\n") ;
1545
1546 bytesread += psf_binheader_readf (psf, "4", &dword) ;
1547 psf_log_printf (psf, " SMPTE Format : %u\n", dword) ;
1548
1549 bytesread += psf_binheader_readf (psf, "4", &dword) ;
1550 snprintf (buffer, sizeof (buffer), "%02d:%02d:%02d %02d",__builtin___snprintf_chk (buffer, sizeof (buffer), 2 - 1, __builtin_object_size
(buffer, 2 > 1), "%02d:%02d:%02d %02d", (dword >> 24
) & 0x7F, (dword >> 16) & 0x7F, (dword >>
8) & 0x7F, dword & 0x7F)
1551 (dword >> 24) & 0x7F, (dword >> 16) & 0x7F, (dword >> 8) & 0x7F, dword & 0x7F)__builtin___snprintf_chk (buffer, sizeof (buffer), 2 - 1, __builtin_object_size
(buffer, 2 > 1), "%02d:%02d:%02d %02d", (dword >> 24
) & 0x7F, (dword >> 16) & 0x7F, (dword >>
8) & 0x7F, dword & 0x7F)
;
1552 psf_log_printf (psf, " SMPTE Offset : %s\n", buffer) ;
1553
1554 bytesread += psf_binheader_readf (psf, "4", &loop_count) ;
1555 psf_log_printf (psf, " Loop Count : %u\n", loop_count) ;
1556
1557 /* Sampler Data holds the number of data bytes after the CUE chunks which
1558 ** is not actually CUE data. Display value after CUE data.
1559 */
1560 bytesread += psf_binheader_readf (psf, "4", &sampler_data) ;
1561
1562 if ((psf->instrument = psf_instrument_alloc ()) == NULL((void*)0))
1563 return SFE_MALLOC_FAILED ;
1564
1565 psf->instrument->loop_count = loop_count ;
1566
1567 for (j = 0 ; loop_count > 0 && chunklen - bytesread >= 24 ; j ++)
1568 { bytesread += psf_binheader_readf (psf, "4", &dword) ;
1569 psf_log_printf (psf, " Cue ID : %2u", dword) ;
1570
1571 bytesread += psf_binheader_readf (psf, "4", &type) ;
1572 psf_log_printf (psf, " Type : %2u", type) ;
1573
1574 bytesread += psf_binheader_readf (psf, "4", &start) ;
1575 psf_log_printf (psf, " Start : %5u", start) ;
1576
1577 bytesread += psf_binheader_readf (psf, "4", &end) ;
1578 psf_log_printf (psf, " End : %5u", end) ;
1579
1580 bytesread += psf_binheader_readf (psf, "4", &dword) ;
1581 psf_log_printf (psf, " Fraction : %5u", dword) ;
1582
1583 bytesread += psf_binheader_readf (psf, "4", &count) ;
1584 psf_log_printf (psf, " Count : %5u\n", count) ;
1585
1586 if (j < ARRAY_LEN (psf->instrument->loops)((int) (sizeof (psf->instrument->loops) / sizeof ((psf->
instrument->loops) [0])))
)
1587 { psf->instrument->loops [j].start = start ;
1588 psf->instrument->loops [j].end = end + 1 ;
1589 psf->instrument->loops [j].count = count ;
1590
1591 switch (type)
1592 { case 0 :
1593 psf->instrument->loops [j].mode = SF_LOOP_FORWARD ;
1594 break ;
1595 case 1 :
1596 psf->instrument->loops [j].mode = SF_LOOP_ALTERNATING ;
1597 break ;
1598 case 2 :
1599 psf->instrument->loops [j].mode = SF_LOOP_BACKWARD ;
1600 break ;
1601 default:
1602 psf->instrument->loops [j].mode = SF_LOOP_NONE ;
1603 break ;
1604 } ;
1605 } ;
1606
1607 loop_count -- ;
1608 } ;
1609
1610 if (chunklen - bytesread == 0)
1611 { if (sampler_data != 0)
1612 psf_log_printf (psf, " Sampler Data : %u (should be 0)\n", sampler_data) ;
1613 else
1614 psf_log_printf (psf, " Sampler Data : %u\n", sampler_data) ;
1615 }
1616 else
1617 { if (sampler_data != chunklen - bytesread)
1618 { psf_log_printf (psf, " Sampler Data : %u (should have been %u)\n", sampler_data, chunklen - bytesread) ;
1619 sampler_data = chunklen - bytesread ;
1620 }
1621 else
1622 psf_log_printf (psf, " Sampler Data : %u\n", sampler_data) ;
1623
1624 psf_log_printf (psf, " ") ;
1625 for (k = 0 ; k < (int) sampler_data ; k++)
1626 { char ch ;
1627
1628 if (k > 0 && (k % 20) == 0)
1629 psf_log_printf (psf, "\n ") ;
1630
1631 bytesread += psf_binheader_readf (psf, "1", &ch) ;
1632 psf_log_printf (psf, "%02X ", ch & 0xFF) ;
1633 } ;
1634
1635 psf_log_printf (psf, "\n") ;
1636 } ;
1637
1638 psf->instrument->basenote = note ;
1639 psf->instrument->gain = 1 ;
1640 psf->instrument->velocity_lo = psf->instrument->key_lo = 0 ;
1641 psf->instrument->velocity_hi = psf->instrument->key_hi = 127 ;
1642
1643 return 0 ;
1644} /* wav_read_smpl_chunk */
1645
1646/*
1647** The acid chunk goes a little something like this:
1648**
1649** 4 bytes 'acid'
1650** 4 bytes (int) length of chunk starting at next byte
1651**
1652** 4 bytes (int) type of file:
1653** this appears to be a bit mask,however some combinations
1654** are probably impossible and/or qualified as "errors"
1655**
1656** 0x01 On: One Shot Off: Loop
1657** 0x02 On: Root note is Set Off: No root
1658** 0x04 On: Stretch is On, Off: Strech is OFF
1659** 0x08 On: Disk Based Off: Ram based
1660** 0x10 On: ?????????? Off: ????????? (Acidizer puts that ON)
1661**
1662** 2 bytes (short) root note
1663** if type 0x10 is OFF : [C,C#,(...),B] -> [0x30 to 0x3B]
1664** if type 0x10 is ON : [C,C#,(...),B] -> [0x3C to 0x47]
1665** (both types fit on same MIDI pitch albeit different octaves, so who cares)
1666**
1667** 2 bytes (short) ??? always set to 0x8000
1668** 4 bytes (float) ??? seems to be always 0
1669** 4 bytes (int) number of beats
1670** 2 bytes (short) meter denominator //always 4 in SF/ACID
1671** 2 bytes (short) meter numerator //always 4 in SF/ACID
1672** //are we sure about the order?? usually its num/denom
1673** 4 bytes (float) tempo
1674**
1675*/
1676
1677static int
1678wav_read_acid_chunk (SF_PRIVATE *psf, uint32_t chunklen)
1679{ char buffer [512] ;
1680 uint32_t bytesread = 0 ;
1681 int beats, flags ;
1682 short rootnote, q1, meter_denom, meter_numer ;
1683 float q2, tempo ;
1684
1685 chunklen += (chunklen & 1) ;
1686
1687 bytesread += psf_binheader_readf (psf, "422f", &flags, &rootnote, &q1, &q2) ;
1688
1689 snprintf (buffer, sizeof (buffer), "%f", q2)__builtin___snprintf_chk (buffer, sizeof (buffer), 2 - 1, __builtin_object_size
(buffer, 2 > 1), "%f", q2)
;
1690
1691 psf_log_printf (psf, " Flags : 0x%04x (%s,%s,%s,%s,%s)\n", flags,
1692 (flags & 0x01) ? "OneShot" : "Loop",
1693 (flags & 0x02) ? "RootNoteValid" : "RootNoteInvalid",
1694 (flags & 0x04) ? "StretchOn" : "StretchOff",
1695 (flags & 0x08) ? "DiskBased" : "RAMBased",
1696 (flags & 0x10) ? "??On" : "??Off") ;
1697
1698 psf_log_printf (psf, " Root note : 0x%x\n ???? : 0x%04x\n ???? : %s\n",
1699 rootnote, q1, buffer) ;
1700
1701 bytesread += psf_binheader_readf (psf, "422f", &beats, &meter_denom, &meter_numer, &tempo) ;
1702 snprintf (buffer, sizeof (buffer), "%f", tempo)__builtin___snprintf_chk (buffer, sizeof (buffer), 2 - 1, __builtin_object_size
(buffer, 2 > 1), "%f", tempo)
;
1703 psf_log_printf (psf, " Beats : %d\n Meter : %d/%d\n Tempo : %s\n",
1704 beats, meter_numer, meter_denom, buffer) ;
1705
1706 psf_binheader_readf (psf, "j", chunklen - bytesread) ;
1707
1708 if ((psf->loop_info = calloc (1, sizeof (SF_LOOP_INFO))) == NULL((void*)0))
1709 return SFE_MALLOC_FAILED ;
1710
1711 psf->loop_info->time_sig_num = meter_numer ;
1712 psf->loop_info->time_sig_den = meter_denom ;
1713 psf->loop_info->loop_mode = (flags & 0x01) ? SF_LOOP_NONE : SF_LOOP_FORWARD ;
1714 psf->loop_info->num_beats = beats ;
1715 psf->loop_info->bpm = tempo ;
1716 psf->loop_info->root_key = (flags & 0x02) ? rootnote : -1 ;
1717
1718 return 0 ;
1719} /* wav_read_acid_chunk */
1720
1721int
1722wav_read_bext_chunk (SF_PRIVATE *psf, uint32_t chunksize)
1723{
1724 SF_BROADCAST_INFO_16K * b ;
1725 uint32_t bytes = 0 ;
1726
1727 if (chunksize < WAV_BEXT_MIN_CHUNK_SIZE602)
1728 { psf_log_printf (psf, "bext : %u (should be >= %d)\n", chunksize, WAV_BEXT_MIN_CHUNK_SIZE602) ;
1729 psf_binheader_readf (psf, "j", chunksize) ;
1730 return 0 ;
1731 } ;
1732
1733 if (chunksize > WAV_BEXT_MAX_CHUNK_SIZE(10 * 1024))
1734 { psf_log_printf (psf, "bext : %u (should be < %d)\n", chunksize, WAV_BEXT_MAX_CHUNK_SIZE(10 * 1024)) ;
1735 psf_binheader_readf (psf, "j", chunksize) ;
1736 return 0 ;
1737 } ;
1738
1739 if (chunksize >= sizeof (SF_BROADCAST_INFO_16K))
1740 { psf_log_printf (psf, "bext : %u too big to be handled\n", chunksize) ;
1741 psf_binheader_readf (psf, "j", chunksize) ;
1742 return 0 ;
1743 } ;
1744
1745 psf_log_printf (psf, "bext : %u\n", chunksize) ;
1746
1747 if ((psf->broadcast_16k = broadcast_var_alloc ()) == NULL((void*)0))
1748 { psf->error = SFE_MALLOC_FAILED ;
1749 return psf->error ;
1750 } ;
1751
1752 b = psf->broadcast_16k ;
1753
1754 bytes += psf_binheader_readf (psf, "b", b->description, sizeof (b->description)) ;
1755 bytes += psf_binheader_readf (psf, "b", b->originator, sizeof (b->originator)) ;
1756 bytes += psf_binheader_readf (psf, "b", b->originator_reference, sizeof (b->originator_reference)) ;
1757 bytes += psf_binheader_readf (psf, "b", b->origination_date, sizeof (b->origination_date)) ;
1758 bytes += psf_binheader_readf (psf, "b", b->origination_time, sizeof (b->origination_time)) ;
1759 bytes += psf_binheader_readf (psf, "442", &b->time_reference_low, &b->time_reference_high, &b->version) ;
1760 bytes += psf_binheader_readf (psf, "bj", &b->umid, sizeof (b->umid), 190) ;
1761
1762 if (chunksize > WAV_BEXT_MIN_CHUNK_SIZE602)
1763 { /* File has coding history data. */
1764
1765 b->coding_history_size = chunksize - WAV_BEXT_MIN_CHUNK_SIZE602 ;
1766
1767 /* We do not parse the coding history */
1768 bytes += psf_binheader_readf (psf, "b", b->coding_history, b->coding_history_size) ;
1769 } ;
1770
1771 if (bytes < chunksize)
1772 psf_binheader_readf (psf, "j", chunksize - bytes) ;
1773
1774 return 0 ;
1775} /* wav_read_bext_chunk */
1776
1777int
1778wav_write_bext_chunk (SF_PRIVATE *psf)
1779{ SF_BROADCAST_INFO_16K *b ;
1780
1781 if (psf->broadcast_16k == NULL((void*)0))
1782 return -1 ;
1783
1784 b = psf->broadcast_16k ;
1785
1786 psf_binheader_writef (psf, "m4", bext_MARKER(((uint32_t) (('b') | (('e') << 8) | (('x') << 16
) | (((uint32_t) ('t')) << 24))))
, WAV_BEXT_MIN_CHUNK_SIZE602 + b->coding_history_size) ;
1787
1788 /*
1789 ** Note that it is very important the the field widths of the SF_BROADCAST_INFO
1790 ** struct match those for the bext chunk fields.
1791 */
1792
1793 psf_binheader_writef (psf, "b", b->description, sizeof (b->description)) ;
1794 psf_binheader_writef (psf, "b", b->originator, sizeof (b->originator)) ;
1795 psf_binheader_writef (psf, "b", b->originator_reference, sizeof (b->originator_reference)) ;
1796 psf_binheader_writef (psf, "b", b->origination_date, sizeof (b->origination_date)) ;
1797 psf_binheader_writef (psf, "b", b->origination_time, sizeof (b->origination_time)) ;
1798 psf_binheader_writef (psf, "442", b->time_reference_low, b->time_reference_high, b->version) ;
1799 psf_binheader_writef (psf, "b", b->umid, sizeof (b->umid)) ;
1800 psf_binheader_writef (psf, "z", make_size_t (190)) ;
1801
1802 if (b->coding_history_size > 0)
1803 psf_binheader_writef (psf, "b", b->coding_history, make_size_t (b->coding_history_size)) ;
1804
1805 return 0 ;
1806} /* wav_write_bext_chunk */
1807
1808int
1809wav_read_cart_chunk (SF_PRIVATE *psf, uint32_t chunksize)
1810{ SF_CART_INFO_16K *c ;
1811 uint32_t bytes = 0 ;
1812 int k ;
1813
1814 if (chunksize < WAV_CART_MIN_CHUNK_SIZE2048)
1815 { psf_log_printf (psf, "cart : %u (should be >= %d)\n", chunksize, WAV_CART_MIN_CHUNK_SIZE2048) ;
1816 psf_binheader_readf (psf, "j", chunksize) ;
1817 return 0 ;
1818 } ;
1819 if (chunksize > WAV_CART_MAX_CHUNK_SIZE0xffffffff)
1820 { psf_log_printf (psf, "cart : %u (should be < %d)\n", chunksize, WAV_CART_MAX_CHUNK_SIZE0xffffffff) ;
1821 psf_binheader_readf (psf, "j", chunksize) ;
1822 return 0 ;
1823 } ;
1824
1825 if (chunksize >= sizeof (SF_CART_INFO_16K))
1826 { psf_log_printf (psf, "cart : %u too big to be handled\n", chunksize) ;
1827 psf_binheader_readf (psf, "j", chunksize) ;
1828 return 0 ;
1829 } ;
1830
1831 psf_log_printf (psf, "cart : %u\n", chunksize) ;
1832
1833 if ((psf->cart_16k = cart_var_alloc ()) == NULL((void*)0))
1834 { psf->error = SFE_MALLOC_FAILED ;
1835 return psf->error ;
1836 } ;
1837
1838 c = psf->cart_16k ;
1839 bytes += psf_binheader_readf (psf, "b", c->version, sizeof (c->version)) ;
1840 bytes += psf_binheader_readf (psf, "b", c->title, sizeof (c->title)) ;
1841 bytes += psf_binheader_readf (psf, "b", c->artist, sizeof (c->artist)) ;
1842 bytes += psf_binheader_readf (psf, "b", c->cut_id, sizeof (c->cut_id)) ;
1843 bytes += psf_binheader_readf (psf, "b", c->client_id, sizeof (c->client_id)) ;
1844 bytes += psf_binheader_readf (psf, "b", c->category, sizeof (c->category)) ;
1845 bytes += psf_binheader_readf (psf, "b", c->classification, sizeof (c->classification)) ;
1846 bytes += psf_binheader_readf (psf, "b", c->out_cue, sizeof (c->out_cue)) ;
1847 bytes += psf_binheader_readf (psf, "b", c->start_date, sizeof (c->start_date)) ;
1848 bytes += psf_binheader_readf (psf, "b", c->start_time, sizeof (c->start_time)) ;
1849 bytes += psf_binheader_readf (psf, "b", c->end_date, sizeof (c->end_date)) ;
1850 bytes += psf_binheader_readf (psf, "b", c->end_time, sizeof (c->end_time)) ;
1851 bytes += psf_binheader_readf (psf, "b", c->producer_app_id, sizeof (c->producer_app_id)) ;
1852 bytes += psf_binheader_readf (psf, "b", c->producer_app_version, sizeof (c->producer_app_version)) ;
1853 bytes += psf_binheader_readf (psf, "b", c->user_def, sizeof (c->user_def)) ;
1854 bytes += psf_binheader_readf (psf, "e4", &c->level_reference, sizeof (c->level_reference)) ;
1855
1856 for (k = 0 ; k < ARRAY_LEN (c->post_timers)((int) (sizeof (c->post_timers) / sizeof ((c->post_timers
) [0])))
; k++)
1857 bytes += psf_binheader_readf (psf, "b4", &c->post_timers [k].usage, make_size_t (4), &c->post_timers [k].value) ;
1858
1859 bytes += psf_binheader_readf (psf, "b", c->reserved, sizeof (c->reserved)) ;
1860 bytes += psf_binheader_readf (psf, "b", c->url, sizeof (c->url)) ;
1861
1862 if (chunksize > WAV_CART_MIN_CHUNK_SIZE2048)
1863 { /* File has tag text. */
1864 c->tag_text_size = chunksize - WAV_CART_MIN_CHUNK_SIZE2048 ;
1865 bytes += psf_binheader_readf (psf, "b", c->tag_text, make_size_t (c->tag_text_size)) ;
Value stored to 'bytes' is never read
1866 } ;
1867
1868 return 0 ;
1869} /* wav_read_cart_chunk */
1870
1871int
1872wav_write_cart_chunk (SF_PRIVATE *psf)
1873{ SF_CART_INFO_16K *c ;
1874 int k ;
1875
1876 if (psf->cart_16k == NULL((void*)0))
1877 return -1 ;
1878
1879 c = psf->cart_16k ;
1880 psf_binheader_writef (psf, "m4", cart_MARKER(((uint32_t) (('c') | (('a') << 8) | (('r') << 16
) | (((uint32_t) ('t')) << 24))))
, WAV_CART_MIN_CHUNK_SIZE2048 + c->tag_text_size) ;
1881 /*
1882 ** Note that it is very important the the field widths of the SF_CART_INFO
1883 ** struct match those for the cart chunk fields.
1884 */
1885 psf_binheader_writef (psf, "b", c->version, sizeof (c->version)) ;
1886 psf_binheader_writef (psf, "b", c->title, sizeof (c->title)) ;
1887 psf_binheader_writef (psf, "b", c->artist, sizeof (c->artist)) ;
1888 psf_binheader_writef (psf, "b", c->cut_id, sizeof (c->cut_id)) ;
1889 psf_binheader_writef (psf, "b", c->client_id, sizeof (c->client_id)) ;
1890 psf_binheader_writef (psf, "b", c->category, sizeof (c->category)) ;
1891 psf_binheader_writef (psf, "b", c->classification, sizeof (c->classification)) ;
1892 psf_binheader_writef (psf, "b", c->out_cue, sizeof (c->out_cue)) ;
1893 psf_binheader_writef (psf, "b", c->start_date, sizeof (c->start_date)) ;
1894 psf_binheader_writef (psf, "b", c->start_time, sizeof (c->start_time)) ;
1895 psf_binheader_writef (psf, "b", c->end_date, sizeof (c->end_date)) ;
1896 psf_binheader_writef (psf, "b", c->end_time, sizeof (c->end_time)) ;
1897 psf_binheader_writef (psf, "b", c->producer_app_id, sizeof (c->producer_app_id)) ;
1898 psf_binheader_writef (psf, "b", c->producer_app_version, sizeof (c->producer_app_version)) ;
1899 psf_binheader_writef (psf, "b", c->user_def, sizeof (c->user_def)) ;
1900 psf_binheader_writef (psf, "4", c->level_reference, sizeof (c->level_reference)) ;
1901
1902 for (k = 0 ; k < ARRAY_LEN (c->post_timers)((int) (sizeof (c->post_timers) / sizeof ((c->post_timers
) [0])))
; k++)
1903 psf_binheader_writef (psf, "b4", c->post_timers [k].usage, make_size_t (4), c->post_timers [k].value) ;
1904
1905 psf_binheader_writef (psf, "z", sizeof (c->reserved)) ; // just write zeros, we don't have any other use for it
1906 psf_binheader_writef (psf, "b", c->url, sizeof (c->url)) ;
1907
1908 if (c->tag_text_size > 0)
1909 psf_binheader_writef (psf, "b", c->tag_text, make_size_t (c->tag_text_size)) ;
1910
1911 return 0 ;
1912} /* wav_write_cart_chunk */
1913
1914static int
1915exif_fill_and_sink (SF_PRIVATE *psf, char* buf, size_t bufsz, size_t toread)
1916{
1917 size_t bytesread = 0 ;
1918
1919 buf [0] = 0 ;
1920 bufsz -= 1 ;
1921 if (toread < bufsz)
1922 bufsz = toread ;
1923 bytesread = psf_binheader_readf (psf, "b", buf, bufsz) ;
1924 buf [bufsz] = 0 ;
1925
1926 if (bytesread == bufsz && toread > bufsz)
1927 bytesread += psf_binheader_readf (psf, "j", toread - bufsz) ;
1928
1929 return bytesread ;
1930} /* exif_fill_and_sink */
1931
1932/*
1933** Exif specification for audio files, at JEITA CP-3451 Exif 2.2 section 5
1934** (Exif Audio File Specification) http://www.exif.org/Exif2-2.PDF
1935*/
1936static int
1937exif_subchunk_parse (SF_PRIVATE *psf, uint32_t length)
1938{ uint32_t marker, dword, vmajor = -1, vminor = -1, bytesread = 0 ;
1939 char buf [4096] ;
1940
1941 while (bytesread < length)
1942 {
1943 bytesread += psf_binheader_readf (psf, "m", &marker) ;
1944
1945 switch (marker)
1946 {
1947 case 0 : /* camera padding? */
1948 break ;
1949
1950 case ever_MARKER(((uint32_t) (('e') | (('v') << 8) | (('e') << 16
) | (((uint32_t) ('r')) << 24))))
:
1951 bytesread += psf_binheader_readf (psf, "j4", 4, &dword) ;
1952 vmajor = 10 * (((dword >> 24) & 0xff) - '0') + (((dword >> 16) & 0xff) - '0') ;
1953 vminor = 10 * (((dword >> 8) & 0xff) - '0') + ((dword & 0xff) - '0') ;
1954 psf_log_printf (psf, " EXIF Version : %u.%02u\n", vmajor, vminor) ;
1955 break ;
1956
1957 case olym_MARKER(((uint32_t) (('o') | (('l') << 8) | (('y') << 16
) | (((uint32_t) ('m')) << 24))))
:
1958 bytesread += psf_binheader_readf (psf, "4", &dword) ;
1959 psf_log_printf (psf, "%M : %u\n", marker, dword) ;
1960 dword += (dword & 1) ;
1961 bytesread += psf_binheader_readf (psf, "j", dword) ;
1962 break ;
1963
1964 case emnt_MARKER(((uint32_t) (('e') | (('m') << 8) | (('n') << 16
) | (((uint32_t) ('t')) << 24))))
: /* design information: null-terminated string */
1965 case emdl_MARKER(((uint32_t) (('e') | (('m') << 8) | (('d') << 16
) | (((uint32_t) ('l')) << 24))))
: /* model name ; null-terminated string */
1966 case ecor_MARKER(((uint32_t) (('e') | (('c') << 8) | (('o') << 16
) | (((uint32_t) ('r')) << 24))))
: /* manufacturer: null-terminated string */
1967 case etim_MARKER(((uint32_t) (('e') | (('t') << 8) | (('i') << 16
) | (((uint32_t) ('m')) << 24))))
: /* creation time: null-terminated string in the format "hour:minute:second.subsecond" */
1968 case erel_MARKER(((uint32_t) (('e') | (('r') << 8) | (('e') << 16
) | (((uint32_t) ('l')) << 24))))
: /* relation info: null-terminated string (filename) */
1969 case eucm_MARKER(((uint32_t) (('e') | (('u') << 8) | (('c') << 16
) | (((uint32_t) ('m')) << 24))))
: /* user comment: 4-byte size follows, then possibly unicode data */
1970 bytesread += psf_binheader_readf (psf, "4", &dword) ;
1971 bytesread += sizeof (dword) ;
1972 dword += (dword & 1) ;
1973
1974 if (dword >= sizeof (buf))
1975 { psf_log_printf (psf, "*** Marker '%M' is too big %u\n\n", marker, dword) ;
1976 return bytesread ;
1977 } ;
1978
1979 bytesread += exif_fill_and_sink (psf, buf, sizeof (buf), dword) ;
1980
1981 /* BAD - don't know what's going on here -- maybe a bug in the camera */
1982 /* field should be NULL-terminated but there's no room for it with the reported number */
1983 /* example output: emdl : 8 (EX-Z1050) */
1984 if (marker == emdl_MARKER(((uint32_t) (('e') | (('m') << 8) | (('d') << 16
) | (((uint32_t) ('l')) << 24))))
&& dword == strlen (buf) /* should be >= strlen+1*/)
1985 { psf_log_printf (psf, " *** field size too small for string (sinking 2 bytes)\n") ;
1986 bytesread += psf_binheader_readf (psf, "j", 2) ;
1987 } ;
1988
1989 psf_log_printf (psf, " %M : %d (%s)\n", marker, dword, buf) ;
1990 if (dword > length)
1991 return bytesread ;
1992 break ;
1993
1994 default :
1995 psf_log_printf (psf, " *** %M (%d): -- ignored --\n", marker, marker) ;
1996 break ;
1997 } ;
1998 } ;
1999
2000 return bytesread ;
2001} /* exif_subchunk_parse */
2002
2003/*==============================================================================
2004*/
2005
2006static int
2007wav_set_chunk (SF_PRIVATE *psf, const SF_CHUNK_INFO * chunk_info)
2008{ return psf_save_write_chunk (&psf->wchunks, chunk_info) ;
2009} /* wav_set_chunk */
2010
2011static SF_CHUNK_ITERATOR *
2012wav_next_chunk_iterator (SF_PRIVATE *psf, SF_CHUNK_ITERATOR * iterator)
2013{ return psf_next_chunk_iterator (&psf->rchunks, iterator) ;
2014} /* wav_next_chunk_iterator */
2015
2016static int
2017wav_get_chunk_size (SF_PRIVATE *psf, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info)
2018{ int indx ;
2019
2020 if ((indx = psf_find_read_chunk_iterator (&psf->rchunks, iterator)) < 0)
2021 return SFE_UNKNOWN_CHUNK ;
2022
2023 chunk_info->datalen = psf->rchunks.chunks [indx].len ;
2024
2025 return SFE_NO_ERROR ;
2026} /* wav_get_chunk_size */
2027
2028static int
2029wav_get_chunk_data (SF_PRIVATE *psf, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info)
2030{ int indx ;
2031 sf_count_t pos ;
2032
2033 if ((indx = psf_find_read_chunk_iterator (&psf->rchunks, iterator)) < 0)
2034 return SFE_UNKNOWN_CHUNK ;
2035
2036 if (chunk_info->data == NULL((void*)0))
2037 return SFE_BAD_CHUNK_DATA_PTR ;
2038
2039 chunk_info->id_size = psf->rchunks.chunks [indx].id_size ;
2040 memcpy (chunk_info->id, psf->rchunks.chunks [indx].id, sizeof (chunk_info->id) / sizeof (*chunk_info->id)) ;
2041
2042 pos = psf_ftell (psf) ;
2043 psf_fseek (psf, psf->rchunks.chunks [indx].offset, SEEK_SET0) ;
2044 psf_fread (chunk_info->data, SF_MIN (chunk_info->datalen, psf->rchunks.chunks [indx].len)({ typeof (chunk_info->datalen) sf_min_x2 = (chunk_info->
datalen) ; typeof (psf->rchunks.chunks [indx].len) sf_min_y2
= (psf->rchunks.chunks [indx].len) ; (void) (&sf_min_x2
== &sf_min_y2) ; sf_min_x2 < sf_min_y2 ? sf_min_x2 : sf_min_y2
; })
, 1, psf) ;
2045 psf_fseek (psf, pos, SEEK_SET0) ;
2046
2047 return SFE_NO_ERROR ;
2048} /* wav_get_chunk_data */