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