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