FastLED 3.9.15
Loading...
Searching...
No Matches
mp3dec.hpp
Go to the documentation of this file.
1/* ***** BEGIN LICENSE BLOCK *****
2 * Version: RCSL 1.0/RPSL 1.0
3 *
4 * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
5 *
6 * The contents of this file, and the files included with this file, are
7 * subject to the current version of the RealNetworks Public Source License
8 * Version 1.0 (the "RPSL") available at
9 * http://www.helixcommunity.org/content/rpsl unless you have licensed
10 * the file under the RealNetworks Community Source License Version 1.0
11 * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
12 * in which case the RCSL will apply. You may also obtain the license terms
13 * directly from RealNetworks. You may not use this file except in
14 * compliance with the RPSL or, if you have a valid RCSL with RealNetworks
15 * applicable to this file, the RCSL. Please see the applicable RPSL or
16 * RCSL for the rights, obligations and limitations governing use of the
17 * contents of the file.
18 *
19 * This file is part of the Helix DNA Technology. RealNetworks is the
20 * developer of the Original Code and owns the copyrights in the portions
21 * it created.
22 *
23 * This file, and the files included with this file, is distributed and made
24 * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
25 * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
26 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
27 * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
28 *
29 * Technology Compatibility Kit Test Suite(s) Location:
30 * http://www.helixcommunity.org/content/tck
31 *
32 * Contributor(s):
33 *
34 * ***** END LICENSE BLOCK ***** */
35
36/**************************************************************************************
37 * Fixed-point MP3 decoder
38 * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com)
39 * June 2003
40 *
41 * mp3dec.c - platform-independent top level MP3 decoder API
42 **************************************************************************************/
43
44// Forward declarations for memory operations
45// (can be replaced with different implementations if desired)
46// Bind to fl/ equivalents instead of C standard library
47#include "fl/stl/cstring.h"
48#include "fl/stl/noexcept.h"
49
50#include "pub/mp3common.h" /* includes mp3dec.h (public API) and internal, platform-independent API */
51
52namespace fl {
53namespace third_party {
54
55//#define PROFILE
56#ifdef PROFILE
57#include "systime.h"
58#endif
59
60/**************************************************************************************
61 * Function: MP3InitDecoder
62 *
63 * Description: allocate memory for platform-specific data
64 * clear all the user-accessible fields
65 *
66 * Inputs: none
67 *
68 * Outputs: none
69 *
70 * Return: handle to mp3 decoder instance, 0 if malloc fails
71 **************************************************************************************/
73{
74 MP3DecInfo *mp3DecInfo;
75
76 mp3DecInfo = AllocateBuffers();
77
78 return (HMP3Decoder)mp3DecInfo;
79}
80
81/**************************************************************************************
82 * Function: MP3FreeDecoder
83 *
84 * Description: free platform-specific data allocated by InitMP3Decoder
85 * zero out the contents of MP3DecInfo struct
86 *
87 * Inputs: valid MP3 decoder instance pointer (HMP3Decoder)
88 *
89 * Outputs: none
90 *
91 * Return: none
92 **************************************************************************************/
94{
95 MP3DecInfo *mp3DecInfo = (MP3DecInfo *)hMP3Decoder;
96
97 if (!mp3DecInfo)
98 return;
99
100 FreeBuffers(mp3DecInfo);
101}
102
103/**************************************************************************************
104 * Function: MP3FindSyncWord
105 *
106 * Description: locate the next byte-alinged sync word in the raw mp3 stream
107 *
108 * Inputs: buffer to search for sync word
109 * max number of bytes to search in buffer
110 *
111 * Outputs: none
112 *
113 * Return: offset to first sync word (bytes from start of buf)
114 * -1 if sync not found after searching nBytes
115 **************************************************************************************/
116int MP3FindSyncWord(const unsigned char *buf, int nBytes) FL_NOEXCEPT
117{
118 int i;
119
120 /* find byte-aligned syncword - need 12 (MPEG 1,2) or 11 (MPEG 2.5) matching bits */
121 for (i = 0; i < nBytes - 1; i++) {
122 if ( (buf[i+0] & SYNCWORDH) == SYNCWORDH && (buf[i+1] & SYNCWORDL) == SYNCWORDL )
123 return i;
124 }
125
126 return -1;
127}
128
129/**************************************************************************************
130 * Function: MP3FindFreeSync
131 *
132 * Description: figure out number of bytes between adjacent sync words in "free" mode
133 *
134 * Inputs: buffer to search for next sync word
135 * the 4-byte frame header starting at the current sync word
136 * max number of bytes to search in buffer
137 *
138 * Outputs: none
139 *
140 * Return: offset to next sync word, minus any pad byte (i.e. nSlots)
141 * -1 if sync not found after searching nBytes
142 *
143 * Notes: this checks that the first 22 bits of the next frame header are the
144 * same as the current frame header, but it's still not foolproof
145 * (could accidentally find a sequence in the bitstream which
146 * appears to match but is not actually the next frame header)
147 * this could be made more error-resilient by checking several frames
148 * in a row and verifying that nSlots is the same in each case
149 * since free mode requires CBR (see spec) we generally only call
150 * this function once (first frame) then store the result (nSlots)
151 * and just use it from then on
152 **************************************************************************************/
153static int MP3FindFreeSync(const unsigned char *buf, const unsigned char firstFH[4], int nBytes) FL_NOEXCEPT
154{
155 int offset = 0;
156 const unsigned char *bufPtr = buf;
157
158 /* loop until we either:
159 * - run out of nBytes (FindMP3SyncWord() returns -1)
160 * - find the next valid frame header (sync word, version, layer, CRC flag, bitrate, and sample rate
161 * in next header must match current header)
162 */
163 while (1) {
164 offset = MP3FindSyncWord(bufPtr, nBytes);
165 bufPtr += offset;
166 if (offset < 0) {
167 return -1;
168 } else if ( (bufPtr[0] == firstFH[0]) && (bufPtr[1] == firstFH[1]) && ((bufPtr[2] & 0xfc) == (firstFH[2] & 0xfc)) ) {
169 /* want to return number of bytes per frame, NOT counting the padding byte, so subtract one if padFlag == 1 */
170 if ((firstFH[2] >> 1) & 0x01)
171 bufPtr--;
172 return bufPtr - buf;
173 }
174 bufPtr += 3;
175 nBytes -= (offset + 3);
176 };
177
178 return -1;
179}
180
181/**************************************************************************************
182 * Function: MP3GetLastFrameInfo
183 *
184 * Description: get info about last MP3 frame decoded (number of sampled decoded,
185 * sample rate, bitrate, etc.)
186 *
187 * Inputs: valid MP3 decoder instance pointer (HMP3Decoder)
188 * pointer to MP3FrameInfo struct
189 *
190 * Outputs: filled-in MP3FrameInfo struct
191 *
192 * Return: none
193 *
194 * Notes: call this right after calling MP3Decode
195 **************************************************************************************/
197{
198 MP3DecInfo *mp3DecInfo = (MP3DecInfo *)hMP3Decoder;
199
200 if (!mp3DecInfo || mp3DecInfo->layer != 3) {
201 mp3FrameInfo->bitrate = 0;
202 mp3FrameInfo->nChans = 0;
203 mp3FrameInfo->samprate = 0;
204 mp3FrameInfo->bitsPerSample = 0;
205 mp3FrameInfo->outputSamps = 0;
206 mp3FrameInfo->layer = 0;
207 mp3FrameInfo->version = 0;
208 } else {
209 mp3FrameInfo->bitrate = mp3DecInfo->bitrate;
210 mp3FrameInfo->nChans = mp3DecInfo->nChans;
211 mp3FrameInfo->samprate = mp3DecInfo->samprate;
212 mp3FrameInfo->bitsPerSample = 16;
213 mp3FrameInfo->outputSamps = mp3DecInfo->nChans * (int)samplesPerFrameTab[mp3DecInfo->version][mp3DecInfo->layer - 1];
214 mp3FrameInfo->layer = mp3DecInfo->layer;
215 mp3FrameInfo->version = mp3DecInfo->version;
216 }
217}
218
219/**************************************************************************************
220 * Function: MP3GetNextFrameInfo
221 *
222 * Description: parse MP3 frame header
223 *
224 * Inputs: valid MP3 decoder instance pointer (HMP3Decoder)
225 * pointer to MP3FrameInfo struct
226 * pointer to buffer containing valid MP3 frame header (located using
227 * MP3FindSyncWord(), above)
228 *
229 * Outputs: filled-in MP3FrameInfo struct
230 *
231 * Return: error code, defined in mp3dec.h (0 means no error, < 0 means error)
232 **************************************************************************************/
233int MP3GetNextFrameInfo(HMP3Decoder hMP3Decoder, MP3FrameInfo *mp3FrameInfo, unsigned char *buf) FL_NOEXCEPT
234{
235 MP3DecInfo *mp3DecInfo = (MP3DecInfo *)hMP3Decoder;
236
237 if (!mp3DecInfo)
239
240 if (UnpackFrameHeader(mp3DecInfo, buf) == -1 || mp3DecInfo->layer != 3)
242
243 MP3GetLastFrameInfo(mp3DecInfo, mp3FrameInfo);
244
245 return ERR_MP3_NONE;
246}
247
248/**************************************************************************************
249 * Function: MP3ClearBadFrame
250 *
251 * Description: zero out pcm buffer if error decoding MP3 frame
252 *
253 * Inputs: mp3DecInfo struct with correct frame size parameters filled in
254 * pointer pcm output buffer
255 *
256 * Outputs: zeroed out pcm buffer
257 *
258 * Return: none
259 **************************************************************************************/
260static void MP3ClearBadFrame(MP3DecInfo *mp3DecInfo, short *outbuf) FL_NOEXCEPT
261{
262 int i;
263
264 if (!mp3DecInfo)
265 return;
266
267 for (i = 0; i < mp3DecInfo->nGrans * mp3DecInfo->nGranSamps * mp3DecInfo->nChans; i++)
268 outbuf[i] = 0;
269}
270
271/**************************************************************************************
272 * Function: MP3Decode
273 *
274 * Description: decode one frame of MP3 data
275 *
276 * Inputs: valid MP3 decoder instance pointer (HMP3Decoder)
277 * double pointer to buffer of MP3 data (containing headers + mainData)
278 * number of valid bytes remaining in inbuf
279 * pointer to outbuf, big enough to hold one frame of decoded PCM samples
280 * flag indicating whether MP3 data is normal MPEG format (useSize = 0)
281 * or reformatted as "self-contained" frames (useSize = 1)
282 *
283 * Outputs: PCM data in outbuf, interleaved LRLRLR... if stereo
284 * number of output samples = nGrans * nGranSamps * nChans
285 * updated inbuf pointer, updated bytesLeft
286 *
287 * Return: error code, defined in mp3dec.h (0 means no error, < 0 means error)
288 *
289 * Notes: switching useSize on and off between frames in the same stream
290 * is not supported (bit reservoir is not maintained if useSize on)
291 **************************************************************************************/
292int MP3Decode(HMP3Decoder hMP3Decoder, const unsigned char **inbuf, size_t *bytesLeft, short *outbuf, int useSize) FL_NOEXCEPT
293{
294 int offset, bitOffset, mainBits, gr, ch, fhBytes, siBytes, freeFrameBytes;
295 int prevBitOffset, sfBlockBits, huffBlockBits;
296 const unsigned char *mainPtr;
297 MP3DecInfo *mp3DecInfo = (MP3DecInfo *)hMP3Decoder;
298
299 #ifdef PROFILE
300 long time;
301 #endif
302
303 if (!mp3DecInfo)
305
306 /* unpack frame header */
307 fhBytes = UnpackFrameHeader(mp3DecInfo, *inbuf);
308 if (fhBytes < 0)
309 return ERR_MP3_INVALID_FRAMEHEADER; /* don't clear outbuf since we don't know size (failed to parse header) */
310 *inbuf += fhBytes;
311
312#ifdef PROFILE
313 time = systime_get();
314#endif
315 /* unpack side info */
316 siBytes = UnpackSideInfo(mp3DecInfo, *inbuf);
317 if (siBytes < 0) {
318 MP3ClearBadFrame(mp3DecInfo, outbuf);
320 }
321 *inbuf += siBytes;
322 *bytesLeft -= (fhBytes + siBytes);
323#ifdef PROFILE
324 time = systime_get() - time;
325 printf("UnpackSideInfo: %i ms\n", time);
326#endif
327
328
329 /* if free mode, need to calculate bitrate and nSlots manually, based on frame size */
330 if (mp3DecInfo->bitrate == 0 || mp3DecInfo->freeBitrateFlag) {
331 if (!mp3DecInfo->freeBitrateFlag) {
332 /* first time through, need to scan for next sync word and figure out frame size */
333 mp3DecInfo->freeBitrateFlag = 1;
334 mp3DecInfo->freeBitrateSlots = MP3FindFreeSync(*inbuf, *inbuf - fhBytes - siBytes, *bytesLeft);
335 if (mp3DecInfo->freeBitrateSlots < 0) {
336 MP3ClearBadFrame(mp3DecInfo, outbuf);
338 }
339 freeFrameBytes = mp3DecInfo->freeBitrateSlots + fhBytes + siBytes;
340 mp3DecInfo->bitrate = (freeFrameBytes * mp3DecInfo->samprate * 8) / (mp3DecInfo->nGrans * mp3DecInfo->nGranSamps);
341 }
342 mp3DecInfo->nSlots = mp3DecInfo->freeBitrateSlots + CheckPadBit(mp3DecInfo); /* add pad byte, if required */
343 }
344
345 /* useSize != 0 means we're getting reformatted (RTP) packets (see RFC 3119)
346 * - calling function assembles "self-contained" MP3 frames by shifting any main_data
347 * from the bit reservoir (in previous frames) to AFTER the sync word and side info
348 * - calling function should set mainDataBegin to 0, and tell us exactly how large this
349 * frame is (in bytesLeft)
350 */
351 if (useSize) {
352 mp3DecInfo->nSlots = *bytesLeft;
353 if (mp3DecInfo->mainDataBegin != 0 || mp3DecInfo->nSlots <= 0) {
354 /* error - non self-contained frame, or missing frame (size <= 0), could do loss concealment here */
355 MP3ClearBadFrame(mp3DecInfo, outbuf);
357 }
358
359 /* can operate in-place on reformatted frames */
360 mp3DecInfo->mainDataBytes = mp3DecInfo->nSlots;
361 mainPtr = *inbuf;
362 *inbuf += mp3DecInfo->nSlots;
363 *bytesLeft -= (mp3DecInfo->nSlots);
364 } else {
365 /* out of data - assume last or truncated frame */
366 if (mp3DecInfo->nSlots > (int)*bytesLeft) {
367 MP3ClearBadFrame(mp3DecInfo, outbuf);
369 }
370
371#ifdef PROFILE
372 time = systime_get();
373#endif
374 /* fill main data buffer with enough new data for this frame */
375 if (mp3DecInfo->mainDataBytes >= mp3DecInfo->mainDataBegin) {
376 /* adequate "old" main data available (i.e. bit reservoir) */
377 ::fl::memmove(mp3DecInfo->mainBuf, mp3DecInfo->mainBuf + mp3DecInfo->mainDataBytes - mp3DecInfo->mainDataBegin, static_cast<fl::size>(mp3DecInfo->mainDataBegin));
378 ::fl::memcopy(mp3DecInfo->mainBuf + mp3DecInfo->mainDataBegin, *inbuf, static_cast<fl::size>(mp3DecInfo->nSlots));
379
380 mp3DecInfo->mainDataBytes = mp3DecInfo->mainDataBegin + mp3DecInfo->nSlots;
381 *inbuf += mp3DecInfo->nSlots;
382 *bytesLeft -= (mp3DecInfo->nSlots);
383 mainPtr = mp3DecInfo->mainBuf;
384 } else {
385 /* not enough data in bit reservoir from previous frames (perhaps starting in middle of file) */
386 ::fl::memcopy(mp3DecInfo->mainBuf + mp3DecInfo->mainDataBytes, *inbuf, static_cast<fl::size>(mp3DecInfo->nSlots));
387 mp3DecInfo->mainDataBytes += mp3DecInfo->nSlots;
388 *inbuf += mp3DecInfo->nSlots;
389 *bytesLeft -= (mp3DecInfo->nSlots);
390 MP3ClearBadFrame(mp3DecInfo, outbuf);
392 }
393#ifdef PROFILE
394 time = systime_get() - time;
395 printf("data buffer filling: %i ms\n", time);
396#endif
397
398 }
399 bitOffset = 0;
400 mainBits = mp3DecInfo->mainDataBytes * 8;
401
402 /* decode one complete frame */
403 for (gr = 0; gr < mp3DecInfo->nGrans; gr++) {
404 for (ch = 0; ch < mp3DecInfo->nChans; ch++) {
405
406 #ifdef PROFILE
407 time = systime_get();
408 #endif
409 /* unpack scale factors and compute size of scale factor block */
410 prevBitOffset = bitOffset;
411 offset = UnpackScaleFactors(mp3DecInfo, mainPtr, &bitOffset, mainBits, gr, ch);
412 #ifdef PROFILE
413 time = systime_get() - time;
414 printf("UnpackScaleFactors: %i ms\n", time);
415 #endif
416
417 sfBlockBits = 8*offset - prevBitOffset + bitOffset;
418 huffBlockBits = mp3DecInfo->part23Length[gr][ch] - sfBlockBits;
419 mainPtr += offset;
420 mainBits -= sfBlockBits;
421
422 if (offset < 0 || mainBits < huffBlockBits) {
423 MP3ClearBadFrame(mp3DecInfo, outbuf);
425 }
426
427 #ifdef PROFILE
428 time = systime_get();
429 #endif
430 /* decode Huffman code words */
431 prevBitOffset = bitOffset;
432 offset = DecodeHuffman(mp3DecInfo, mainPtr, &bitOffset, huffBlockBits, gr, ch);
433 if (offset < 0) {
434 MP3ClearBadFrame(mp3DecInfo, outbuf);
436 }
437 #ifdef PROFILE
438 time = systime_get() - time;
439 printf("Huffman: %i ms\n", time);
440 #endif
441
442 mainPtr += offset;
443 mainBits -= (8*offset - prevBitOffset + bitOffset);
444 }
445
446 #ifdef PROFILE
447 time = systime_get();
448 #endif
449 /* dequantize coefficients, decode stereo, reorder short blocks */
450 if (Dequantize(mp3DecInfo, gr) < 0) {
451 MP3ClearBadFrame(mp3DecInfo, outbuf);
453 }
454 #ifdef PROFILE
455 time = systime_get() - time;
456 printf("Dequantize: %i ms\n", time);
457 #endif
458
459 /* alias reduction, inverse MDCT, overlap-add, frequency inversion */
460 for (ch = 0; ch < mp3DecInfo->nChans; ch++)
461 {
462 #ifdef PROFILE
463 time = systime_get();
464 #endif
465 if (IMDCT(mp3DecInfo, gr, ch) < 0) {
466 MP3ClearBadFrame(mp3DecInfo, outbuf);
467 return ERR_MP3_INVALID_IMDCT;
468 }
469 #ifdef PROFILE
470 time = systime_get() - time;
471 printf("IMDCT: %i ms\n", time);
472 #endif
473 }
474
475 #ifdef PROFILE
476 time = systime_get();
477 #endif
478 /* subband transform - if stereo, interleaves pcm LRLRLR */
479 if (Subband(mp3DecInfo, outbuf + gr*mp3DecInfo->nGranSamps*mp3DecInfo->nChans) < 0) {
480 MP3ClearBadFrame(mp3DecInfo, outbuf);
482 }
483 #ifdef PROFILE
484 time = systime_get() - time;
485 printf("Subband: %i ms\n", time);
486 #endif
487
488 }
489 return ERR_MP3_NONE;
490}
491
492} // namespace third_party
493} // namespace fl
fl::UISlider offset("Offset", 0.0f, 0.0f, 1.0f, 0.01f)
#define SYNCWORDL
Definition mp3common.h:64
#define SYNCWORDH
Definition mp3common.h:63
struct _MP3DecInfo MP3DecInfo
MPEGVersion version
Definition mp3common.h:91
int part23Length[MAX_NGRAN][MAX_NCHAN]
Definition mp3common.h:96
int mainDataBegin
Definition mp3common.h:93
int mainDataBytes
Definition mp3common.h:94
int freeBitrateSlots
Definition mp3common.h:81
unsigned char mainBuf[MAINBUF_SIZE]
Definition mp3common.h:77
int freeBitrateFlag
Definition mp3common.h:80
int nGranSamps
Definition mp3common.h:88
@ ERR_MP3_INVALID_SCALEFACT
Definition mp3dec.h:99
@ ERR_MP3_INVALID_IMDCT
Definition mp3dec.h:102
@ ERR_MP3_NONE
Definition mp3dec.h:91
@ ERR_MP3_INDATA_UNDERFLOW
Definition mp3dec.h:92
@ ERR_MP3_MAINDATA_UNDERFLOW
Definition mp3dec.h:93
@ ERR_MP3_INVALID_HUFFCODES
Definition mp3dec.h:100
@ ERR_MP3_INVALID_FRAMEHEADER
Definition mp3dec.h:97
@ ERR_MP3_INVALID_SUBBAND
Definition mp3dec.h:103
@ ERR_MP3_INVALID_DEQUANTIZE
Definition mp3dec.h:101
@ ERR_MP3_FREE_BITRATE_SYNC
Definition mp3dec.h:94
@ ERR_MP3_INVALID_SIDEINFO
Definition mp3dec.h:98
@ ERR_MP3_NULL_POINTER
Definition mp3dec.h:96
void * HMP3Decoder
Definition mp3dec.h:88
struct _MP3FrameInfo MP3FrameInfo
int MP3FindSyncWord(const unsigned char *buf, int nBytes) FL_NOEXCEPT
Definition mp3dec.hpp:116
int Dequantize(MP3DecInfo *mp3DecInfo, int gr) FL_NOEXCEPT
Definition dequant.hpp:78
static void MP3ClearBadFrame(MP3DecInfo *mp3DecInfo, short *outbuf) FL_NOEXCEPT
Definition mp3dec.hpp:260
void MP3FreeDecoder(HMP3Decoder hMP3Decoder) FL_NOEXCEPT
Definition mp3dec.hpp:93
HMP3Decoder MP3InitDecoder(void) FL_NOEXCEPT
Definition mp3dec.hpp:72
int UnpackFrameHeader(MP3DecInfo *mp3DecInfo, const unsigned char *buf) FL_NOEXCEPT
int UnpackScaleFactors(MP3DecInfo *mp3DecInfo, const unsigned char *buf, int *bitOffset, int bitsAvail, int gr, int ch) FL_NOEXCEPT
Definition scalfact.hpp:357
int MP3Decode(HMP3Decoder hMP3Decoder, const unsigned char **inbuf, size_t *bytesLeft, short *outbuf, int useSize) FL_NOEXCEPT
Definition mp3dec.hpp:292
void MP3GetLastFrameInfo(HMP3Decoder hMP3Decoder, MP3FrameInfo *mp3FrameInfo) FL_NOEXCEPT
Definition mp3dec.hpp:196
static int MP3FindFreeSync(const unsigned char *buf, const unsigned char firstFH[4], int nBytes) FL_NOEXCEPT
Definition mp3dec.hpp:153
int UnpackSideInfo(MP3DecInfo *mp3DecInfo, const unsigned char *buf) FL_NOEXCEPT
const short samplesPerFrameTab[3][3]
Definition mp3tabs.hpp:88
int DecodeHuffman(MP3DecInfo *mp3DecInfo, const unsigned char *buf, int *bitOffset, int huffBlockBits, int gr, int ch) FL_NOEXCEPT
Definition huffman.hpp:385
void FreeBuffers(MP3DecInfo *mp3DecInfo) FL_NOEXCEPT
Definition buffers.hpp:163
int IMDCT(MP3DecInfo *mp3DecInfo, int gr, int ch) FL_NOEXCEPT
MP3DecInfo * AllocateBuffers(void) FL_NOEXCEPT
Definition buffers.hpp:99
int MP3GetNextFrameInfo(HMP3Decoder hMP3Decoder, MP3FrameInfo *mp3FrameInfo, unsigned char *buf) FL_NOEXCEPT
Definition mp3dec.hpp:233
int Subband(MP3DecInfo *mp3DecInfo, short *pcmBuf) FL_NOEXCEPT
Definition subband.hpp:65
int CheckPadBit(MP3DecInfo *mp3DecInfo) FL_NOEXCEPT
fl::u64 time() FL_NOEXCEPT
Alias for millis64() - returns 64-bit millisecond time.
Definition chrono.h:346
void printf(const char *format, const Args &... args) FL_NOEXCEPT
Printf-like formatting function that prints directly to the platform output.
Definition stdio.h:635
void * memcopy(void *dest, const void *src, size_t n) FL_NOEXCEPT
Definition cstring.h:103
void * memmove(void *dest, const void *src, size_t n) FL_NOEXCEPT
Base definition for an LED controller.
Definition crgb.hpp:179
#define FL_NOEXCEPT