Home | History | Annotate | Download | only in libFLAC
      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 
    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 
    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 
    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 */
    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() */
    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 */
    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  */
    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 
    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 
    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 
    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 */
    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 */
    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  */
    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 
    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 
    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 
    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 
    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 
    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