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