]> 4ch.mooo.com Git - 16.git/blob - src/lib/doslib/ext/flac/format.c
wwww
[16.git] / src / lib / doslib / ext / flac / format.c
1 /* libFLAC - Free Lossless Audio Codec library
2  * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007  Josh Coalson
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * - Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * - Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * - Neither the name of the Xiph.org Foundation nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #if HAVE_CONFIG_H
33 #  include "config.h"
34 #endif
35
36 #include <stdio.h>
37 #include <stdlib.h> /* for qsort() */
38 #include <string.h> /* for memset() */
39 #include "flac/assert.h"
40 #include "flac/format.h"
41 #include "private/format.h"
42
43 #ifndef FLaC__INLINE
44 #define FLaC__INLINE
45 #endif
46
47 #ifdef min
48 #undef min
49 #endif
50 #define min(a,b) ((a)<(b)?(a):(b))
51
52 /* adjust for compilers that can't understand using LLU suffix for uint64_t literals */
53 #ifdef _MSC_VER
54 #define FLAC__U64L(x) x
55 #else
56 #define FLAC__U64L(x) x##LLU
57 #endif
58
59 /* VERSION should come from configure */
60 FLAC_API const char *FLAC__VERSION_STRING = VERSION;
61
62 #if defined _MSC_VER || defined __BORLANDC__ || defined __MINW32__
63 /* yet one more hack because of MSVC6: */
64 FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC 1.2.1 20070917";
65 #else
66 FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC " VERSION " 20070917";
67 #endif
68
69 FLAC_API const FLAC__byte FLAC__STREAM_SYNC_STRING[4] = { 'f','L','a','C' };
70 FLAC_API const unsigned FLAC__STREAM_SYNC = 0x664C6143;
71 FLAC_API const unsigned FLAC__STREAM_SYNC_LEN = 32; /* bits */
72
73 FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN = 16; /* bits */
74 FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN = 16; /* bits */
75 FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN = 24; /* bits */
76 FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN = 24; /* bits */
77 FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN = 20; /* bits */
78 FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN = 3; /* bits */
79 FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN = 5; /* bits */
80 FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN = 36; /* bits */
81 FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MD5SUM_LEN = 128; /* bits */
82
83 FLAC_API const unsigned FLAC__STREAM_METADATA_APPLICATION_ID_LEN = 32; /* bits */
84
85 FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN = 64; /* bits */
86 FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN = 64; /* bits */
87 FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN = 16; /* bits */
88
89 FLAC_API const FLAC__uint64 FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER = FLAC__U64L(0xffffffffffffffff);
90
91 FLAC_API const unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN = 32; /* bits */
92 FLAC_API const unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN = 32; /* bits */
93
94 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN = 64; /* bits */
95 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN = 8; /* bits */
96 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN = 3*8; /* bits */
97
98 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN = 64; /* bits */
99 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN = 8; /* bits */
100 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN = 12*8; /* bits */
101 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN = 1; /* bit */
102 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN = 1; /* bit */
103 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN = 6+13*8; /* bits */
104 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN = 8; /* bits */
105
106 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN = 128*8; /* bits */
107 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN = 64; /* bits */
108 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN = 1; /* bit */
109 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN = 7+258*8; /* bits */
110 FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN = 8; /* bits */
111
112 FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_TYPE_LEN = 32; /* bits */
113 FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN = 32; /* bits */
114 FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN = 32; /* bits */
115 FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN = 32; /* bits */
116 FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN = 32; /* bits */
117 FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN = 32; /* bits */
118 FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_COLORS_LEN = 32; /* bits */
119 FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN = 32; /* bits */
120
121 FLAC_API const unsigned FLAC__STREAM_METADATA_IS_LAST_LEN = 1; /* bits */
122 FLAC_API const unsigned FLAC__STREAM_METADATA_TYPE_LEN = 7; /* bits */
123 FLAC_API const unsigned FLAC__STREAM_METADATA_LENGTH_LEN = 24; /* bits */
124
125 FLAC_API const unsigned FLAC__FRAME_HEADER_SYNC = 0x3ffe;
126 FLAC_API const unsigned FLAC__FRAME_HEADER_SYNC_LEN = 14; /* bits */
127 FLAC_API const unsigned FLAC__FRAME_HEADER_RESERVED_LEN = 1; /* bits */
128 FLAC_API const unsigned FLAC__FRAME_HEADER_BLOCKING_STRATEGY_LEN = 1; /* bits */
129 FLAC_API const unsigned FLAC__FRAME_HEADER_BLOCK_SIZE_LEN = 4; /* bits */
130 FLAC_API const unsigned FLAC__FRAME_HEADER_SAMPLE_RATE_LEN = 4; /* bits */
131 FLAC_API const unsigned FLAC__FRAME_HEADER_CHANNEL_ASSIGNMENT_LEN = 4; /* bits */
132 FLAC_API const unsigned FLAC__FRAME_HEADER_BITS_PER_SAMPLE_LEN = 3; /* bits */
133 FLAC_API const unsigned FLAC__FRAME_HEADER_ZERO_PAD_LEN = 1; /* bits */
134 FLAC_API const unsigned FLAC__FRAME_HEADER_CRC_LEN = 8; /* bits */
135
136 FLAC_API const unsigned FLAC__FRAME_FOOTER_CRC_LEN = 16; /* bits */
137
138 FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_TYPE_LEN = 2; /* bits */
139 FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN = 4; /* bits */
140 FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN = 4; /* bits */
141 FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN = 5; /* bits */
142 FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN = 5; /* bits */
143
144 FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER = 15; /* == (1<<FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN)-1 */
145 FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_ESCAPE_PARAMETER = 31; /* == (1<<FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN)-1 */
146
147 FLAC_API const char * const FLAC__EntropyCodingMethodTypeString[] = {
148         "PARTITIONED_RICE",
149         "PARTITIONED_RICE2"
150 };
151
152 FLAC_API const unsigned FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN = 4; /* bits */
153 FLAC_API const unsigned FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN = 5; /* bits */
154
155 FLAC_API const unsigned FLAC__SUBFRAME_ZERO_PAD_LEN = 1; /* bits */
156 FLAC_API const unsigned FLAC__SUBFRAME_TYPE_LEN = 6; /* bits */
157 FLAC_API const unsigned FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN = 1; /* bits */
158
159 FLAC_API const unsigned FLAC__SUBFRAME_TYPE_CONSTANT_BYTE_ALIGNED_MASK = 0x00;
160 FLAC_API const unsigned FLAC__SUBFRAME_TYPE_VERBATIM_BYTE_ALIGNED_MASK = 0x02;
161 FLAC_API const unsigned FLAC__SUBFRAME_TYPE_FIXED_BYTE_ALIGNED_MASK = 0x10;
162 FLAC_API const unsigned FLAC__SUBFRAME_TYPE_LPC_BYTE_ALIGNED_MASK = 0x40;
163
164 FLAC_API const char * const FLAC__SubframeTypeString[] = {
165         "CONSTANT",
166         "VERBATIM",
167         "FIXED",
168         "LPC"
169 };
170
171 FLAC_API const char * const FLAC__ChannelAssignmentString[] = {
172         "INDEPENDENT",
173         "LEFT_SIDE",
174         "RIGHT_SIDE",
175         "MID_SIDE"
176 };
177
178 FLAC_API const char * const FLAC__FrameNumberTypeString[] = {
179         "FRAME_NUMBER_TYPE_FRAME_NUMBER",
180         "FRAME_NUMBER_TYPE_SAMPLE_NUMBER"
181 };
182
183 FLAC_API const char * const FLAC__MetadataTypeString[] = {
184         "STREAMINFO",
185         "PADDING",
186         "APPLICATION",
187         "SEEKTABLE",
188         "VORBIS_COMMENT",
189         "CUESHEET",
190         "PICTURE"
191 };
192
193 FLAC_API const char * const FLAC__StreamMetadata_Picture_TypeString[] = {
194         "Other",
195         "32x32 pixels 'file icon' (PNG only)",
196         "Other file icon",
197         "Cover (front)",
198         "Cover (back)",
199         "Leaflet page",
200         "Media (e.g. label side of CD)",
201         "Lead artist/lead performer/soloist",
202         "Artist/performer",
203         "Conductor",
204         "Band/Orchestra",
205         "Composer",
206         "Lyricist/text writer",
207         "Recording Location",
208         "During recording",
209         "During performance",
210         "Movie/video screen capture",
211         "A bright coloured fish",
212         "Illustration",
213         "Band/artist logotype",
214         "Publisher/Studio logotype"
215 };
216
217 FLAC_API FLAC__bool FLAC__format_sample_rate_is_valid(unsigned sample_rate)
218 {
219         if(sample_rate == 0 || sample_rate > FLAC__MAX_SAMPLE_RATE) {
220                 return false;
221         }
222         else
223                 return true;
224 }
225
226 FLAC_API FLAC__bool FLAC__format_sample_rate_is_subset(unsigned sample_rate)
227 {
228         if(
229                 !FLAC__format_sample_rate_is_valid(sample_rate) ||
230                 (
231                         sample_rate >= (1u << 16) &&
232                         !(sample_rate % 1000 == 0 || sample_rate % 10 == 0)
233                 )
234         ) {
235                 return false;
236         }
237         else
238                 return true;
239 }
240
241 /* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */
242 FLAC_API FLAC__bool FLAC__format_seektable_is_legal(const FLAC__StreamMetadata_SeekTable *seek_table)
243 {
244         unsigned i;
245         FLAC__uint64 prev_sample_number = 0;
246         FLAC__bool got_prev = false;
247
248         FLAC__ASSERT(0 != seek_table);
249
250         for(i = 0; i < seek_table->num_points; i++) {
251                 if(got_prev) {
252                         if(
253                                 seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER &&
254                                 seek_table->points[i].sample_number <= prev_sample_number
255                         )
256                                 return false;
257                 }
258                 prev_sample_number = seek_table->points[i].sample_number;
259                 got_prev = true;
260         }
261
262         return true;
263 }
264
265 /* used as the sort predicate for qsort() */
266 static int seekpoint_compare_(const FLAC__StreamMetadata_SeekPoint *l, const FLAC__StreamMetadata_SeekPoint *r)
267 {
268         /* we don't just 'return l->sample_number - r->sample_number' since the result (FLAC__int64) might overflow an 'int' */
269         if(l->sample_number == r->sample_number)
270                 return 0;
271         else if(l->sample_number < r->sample_number)
272                 return -1;
273         else
274                 return 1;
275 }
276
277 /* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */
278 FLAC_API unsigned FLAC__format_seektable_sort(FLAC__StreamMetadata_SeekTable *seek_table)
279 {
280         unsigned i, j;
281         FLAC__bool first;
282
283         FLAC__ASSERT(0 != seek_table);
284
285         /* sort the seekpoints */
286         qsort(seek_table->points, seek_table->num_points, sizeof(FLAC__StreamMetadata_SeekPoint), (int (*)(const void *, const void *))seekpoint_compare_);
287
288         /* uniquify the seekpoints */
289         first = true;
290         for(i = j = 0; i < seek_table->num_points; i++) {
291                 if(seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER) {
292                         if(!first) {
293                                 if(seek_table->points[i].sample_number == seek_table->points[j-1].sample_number)
294                                         continue;
295                         }
296                 }
297                 first = false;
298                 seek_table->points[j++] = seek_table->points[i];
299         }
300
301         for(i = j; i < seek_table->num_points; i++) {
302                 seek_table->points[i].sample_number = FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER;
303                 seek_table->points[i].stream_offset = 0;
304                 seek_table->points[i].frame_samples = 0;
305         }
306
307         return j;
308 }
309
310 /*
311  * also disallows non-shortest-form encodings, c.f.
312  *   http://www.unicode.org/versions/corrigendum1.html
313  * and a more clear explanation at the end of this section:
314  *   http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
315  */
316 static FLaC__INLINE unsigned utf8len_(const FLAC__byte *utf8)
317 {
318         FLAC__ASSERT(0 != utf8);
319         if ((utf8[0] & 0x80) == 0) {
320                 return 1;
321         }
322         else if ((utf8[0] & 0xE0) == 0xC0 && (utf8[1] & 0xC0) == 0x80) {
323                 if ((utf8[0] & 0xFE) == 0xC0) /* overlong sequence check */
324                         return 0;
325                 return 2;
326         }
327         else if ((utf8[0] & 0xF0) == 0xE0 && (utf8[1] & 0xC0) == 0x80 && (utf8[2] & 0xC0) == 0x80) {
328                 if (utf8[0] == 0xE0 && (utf8[1] & 0xE0) == 0x80) /* overlong sequence check */
329                         return 0;
330                 /* illegal surrogates check (U+D800...U+DFFF and U+FFFE...U+FFFF) */
331                 if (utf8[0] == 0xED && (utf8[1] & 0xE0) == 0xA0) /* D800-DFFF */
332                         return 0;
333                 if (utf8[0] == 0xEF && utf8[1] == 0xBF && (utf8[2] & 0xFE) == 0xBE) /* FFFE-FFFF */
334                         return 0;
335                 return 3;
336         }
337         else if ((utf8[0] & 0xF8) == 0xF0 && (utf8[1] & 0xC0) == 0x80 && (utf8[2] & 0xC0) == 0x80 && (utf8[3] & 0xC0) == 0x80) {
338                 if (utf8[0] == 0xF0 && (utf8[1] & 0xF0) == 0x80) /* overlong sequence check */
339                         return 0;
340                 return 4;
341         }
342         else if ((utf8[0] & 0xFC) == 0xF8 && (utf8[1] & 0xC0) == 0x80 && (utf8[2] & 0xC0) == 0x80 && (utf8[3] & 0xC0) == 0x80 && (utf8[4] & 0xC0) == 0x80) {
343                 if (utf8[0] == 0xF8 && (utf8[1] & 0xF8) == 0x80) /* overlong sequence check */
344                         return 0;
345                 return 5;
346         }
347         else if ((utf8[0] & 0xFE) == 0xFC && (utf8[1] & 0xC0) == 0x80 && (utf8[2] & 0xC0) == 0x80 && (utf8[3] & 0xC0) == 0x80 && (utf8[4] & 0xC0) == 0x80 && (utf8[5] & 0xC0) == 0x80) {
348                 if (utf8[0] == 0xFC && (utf8[1] & 0xFC) == 0x80) /* overlong sequence check */
349                         return 0;
350                 return 6;
351         }
352         else {
353                 return 0;
354         }
355 }
356
357 FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_name_is_legal(const char *name)
358 {
359         char c;
360         for(c = *name; c; c = *(++name))
361                 if(c < 0x20 || c == 0x3d || c > 0x7d)
362                         return false;
363         return true;
364 }
365
366 FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_value_is_legal(const FLAC__byte *value, unsigned length)
367 {
368         if(length == (unsigned)(-1)) {
369                 while(*value) {
370                         unsigned n = utf8len_(value);
371                         if(n == 0)
372                                 return false;
373                         value += n;
374                 }
375         }
376         else {
377                 const FLAC__byte *end = value + length;
378                 while(value < end) {
379                         unsigned n = utf8len_(value);
380                         if(n == 0)
381                                 return false;
382                         value += n;
383                 }
384                 if(value != end)
385                         return false;
386         }
387         return true;
388 }
389
390 FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_is_legal(const FLAC__byte *entry, unsigned length)
391 {
392         const FLAC__byte *s, *end;
393
394         for(s = entry, end = s + length; s < end && *s != '='; s++) {
395                 if(*s < 0x20 || *s > 0x7D)
396                         return false;
397         }
398         if(s == end)
399                 return false;
400
401         s++; /* skip '=' */
402
403         while(s < end) {
404                 unsigned n = utf8len_(s);
405                 if(n == 0)
406                         return false;
407                 s += n;
408         }
409         if(s != end)
410                 return false;
411
412         return true;
413 }
414
415 /* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */
416 FLAC_API FLAC__bool FLAC__format_cuesheet_is_legal(const FLAC__StreamMetadata_CueSheet *cue_sheet, FLAC__bool check_cd_da_subset, const char **violation)
417 {
418         unsigned i, j;
419
420         if(check_cd_da_subset) {
421                 if(cue_sheet->lead_in < 2 * 44100) {
422                         if(violation) *violation = "CD-DA cue sheet must have a lead-in length of at least 2 seconds";
423                         return false;
424                 }
425                 if(cue_sheet->lead_in % 588 != 0) {
426                         if(violation) *violation = "CD-DA cue sheet lead-in length must be evenly divisible by 588 samples";
427                         return false;
428                 }
429         }
430
431         if(cue_sheet->num_tracks == 0) {
432                 if(violation) *violation = "cue sheet must have at least one track (the lead-out)";
433                 return false;
434         }
435
436         if(check_cd_da_subset && cue_sheet->tracks[cue_sheet->num_tracks-1].number != 170) {
437                 if(violation) *violation = "CD-DA cue sheet must have a lead-out track number 170 (0xAA)";
438                 return false;
439         }
440
441         for(i = 0; i < cue_sheet->num_tracks; i++) {
442                 if(cue_sheet->tracks[i].number == 0) {
443                         if(violation) *violation = "cue sheet may not have a track number 0";
444                         return false;
445                 }
446
447                 if(check_cd_da_subset) {
448                         if(!((cue_sheet->tracks[i].number >= 1 && cue_sheet->tracks[i].number <= 99) || cue_sheet->tracks[i].number == 170)) {
449                                 if(violation) *violation = "CD-DA cue sheet track number must be 1-99 or 170";
450                                 return false;
451                         }
452                 }
453
454                 if(check_cd_da_subset && cue_sheet->tracks[i].offset % 588 != 0) {
455                         if(violation) {
456                                 if(i == cue_sheet->num_tracks-1) /* the lead-out track... */
457                                         *violation = "CD-DA cue sheet lead-out offset must be evenly divisible by 588 samples";
458                                 else
459                                         *violation = "CD-DA cue sheet track offset must be evenly divisible by 588 samples";
460                         }
461                         return false;
462                 }
463
464                 if(i < cue_sheet->num_tracks - 1) {
465                         if(cue_sheet->tracks[i].num_indices == 0) {
466                                 if(violation) *violation = "cue sheet track must have at least one index point";
467                                 return false;
468                         }
469
470                         if(cue_sheet->tracks[i].indices[0].number > 1) {
471                                 if(violation) *violation = "cue sheet track's first index number must be 0 or 1";
472                                 return false;
473                         }
474                 }
475
476                 for(j = 0; j < cue_sheet->tracks[i].num_indices; j++) {
477                         if(check_cd_da_subset && cue_sheet->tracks[i].indices[j].offset % 588 != 0) {
478                                 if(violation) *violation = "CD-DA cue sheet track index offset must be evenly divisible by 588 samples";
479                                 return false;
480                         }
481
482                         if(j > 0) {
483                                 if(cue_sheet->tracks[i].indices[j].number != cue_sheet->tracks[i].indices[j-1].number + 1) {
484                                         if(violation) *violation = "cue sheet track index numbers must increase by 1";
485                                         return false;
486                                 }
487                         }
488                 }
489         }
490
491         return true;
492 }
493
494 /* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */
495 FLAC_API FLAC__bool FLAC__format_picture_is_legal(const FLAC__StreamMetadata_Picture *picture, const char **violation)
496 {
497         char *p;
498         FLAC__byte *b;
499
500         for(p = picture->mime_type; *p; p++) {
501                 if(*p < 0x20 || *p > 0x7e) {
502                         if(violation) *violation = "MIME type string must contain only printable ASCII characters (0x20-0x7e)";
503                         return false;
504                 }
505         }
506
507         for(b = picture->description; *b; ) {
508                 unsigned n = utf8len_(b);
509                 if(n == 0) {
510                         if(violation) *violation = "description string must be valid UTF-8";
511                         return false;
512                 }
513                 b += n;
514         }
515
516         return true;
517 }
518
519 /*
520  * These routines are private to libFLAC
521  */
522 unsigned FLAC__format_get_max_rice_partition_order(unsigned blocksize, unsigned predictor_order)
523 {
524         return
525                 FLAC__format_get_max_rice_partition_order_from_blocksize_limited_max_and_predictor_order(
526                         FLAC__format_get_max_rice_partition_order_from_blocksize(blocksize),
527                         blocksize,
528                         predictor_order
529                 );
530 }
531
532 unsigned FLAC__format_get_max_rice_partition_order_from_blocksize(unsigned blocksize)
533 {
534         unsigned max_rice_partition_order = 0;
535         while(!(blocksize & 1)) {
536                 max_rice_partition_order++;
537                 blocksize >>= 1;
538         }
539         return min(FLAC__MAX_RICE_PARTITION_ORDER, max_rice_partition_order);
540 }
541
542 unsigned FLAC__format_get_max_rice_partition_order_from_blocksize_limited_max_and_predictor_order(unsigned limit, unsigned blocksize, unsigned predictor_order)
543 {
544         unsigned max_rice_partition_order = limit;
545
546         while(max_rice_partition_order > 0 && (blocksize >> max_rice_partition_order) <= predictor_order)
547                 max_rice_partition_order--;
548
549         FLAC__ASSERT(
550                 (max_rice_partition_order == 0 && blocksize >= predictor_order) ||
551                 (max_rice_partition_order > 0 && blocksize >> max_rice_partition_order > predictor_order)
552         );
553
554         return max_rice_partition_order;
555 }
556
557 void FLAC__format_entropy_coding_method_partitioned_rice_contents_init(FLAC__EntropyCodingMethod_PartitionedRiceContents *object)
558 {
559         FLAC__ASSERT(0 != object);
560
561         object->parameters = 0;
562         object->raw_bits = 0;
563         object->capacity_by_order = 0;
564 }
565
566 void FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(FLAC__EntropyCodingMethod_PartitionedRiceContents *object)
567 {
568         FLAC__ASSERT(0 != object);
569
570         if(0 != object->parameters)
571                 free(object->parameters);
572         if(0 != object->raw_bits)
573                 free(object->raw_bits);
574         FLAC__format_entropy_coding_method_partitioned_rice_contents_init(object);
575 }
576
577 FLAC__bool FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(FLAC__EntropyCodingMethod_PartitionedRiceContents *object, unsigned max_partition_order)
578 {
579         FLAC__ASSERT(0 != object);
580
581         FLAC__ASSERT(object->capacity_by_order > 0 || (0 == object->parameters && 0 == object->raw_bits));
582
583         if(object->capacity_by_order < max_partition_order) {
584                 if(0 == (object->parameters = (unsigned*)realloc(object->parameters, sizeof(unsigned)*(1 << max_partition_order))))
585                         return false;
586                 if(0 == (object->raw_bits = (unsigned*)realloc(object->raw_bits, sizeof(unsigned)*(1 << max_partition_order))))
587                         return false;
588                 memset(object->raw_bits, 0, sizeof(unsigned)*(1 << max_partition_order));
589                 object->capacity_by_order = max_partition_order;
590         }
591
592         return true;
593 }