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