YARP
Yet Another Robot Platform
 
Loading...
Searching...
No Matches
dr_mp3.h
Go to the documentation of this file.
1/*
2MP3 audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
3dr_mp3 - v0.7.0 - TBD
4
5David Reid - mackron@gmail.com
6
7GitHub: https://github.com/mackron/dr_libs
8
9Based on minimp3 (https://github.com/lieff/minimp3) which is where the real work was done. See the bottom of this file for differences between minimp3 and dr_mp3.
10*/
11
12/*
13Introduction
14=============
15dr_mp3 is a single file library. To use it, do something like the following in one .c file.
16
17 ```c
18 #define DR_MP3_IMPLEMENTATION
19 #include "dr_mp3.h"
20 ```
21
22You can then #include this file in other parts of the program as you would with any other header file. To decode audio data, do something like the following:
23
24 ```c
25 drmp3 mp3;
26 if (!drmp3_init_file(&mp3, "MySong.mp3", NULL)) {
27 // Failed to open file
28 }
29
30 ...
31
32 drmp3_uint64 framesRead = drmp3_read_pcm_frames_f32(pMP3, framesToRead, pFrames);
33 ```
34
35The drmp3 object is transparent so you can get access to the channel count and sample rate like so:
36
37 ```
38 drmp3_uint32 channels = mp3.channels;
39 drmp3_uint32 sampleRate = mp3.sampleRate;
40 ```
41
42The example above initializes a decoder from a file, but you can also initialize it from a block of memory and read and seek callbacks with
43`drmp3_init_memory()` and `drmp3_init()` respectively.
44
45You do not need to do any annoying memory management when reading PCM frames - this is all managed internally. You can request any number of PCM frames in each
46call to `drmp3_read_pcm_frames_f32()` and it will return as many PCM frames as it can, up to the requested amount.
47
48You can also decode an entire file in one go with `drmp3_open_and_read_pcm_frames_f32()`, `drmp3_open_memory_and_read_pcm_frames_f32()` and
49`drmp3_open_file_and_read_pcm_frames_f32()`.
50
51
52Build Options
53=============
54#define these options before including this file.
55
56#define DR_MP3_NO_STDIO
57 Disable drmp3_init_file(), etc.
58
59#define DR_MP3_NO_SIMD
60 Disable SIMD optimizations.
61*/
62
63#ifndef dr_mp3_h
64#define dr_mp3_h
65
66#ifdef __cplusplus
67extern "C" {
68#endif
69
70#define DRMP3_STRINGIFY(x) #x
71#define DRMP3_XSTRINGIFY(x) DRMP3_STRINGIFY(x)
72
73#define DRMP3_VERSION_MAJOR 0
74#define DRMP3_VERSION_MINOR 7
75#define DRMP3_VERSION_REVISION 0
76#define DRMP3_VERSION_STRING DRMP3_XSTRINGIFY(DRMP3_VERSION_MAJOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_MINOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_REVISION)
77
78#include <stddef.h> /* For size_t. */
79
80/* Sized Types */
81typedef signed char drmp3_int8;
82typedef unsigned char drmp3_uint8;
83typedef signed short drmp3_int16;
84typedef unsigned short drmp3_uint16;
85typedef signed int drmp3_int32;
86typedef unsigned int drmp3_uint32;
87#if defined(_MSC_VER) && !defined(__clang__)
88 typedef signed __int64 drmp3_int64;
89 typedef unsigned __int64 drmp3_uint64;
90#else
91 #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
92 #pragma GCC diagnostic push
93 #pragma GCC diagnostic ignored "-Wlong-long"
94 #if defined(__clang__)
95 #pragma GCC diagnostic ignored "-Wc++11-long-long"
96 #endif
97 #endif
98 typedef signed long long drmp3_int64;
99 typedef unsigned long long drmp3_uint64;
100 #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
101 #pragma GCC diagnostic pop
102 #endif
103#endif
104#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC) || defined(__powerpc64__)
106#else
108#endif
111#define DRMP3_TRUE 1
112#define DRMP3_FALSE 0
113
114/* Weird shifting syntax is for VC6 compatibility. */
115#define DRMP3_UINT64_MAX (((drmp3_uint64)0xFFFFFFFF << 32) | (drmp3_uint64)0xFFFFFFFF)
116/* End Sized Types */
117
118/* Decorations */
119#if !defined(DRMP3_API)
120 #if defined(DRMP3_DLL)
121 #if defined(_WIN32)
122 #define DRMP3_DLL_IMPORT __declspec(dllimport)
123 #define DRMP3_DLL_EXPORT __declspec(dllexport)
124 #define DRMP3_DLL_PRIVATE static
125 #else
126 #if defined(__GNUC__) && __GNUC__ >= 4
127 #define DRMP3_DLL_IMPORT __attribute__((visibility("default")))
128 #define DRMP3_DLL_EXPORT __attribute__((visibility("default")))
129 #define DRMP3_DLL_PRIVATE __attribute__((visibility("hidden")))
130 #else
131 #define DRMP3_DLL_IMPORT
132 #define DRMP3_DLL_EXPORT
133 #define DRMP3_DLL_PRIVATE static
134 #endif
135 #endif
136
137 #if defined(DR_MP3_IMPLEMENTATION)
138 #define DRMP3_API DRMP3_DLL_EXPORT
139 #else
140 #define DRMP3_API DRMP3_DLL_IMPORT
141 #endif
142 #define DRMP3_PRIVATE DRMP3_DLL_PRIVATE
143 #else
144 #define DRMP3_API extern
145 #define DRMP3_PRIVATE static
146 #endif
147#endif
148/* End Decorations */
149
150/* Result Codes */
152#define DRMP3_SUCCESS 0
153#define DRMP3_ERROR -1 /* A generic error. */
154#define DRMP3_INVALID_ARGS -2
155#define DRMP3_INVALID_OPERATION -3
156#define DRMP3_OUT_OF_MEMORY -4
157#define DRMP3_OUT_OF_RANGE -5
158#define DRMP3_ACCESS_DENIED -6
159#define DRMP3_DOES_NOT_EXIST -7
160#define DRMP3_ALREADY_EXISTS -8
161#define DRMP3_TOO_MANY_OPEN_FILES -9
162#define DRMP3_INVALID_FILE -10
163#define DRMP3_TOO_BIG -11
164#define DRMP3_PATH_TOO_LONG -12
165#define DRMP3_NAME_TOO_LONG -13
166#define DRMP3_NOT_DIRECTORY -14
167#define DRMP3_IS_DIRECTORY -15
168#define DRMP3_DIRECTORY_NOT_EMPTY -16
169#define DRMP3_END_OF_FILE -17
170#define DRMP3_NO_SPACE -18
171#define DRMP3_BUSY -19
172#define DRMP3_IO_ERROR -20
173#define DRMP3_INTERRUPT -21
174#define DRMP3_UNAVAILABLE -22
175#define DRMP3_ALREADY_IN_USE -23
176#define DRMP3_BAD_ADDRESS -24
177#define DRMP3_BAD_SEEK -25
178#define DRMP3_BAD_PIPE -26
179#define DRMP3_DEADLOCK -27
180#define DRMP3_TOO_MANY_LINKS -28
181#define DRMP3_NOT_IMPLEMENTED -29
182#define DRMP3_NO_MESSAGE -30
183#define DRMP3_BAD_MESSAGE -31
184#define DRMP3_NO_DATA_AVAILABLE -32
185#define DRMP3_INVALID_DATA -33
186#define DRMP3_TIMEOUT -34
187#define DRMP3_NO_NETWORK -35
188#define DRMP3_NOT_UNIQUE -36
189#define DRMP3_NOT_SOCKET -37
190#define DRMP3_NO_ADDRESS -38
191#define DRMP3_BAD_PROTOCOL -39
192#define DRMP3_PROTOCOL_UNAVAILABLE -40
193#define DRMP3_PROTOCOL_NOT_SUPPORTED -41
194#define DRMP3_PROTOCOL_FAMILY_NOT_SUPPORTED -42
195#define DRMP3_ADDRESS_FAMILY_NOT_SUPPORTED -43
196#define DRMP3_SOCKET_NOT_SUPPORTED -44
197#define DRMP3_CONNECTION_RESET -45
198#define DRMP3_ALREADY_CONNECTED -46
199#define DRMP3_NOT_CONNECTED -47
200#define DRMP3_CONNECTION_REFUSED -48
201#define DRMP3_NO_HOST -49
202#define DRMP3_IN_PROGRESS -50
203#define DRMP3_CANCELLED -51
204#define DRMP3_MEMORY_ALREADY_MAPPED -52
205#define DRMP3_AT_END -53
206/* End Result Codes */
207
208#define DRMP3_MAX_PCM_FRAMES_PER_MP3_FRAME 1152
209#define DRMP3_MAX_SAMPLES_PER_FRAME (DRMP3_MAX_PCM_FRAMES_PER_MP3_FRAME*2)
210
211/* Inline */
212#ifdef _MSC_VER
213 #define DRMP3_INLINE __forceinline
214#elif defined(__GNUC__)
215 /*
216 I've had a bug report where GCC is emitting warnings about functions possibly not being inlineable. This warning happens when
217 the __attribute__((always_inline)) attribute is defined without an "inline" statement. I think therefore there must be some
218 case where "__inline__" is not always defined, thus the compiler emitting these warnings. When using -std=c89 or -ansi on the
219 command line, we cannot use the "inline" keyword and instead need to use "__inline__". In an attempt to work around this issue
220 I am using "__inline__" only when we're compiling in strict ANSI mode.
221 */
222 #if defined(__STRICT_ANSI__)
223 #define DRMP3_GNUC_INLINE_HINT __inline__
224 #else
225 #define DRMP3_GNUC_INLINE_HINT inline
226 #endif
227
228 #if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 2)) || defined(__clang__)
229 #define DRMP3_INLINE DRMP3_GNUC_INLINE_HINT __attribute__((always_inline))
230 #else
231 #define DRMP3_INLINE DRMP3_GNUC_INLINE_HINT
232 #endif
233#elif defined(__WATCOMC__)
234 #define DRMP3_INLINE __inline
235#else
236 #define DRMP3_INLINE
237#endif
238/* End Inline */
239
240
243
244
245/* Allocation Callbacks */
246typedef struct
247{
249 void* (* onMalloc)(size_t sz, void* pUserData);
250 void* (* onRealloc)(void* p, size_t sz, void* pUserData);
251 void (* onFree)(void* p, void* pUserData);
253/* End Allocation Callbacks */
254
255
256/*
257Low Level Push API
258==================
259*/
260typedef struct
261{
262 int frame_bytes, channels, sample_rate, layer, bitrate_kbps;
264
265typedef struct
266{
267 float mdct_overlap[2][9*32], qmf_state[15*2*32];
268 int reserv, free_format_bytes;
269 drmp3_uint8 header[4], reserv_buf[511];
270} drmp3dec;
271
272/* Initializes a low level decoder. */
274
275/* Reads a frame from a low level decoder. */
276DRMP3_API int drmp3dec_decode_frame(drmp3dec *dec, const drmp3_uint8 *mp3, int mp3_bytes, void *pcm, drmp3dec_frame_info *info);
277
278/* Helper for converting between f32 and s16. */
279DRMP3_API void drmp3dec_f32_to_s16(const float *in, drmp3_int16 *out, size_t num_samples);
280
281
282
283/*
284Main API (Pull API)
285===================
286*/
293
294typedef struct
295{
296 drmp3_uint64 seekPosInBytes; /* Points to the first byte of an MP3 frame. */
297 drmp3_uint64 pcmFrameIndex; /* The index of the PCM frame this seek point targets. */
298 drmp3_uint16 mp3FramesToDiscard; /* The number of whole MP3 frames to be discarded before pcmFramesToDiscard. */
299 drmp3_uint16 pcmFramesToDiscard; /* The number of leading samples to read and discard. These are discarded after mp3FramesToDiscard. */
301
310
311typedef struct
312{
314 const void* pRawData; /* A pointer to the raw data. */
317
318
319/*
320Callback for when data is read. Return value is the number of bytes actually read.
321
322pUserData [in] The user data that was passed to drmp3_init(), and family.
323pBufferOut [out] The output buffer.
324bytesToRead [in] The number of bytes to read.
325
326Returns the number of bytes actually read.
327
328A return value of less than bytesToRead indicates the end of the stream. Do _not_ return from this callback until
329either the entire bytesToRead is filled or you have reached the end of the stream.
330*/
331typedef size_t (* drmp3_read_proc)(void* pUserData, void* pBufferOut, size_t bytesToRead);
332
333/*
334Callback for when data needs to be seeked.
335
336pUserData [in] The user data that was passed to drmp3_init(), and family.
337offset [in] The number of bytes to move, relative to the origin. Can be negative.
338origin [in] The origin of the seek.
339
340Returns whether or not the seek was successful.
341*/
342typedef drmp3_bool32 (* drmp3_seek_proc)(void* pUserData, int offset, drmp3_seek_origin origin);
343
344/*
345Callback for retrieving the current cursor position.
346
347pUserData [in] The user data that was passed to drmp3_init(), and family.
348pCursor [out] The cursor position in bytes from the start of the stream.
349
350Returns whether or not the cursor position was successfully retrieved.
351*/
352typedef drmp3_bool32 (* drmp3_tell_proc)(void* pUserData, drmp3_int64* pCursor);
353
354
355/*
356Callback for when metadata is read.
357
358Only the raw data is provided. The client is responsible for parsing the contents of the data themsevles.
359*/
360typedef void (* drmp3_meta_proc)(void* pUserData, const drmp3_metadata* pMetadata);
361
362
368
369typedef struct
370{
380 drmp3_uint32 mp3FrameChannels; /* The number of channels in the currently loaded MP3 frame. Internal use only. */
381 drmp3_uint32 mp3FrameSampleRate; /* The sample rate of the currently loaded MP3 frame. Internal use only. */
384 drmp3_uint8 pcmFrames[sizeof(float)*DRMP3_MAX_SAMPLES_PER_FRAME]; /* <-- Multipled by sizeof(float) to ensure there's enough room for DR_MP3_FLOAT_OUTPUT. */
385 drmp3_uint64 currentPCMFrame; /* The current PCM frame, globally. */
386 drmp3_uint64 streamCursor; /* The current byte the decoder is sitting on in the raw stream. */
387 drmp3_uint64 streamLength; /* The length of the stream in bytes. dr_mp3 will not read beyond this. If a ID3v1 or APE tag is present, this will be set to the first byte of the tag. */
388 drmp3_uint64 streamStartOffset; /* The offset of the start of the MP3 data. This is used for skipping ID3v2 and VBR tags. */
389 drmp3_seek_point* pSeekPoints; /* NULL by default. Set with drmp3_bind_seek_table(). Memory is owned by the client. dr_mp3 will never attempt to free this pointer. */
390 drmp3_uint32 seekPointCount; /* The number of items in pSeekPoints. When set to 0 assumes to no seek table. Defaults to zero. */
393 drmp3_uint64 totalPCMFrameCount; /* Set to DRMP3_UINT64_MAX if the length is unknown. Includes delay and padding. */
396 size_t dataSize;
401 struct
402 {
404 size_t dataSize;
406 } memory; /* Only used for decoders that were opened against a block of memory. */
407} drmp3;
408
409/*
410Initializes an MP3 decoder.
411
412onRead [in] The function to call when data needs to be read from the client.
413onSeek [in] The function to call when the read position of the client data needs to move.
414onTell [in] The function to call when the read position of the client data needs to be retrieved.
415pUserData [in, optional] A pointer to application defined data that will be passed to onRead and onSeek.
416
417Returns true if successful; false otherwise.
418
419Close the loader with drmp3_uninit().
420
421See also: drmp3_init_file(), drmp3_init_memory(), drmp3_uninit()
422*/
423DRMP3_API drmp3_bool32 drmp3_init(drmp3* pMP3, drmp3_read_proc onRead, drmp3_seek_proc onSeek, drmp3_tell_proc onTell, drmp3_meta_proc onMeta, void* pUserData, const drmp3_allocation_callbacks* pAllocationCallbacks);
424
425/*
426Initializes an MP3 decoder from a block of memory.
427
428This does not create a copy of the data. It is up to the application to ensure the buffer remains valid for
429the lifetime of the drmp3 object.
430
431The buffer should contain the contents of the entire MP3 file.
432*/
433DRMP3_API drmp3_bool32 drmp3_init_memory_with_metadata(drmp3* pMP3, const void* pData, size_t dataSize, drmp3_meta_proc onMeta, void* pUserDataMeta, const drmp3_allocation_callbacks* pAllocationCallbacks);
434DRMP3_API drmp3_bool32 drmp3_init_memory(drmp3* pMP3, const void* pData, size_t dataSize, const drmp3_allocation_callbacks* pAllocationCallbacks);
435
436#ifndef DR_MP3_NO_STDIO
437/*
438Initializes an MP3 decoder from a file.
439
440This holds the internal FILE object until drmp3_uninit() is called. Keep this in mind if you're caching drmp3
441objects because the operating system may restrict the number of file handles an application can have open at
442any given time.
443*/
444DRMP3_API drmp3_bool32 drmp3_init_file_with_metadata(drmp3* pMP3, const char* pFilePath, drmp3_meta_proc onMeta, void* pUserDataMeta, const drmp3_allocation_callbacks* pAllocationCallbacks);
445DRMP3_API drmp3_bool32 drmp3_init_file_with_metadata_w(drmp3* pMP3, const wchar_t* pFilePath, drmp3_meta_proc onMeta, void* pUserDataMeta, const drmp3_allocation_callbacks* pAllocationCallbacks);
446
447DRMP3_API drmp3_bool32 drmp3_init_file(drmp3* pMP3, const char* pFilePath, const drmp3_allocation_callbacks* pAllocationCallbacks);
448DRMP3_API drmp3_bool32 drmp3_init_file_w(drmp3* pMP3, const wchar_t* pFilePath, const drmp3_allocation_callbacks* pAllocationCallbacks);
449#endif
450
451/*
452Uninitializes an MP3 decoder.
453*/
455
456/*
457Reads PCM frames as interleaved 32-bit IEEE floating point PCM.
458
459Note that framesToRead specifies the number of PCM frames to read, _not_ the number of MP3 frames.
460*/
461DRMP3_API drmp3_uint64 drmp3_read_pcm_frames_f32(drmp3* pMP3, drmp3_uint64 framesToRead, float* pBufferOut);
462
463/*
464Reads PCM frames as interleaved signed 16-bit integer PCM.
465
466Note that framesToRead specifies the number of PCM frames to read, _not_ the number of MP3 frames.
467*/
469
470/*
471Seeks to a specific frame.
472
473Note that this is _not_ an MP3 frame, but rather a PCM frame.
474*/
476
477/*
478Calculates the total number of PCM frames in the MP3 stream. Cannot be used for infinite streams such as internet
479radio. Runs in linear time. Returns 0 on error.
480*/
482
483/*
484Calculates the total number of MP3 frames in the MP3 stream. Cannot be used for infinite streams such as internet
485radio. Runs in linear time. Returns 0 on error.
486*/
488
489/*
490Calculates the total number of MP3 and PCM frames in the MP3 stream. Cannot be used for infinite streams such as internet
491radio. Runs in linear time. Returns 0 on error.
492
493This is equivalent to calling drmp3_get_mp3_frame_count() and drmp3_get_pcm_frame_count() except that it's more efficient.
494*/
496
497/*
498Calculates the seekpoints based on PCM frames. This is slow.
499
500pSeekpoint count is a pointer to a uint32 containing the seekpoint count. On input it contains the desired count.
501On output it contains the actual count. The reason for this design is that the client may request too many
502seekpoints, in which case dr_mp3 will return a corrected count.
503
504Note that seektable seeking is not quite sample exact when the MP3 stream contains inconsistent sample rates.
505*/
507
508/*
509Binds a seek table to the decoder.
510
511This does _not_ make a copy of pSeekPoints - it only references it. It is up to the application to ensure this
512remains valid while it is bound to the decoder.
513
514Use drmp3_calculate_seek_points() to calculate the seek points.
515*/
517
518
519/*
520Opens an decodes an entire MP3 stream as a single operation.
521
522On output pConfig will receive the channel count and sample rate of the stream.
523
524Free the returned pointer with drmp3_free().
525*/
526DRMP3_API float* drmp3_open_and_read_pcm_frames_f32(drmp3_read_proc onRead, drmp3_seek_proc onSeek, drmp3_tell_proc onTell, void* pUserData, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks);
527DRMP3_API drmp3_int16* drmp3_open_and_read_pcm_frames_s16(drmp3_read_proc onRead, drmp3_seek_proc onSeek, drmp3_tell_proc onTell, void* pUserData, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks);
528
529DRMP3_API float* drmp3_open_memory_and_read_pcm_frames_f32(const void* pData, size_t dataSize, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks);
530DRMP3_API drmp3_int16* drmp3_open_memory_and_read_pcm_frames_s16(const void* pData, size_t dataSize, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks);
531
532#ifndef DR_MP3_NO_STDIO
533DRMP3_API float* drmp3_open_file_and_read_pcm_frames_f32(const char* filePath, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks);
534DRMP3_API drmp3_int16* drmp3_open_file_and_read_pcm_frames_s16(const char* filePath, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks);
535#endif
536
537/*
538Allocates a block of memory on the heap.
539*/
540DRMP3_API void* drmp3_malloc(size_t sz, const drmp3_allocation_callbacks* pAllocationCallbacks);
541
542/*
543Frees any memory that was allocated by a public drmp3 API.
544*/
545DRMP3_API void drmp3_free(void* p, const drmp3_allocation_callbacks* pAllocationCallbacks);
546
547#ifdef __cplusplus
548}
549#endif
550#endif /* dr_mp3_h */
551
552
553/************************************************************************************************************************************************************
554 ************************************************************************************************************************************************************
555
556 IMPLEMENTATION
557
558 ************************************************************************************************************************************************************
559 ************************************************************************************************************************************************************/
560#if defined(DR_MP3_IMPLEMENTATION)
561#ifndef dr_mp3_c
562#define dr_mp3_c
563
564#include <stdlib.h>
565#include <string.h>
566#include <limits.h> /* For INT_MAX */
567
568DRMP3_API void drmp3_version(drmp3_uint32* pMajor, drmp3_uint32* pMinor, drmp3_uint32* pRevision)
569{
570 if (pMajor) {
571 *pMajor = DRMP3_VERSION_MAJOR;
572 }
573
574 if (pMinor) {
575 *pMinor = DRMP3_VERSION_MINOR;
576 }
577
578 if (pRevision) {
579 *pRevision = DRMP3_VERSION_REVISION;
580 }
581}
582
583DRMP3_API const char* drmp3_version_string(void)
584{
586}
587
588/* Disable SIMD when compiling with TCC for now. */
589#if defined(__TINYC__)
590#define DR_MP3_NO_SIMD
591#endif
592
593#define DRMP3_OFFSET_PTR(p, offset) ((void*)((drmp3_uint8*)(p) + (offset)))
594
595#define DRMP3_MAX_FREE_FORMAT_FRAME_SIZE 2304 /* more than ISO spec's */
596#ifndef DRMP3_MAX_FRAME_SYNC_MATCHES
597#define DRMP3_MAX_FRAME_SYNC_MATCHES 10
598#endif
599
600#define DRMP3_MAX_L3_FRAME_PAYLOAD_BYTES DRMP3_MAX_FREE_FORMAT_FRAME_SIZE /* MUST be >= 320000/8/32000*1152 = 1440 */
601
602#define DRMP3_MAX_BITRESERVOIR_BYTES 511
603#define DRMP3_SHORT_BLOCK_TYPE 2
604#define DRMP3_STOP_BLOCK_TYPE 3
605#define DRMP3_MODE_MONO 3
606#define DRMP3_MODE_JOINT_STEREO 1
607#define DRMP3_HDR_SIZE 4
608#define DRMP3_HDR_IS_MONO(h) (((h[3]) & 0xC0) == 0xC0)
609#define DRMP3_HDR_IS_MS_STEREO(h) (((h[3]) & 0xE0) == 0x60)
610#define DRMP3_HDR_IS_FREE_FORMAT(h) (((h[2]) & 0xF0) == 0)
611#define DRMP3_HDR_IS_CRC(h) (!((h[1]) & 1))
612#define DRMP3_HDR_TEST_PADDING(h) ((h[2]) & 0x2)
613#define DRMP3_HDR_TEST_MPEG1(h) ((h[1]) & 0x8)
614#define DRMP3_HDR_TEST_NOT_MPEG25(h) ((h[1]) & 0x10)
615#define DRMP3_HDR_TEST_I_STEREO(h) ((h[3]) & 0x10)
616#define DRMP3_HDR_TEST_MS_STEREO(h) ((h[3]) & 0x20)
617#define DRMP3_HDR_GET_STEREO_MODE(h) (((h[3]) >> 6) & 3)
618#define DRMP3_HDR_GET_STEREO_MODE_EXT(h) (((h[3]) >> 4) & 3)
619#define DRMP3_HDR_GET_LAYER(h) (((h[1]) >> 1) & 3)
620#define DRMP3_HDR_GET_BITRATE(h) ((h[2]) >> 4)
621#define DRMP3_HDR_GET_SAMPLE_RATE(h) (((h[2]) >> 2) & 3)
622#define DRMP3_HDR_GET_MY_SAMPLE_RATE(h) (DRMP3_HDR_GET_SAMPLE_RATE(h) + (((h[1] >> 3) & 1) + ((h[1] >> 4) & 1))*3)
623#define DRMP3_HDR_IS_FRAME_576(h) ((h[1] & 14) == 2)
624#define DRMP3_HDR_IS_LAYER_1(h) ((h[1] & 6) == 6)
625
626#define DRMP3_BITS_DEQUANTIZER_OUT -1
627#define DRMP3_MAX_SCF (255 + DRMP3_BITS_DEQUANTIZER_OUT*4 - 210)
628#define DRMP3_MAX_SCFI ((DRMP3_MAX_SCF + 3) & ~3)
629
630#define DRMP3_MIN(a, b) ((a) > (b) ? (b) : (a))
631#define DRMP3_MAX(a, b) ((a) < (b) ? (b) : (a))
632
633#if !defined(DR_MP3_NO_SIMD)
634
635#if !defined(DR_MP3_ONLY_SIMD) && (defined(_M_X64) || defined(__x86_64__) || defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC))
636/* x64 always have SSE2, arm64 always have neon, no need for generic code */
637#define DR_MP3_ONLY_SIMD
638#endif
639
640#if ((defined(_MSC_VER) && _MSC_VER >= 1400) && defined(_M_X64)) || ((defined(__i386) || defined(_M_IX86) || defined(__i386__) || defined(__x86_64__)) && ((defined(_M_IX86_FP) && _M_IX86_FP == 2) || defined(__SSE2__)))
641#if defined(_MSC_VER)
642#include <intrin.h>
643#endif
644#include <emmintrin.h>
645#define DRMP3_HAVE_SSE 1
646#define DRMP3_HAVE_SIMD 1
647#define DRMP3_VSTORE _mm_storeu_ps
648#define DRMP3_VLD _mm_loadu_ps
649#define DRMP3_VSET _mm_set1_ps
650#define DRMP3_VADD _mm_add_ps
651#define DRMP3_VSUB _mm_sub_ps
652#define DRMP3_VMUL _mm_mul_ps
653#define DRMP3_VMAC(a, x, y) _mm_add_ps(a, _mm_mul_ps(x, y))
654#define DRMP3_VMSB(a, x, y) _mm_sub_ps(a, _mm_mul_ps(x, y))
655#define DRMP3_VMUL_S(x, s) _mm_mul_ps(x, _mm_set1_ps(s))
656#define DRMP3_VREV(x) _mm_shuffle_ps(x, x, _MM_SHUFFLE(0, 1, 2, 3))
657typedef __m128 drmp3_f4;
658#if defined(_MSC_VER) || defined(DR_MP3_ONLY_SIMD)
659#define drmp3_cpuid __cpuid
660#else
661static __inline__ __attribute__((always_inline)) void drmp3_cpuid(int CPUInfo[], const int InfoType)
662{
663#if defined(__PIC__)
664 __asm__ __volatile__(
665#if defined(__x86_64__)
666 "push %%rbx\n"
667 "cpuid\n"
668 "xchgl %%ebx, %1\n"
669 "pop %%rbx\n"
670#else
671 "xchgl %%ebx, %1\n"
672 "cpuid\n"
673 "xchgl %%ebx, %1\n"
674#endif
675 : "=a" (CPUInfo[0]), "=r" (CPUInfo[1]), "=c" (CPUInfo[2]), "=d" (CPUInfo[3])
676 : "a" (InfoType));
677#else
678 __asm__ __volatile__(
679 "cpuid"
680 : "=a" (CPUInfo[0]), "=b" (CPUInfo[1]), "=c" (CPUInfo[2]), "=d" (CPUInfo[3])
681 : "a" (InfoType));
682#endif
683}
684#endif
685static int drmp3_have_simd(void)
686{
687#ifdef DR_MP3_ONLY_SIMD
688 return 1;
689#else
690 static int g_have_simd;
691 int CPUInfo[4];
692#ifdef MINIMP3_TEST
693 static int g_counter;
694 if (g_counter++ > 100)
695 return 0;
696#endif
697 if (g_have_simd)
698 goto end;
699 drmp3_cpuid(CPUInfo, 0);
700 if (CPUInfo[0] > 0)
701 {
702 drmp3_cpuid(CPUInfo, 1);
703 g_have_simd = (CPUInfo[3] & (1 << 26)) + 1; /* SSE2 */
704 return g_have_simd - 1;
705 }
706
707end:
708 return g_have_simd - 1;
709#endif
710}
711#elif defined(__ARM_NEON) || defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC)
712#include <arm_neon.h>
713#define DRMP3_HAVE_SSE 0
714#define DRMP3_HAVE_SIMD 1
715#define DRMP3_VSTORE vst1q_f32
716#define DRMP3_VLD vld1q_f32
717#define DRMP3_VSET vmovq_n_f32
718#define DRMP3_VADD vaddq_f32
719#define DRMP3_VSUB vsubq_f32
720#define DRMP3_VMUL vmulq_f32
721#define DRMP3_VMAC(a, x, y) vmlaq_f32(a, x, y)
722#define DRMP3_VMSB(a, x, y) vmlsq_f32(a, x, y)
723#define DRMP3_VMUL_S(x, s) vmulq_f32(x, vmovq_n_f32(s))
724#define DRMP3_VREV(x) vcombine_f32(vget_high_f32(vrev64q_f32(x)), vget_low_f32(vrev64q_f32(x)))
725typedef float32x4_t drmp3_f4;
726static int drmp3_have_simd(void)
727{ /* TODO: detect neon for !DR_MP3_ONLY_SIMD */
728 return 1;
729}
730#else
731#define DRMP3_HAVE_SSE 0
732#define DRMP3_HAVE_SIMD 0
733#ifdef DR_MP3_ONLY_SIMD
734#error DR_MP3_ONLY_SIMD used, but SSE/NEON not enabled
735#endif
736#endif
737
738#else
739
740#define DRMP3_HAVE_SIMD 0
741
742#endif
743
744#if defined(__ARM_ARCH) && (__ARM_ARCH >= 6) && !defined(__aarch64__) && !defined(_M_ARM64) && !defined(_M_ARM64EC) && !defined(__ARM_ARCH_6M__)
745#define DRMP3_HAVE_ARMV6 1
746static __inline__ __attribute__((always_inline)) drmp3_int32 drmp3_clip_int16_arm(drmp3_int32 a)
747{
748 drmp3_int32 x = 0;
749 __asm__ ("ssat %0, #16, %1" : "=r"(x) : "r"(a));
750 return x;
751}
752#else
753#define DRMP3_HAVE_ARMV6 0
754#endif
755
756
757/* Standard library stuff. */
758#ifndef DRMP3_ASSERT
759#include <assert.h>
760#define DRMP3_ASSERT(expression) assert(expression)
761#endif
762#ifndef DRMP3_COPY_MEMORY
763#define DRMP3_COPY_MEMORY(dst, src, sz) memcpy((dst), (src), (sz))
764#endif
765#ifndef DRMP3_MOVE_MEMORY
766#define DRMP3_MOVE_MEMORY(dst, src, sz) memmove((dst), (src), (sz))
767#endif
768#ifndef DRMP3_ZERO_MEMORY
769#define DRMP3_ZERO_MEMORY(p, sz) memset((p), 0, (sz))
770#endif
771#define DRMP3_ZERO_OBJECT(p) DRMP3_ZERO_MEMORY((p), sizeof(*(p)))
772#ifndef DRMP3_MALLOC
773#define DRMP3_MALLOC(sz) malloc((sz))
774#endif
775#ifndef DRMP3_REALLOC
776#define DRMP3_REALLOC(p, sz) realloc((p), (sz))
777#endif
778#ifndef DRMP3_FREE
779#define DRMP3_FREE(p) free((p))
780#endif
781
782typedef struct
783{
784 const drmp3_uint8 *buf;
785 int pos, limit;
786} drmp3_bs;
787
788typedef struct
789{
790 float scf[3*64];
791 drmp3_uint8 total_bands, stereo_bands, bitalloc[64], scfcod[64];
792} drmp3_L12_scale_info;
793
794typedef struct
795{
796 drmp3_uint8 tab_offset, code_tab_width, band_count;
797} drmp3_L12_subband_alloc;
798
799typedef struct
800{
801 const drmp3_uint8 *sfbtab;
802 drmp3_uint16 part_23_length, big_values, scalefac_compress;
803 drmp3_uint8 global_gain, block_type, mixed_block_flag, n_long_sfb, n_short_sfb;
804 drmp3_uint8 table_select[3], region_count[3], subblock_gain[3];
805 drmp3_uint8 preflag, scalefac_scale, count1_table, scfsi;
806} drmp3_L3_gr_info;
807
808typedef struct
809{
810 drmp3_bs bs;
811 drmp3_uint8 maindata[DRMP3_MAX_BITRESERVOIR_BYTES + DRMP3_MAX_L3_FRAME_PAYLOAD_BYTES];
812 drmp3_L3_gr_info gr_info[4];
813 float grbuf[2][576], scf[40], syn[18 + 15][2*32];
814 drmp3_uint8 ist_pos[2][39];
815} drmp3dec_scratch;
816
817static void drmp3_bs_init(drmp3_bs *bs, const drmp3_uint8 *data, int bytes)
818{
819 bs->buf = data;
820 bs->pos = 0;
821 bs->limit = bytes*8;
822}
823
824static drmp3_uint32 drmp3_bs_get_bits(drmp3_bs *bs, int n)
825{
826 drmp3_uint32 next, cache = 0, s = bs->pos & 7;
827 int shl = n + s;
828 const drmp3_uint8 *p = bs->buf + (bs->pos >> 3);
829 if ((bs->pos += n) > bs->limit)
830 return 0;
831 next = *p++ & (255 >> s);
832 while ((shl -= 8) > 0)
833 {
834 cache |= next << shl;
835 next = *p++;
836 }
837 return cache | (next >> -shl);
838}
839
840static int drmp3_hdr_valid(const drmp3_uint8 *h)
841{
842 return h[0] == 0xff &&
843 ((h[1] & 0xF0) == 0xf0 || (h[1] & 0xFE) == 0xe2) &&
844 (DRMP3_HDR_GET_LAYER(h) != 0) &&
845 (DRMP3_HDR_GET_BITRATE(h) != 15) &&
846 (DRMP3_HDR_GET_SAMPLE_RATE(h) != 3);
847}
848
849static int drmp3_hdr_compare(const drmp3_uint8 *h1, const drmp3_uint8 *h2)
850{
851 return drmp3_hdr_valid(h2) &&
852 ((h1[1] ^ h2[1]) & 0xFE) == 0 &&
853 ((h1[2] ^ h2[2]) & 0x0C) == 0 &&
854 !(DRMP3_HDR_IS_FREE_FORMAT(h1) ^ DRMP3_HDR_IS_FREE_FORMAT(h2));
855}
856
857static unsigned drmp3_hdr_bitrate_kbps(const drmp3_uint8 *h)
858{
859 static const drmp3_uint8 halfrate[2][3][15] = {
860 { { 0,4,8,12,16,20,24,28,32,40,48,56,64,72,80 }, { 0,4,8,12,16,20,24,28,32,40,48,56,64,72,80 }, { 0,16,24,28,32,40,48,56,64,72,80,88,96,112,128 } },
861 { { 0,16,20,24,28,32,40,48,56,64,80,96,112,128,160 }, { 0,16,24,28,32,40,48,56,64,80,96,112,128,160,192 }, { 0,16,32,48,64,80,96,112,128,144,160,176,192,208,224 } },
862 };
863 return 2*halfrate[!!DRMP3_HDR_TEST_MPEG1(h)][DRMP3_HDR_GET_LAYER(h) - 1][DRMP3_HDR_GET_BITRATE(h)];
864}
865
866static unsigned drmp3_hdr_sample_rate_hz(const drmp3_uint8 *h)
867{
868 static const unsigned g_hz[3] = { 44100, 48000, 32000 };
869 return g_hz[DRMP3_HDR_GET_SAMPLE_RATE(h)] >> (int)!DRMP3_HDR_TEST_MPEG1(h) >> (int)!DRMP3_HDR_TEST_NOT_MPEG25(h);
870}
871
872static unsigned drmp3_hdr_frame_samples(const drmp3_uint8 *h)
873{
874 return DRMP3_HDR_IS_LAYER_1(h) ? 384 : (1152 >> (int)DRMP3_HDR_IS_FRAME_576(h));
875}
876
877static int drmp3_hdr_frame_bytes(const drmp3_uint8 *h, int free_format_size)
878{
879 int frame_bytes = drmp3_hdr_frame_samples(h)*drmp3_hdr_bitrate_kbps(h)*125/drmp3_hdr_sample_rate_hz(h);
880 if (DRMP3_HDR_IS_LAYER_1(h))
881 {
882 frame_bytes &= ~3; /* slot align */
883 }
884 return frame_bytes ? frame_bytes : free_format_size;
885}
886
887static int drmp3_hdr_padding(const drmp3_uint8 *h)
888{
889 return DRMP3_HDR_TEST_PADDING(h) ? (DRMP3_HDR_IS_LAYER_1(h) ? 4 : 1) : 0;
890}
891
892#ifndef DR_MP3_ONLY_MP3
893static const drmp3_L12_subband_alloc *drmp3_L12_subband_alloc_table(const drmp3_uint8 *hdr, drmp3_L12_scale_info *sci)
894{
895 const drmp3_L12_subband_alloc *alloc;
896 int mode = DRMP3_HDR_GET_STEREO_MODE(hdr);
897 int nbands, stereo_bands = (mode == DRMP3_MODE_MONO) ? 0 : (mode == DRMP3_MODE_JOINT_STEREO) ? (DRMP3_HDR_GET_STEREO_MODE_EXT(hdr) << 2) + 4 : 32;
898
899 if (DRMP3_HDR_IS_LAYER_1(hdr))
900 {
901 static const drmp3_L12_subband_alloc g_alloc_L1[] = { { 76, 4, 32 } };
902 alloc = g_alloc_L1;
903 nbands = 32;
904 } else if (!DRMP3_HDR_TEST_MPEG1(hdr))
905 {
906 static const drmp3_L12_subband_alloc g_alloc_L2M2[] = { { 60, 4, 4 }, { 44, 3, 7 }, { 44, 2, 19 } };
907 alloc = g_alloc_L2M2;
908 nbands = 30;
909 } else
910 {
911 static const drmp3_L12_subband_alloc g_alloc_L2M1[] = { { 0, 4, 3 }, { 16, 4, 8 }, { 32, 3, 12 }, { 40, 2, 7 } };
912 int sample_rate_idx = DRMP3_HDR_GET_SAMPLE_RATE(hdr);
913 unsigned kbps = drmp3_hdr_bitrate_kbps(hdr) >> (int)(mode != DRMP3_MODE_MONO);
914 if (!kbps) /* free-format */
915 {
916 kbps = 192;
917 }
918
919 alloc = g_alloc_L2M1;
920 nbands = 27;
921 if (kbps < 56)
922 {
923 static const drmp3_L12_subband_alloc g_alloc_L2M1_lowrate[] = { { 44, 4, 2 }, { 44, 3, 10 } };
924 alloc = g_alloc_L2M1_lowrate;
925 nbands = sample_rate_idx == 2 ? 12 : 8;
926 } else if (kbps >= 96 && sample_rate_idx != 1)
927 {
928 nbands = 30;
929 }
930 }
931
932 sci->total_bands = (drmp3_uint8)nbands;
933 sci->stereo_bands = (drmp3_uint8)DRMP3_MIN(stereo_bands, nbands);
934
935 return alloc;
936}
937
938static void drmp3_L12_read_scalefactors(drmp3_bs *bs, drmp3_uint8 *pba, drmp3_uint8 *scfcod, int bands, float *scf)
939{
940 static const float g_deq_L12[18*3] = {
941#define DRMP3_DQ(x) 9.53674316e-07f/x, 7.56931807e-07f/x, 6.00777173e-07f/x
942 DRMP3_DQ(3),DRMP3_DQ(7),DRMP3_DQ(15),DRMP3_DQ(31),DRMP3_DQ(63),DRMP3_DQ(127),DRMP3_DQ(255),DRMP3_DQ(511),DRMP3_DQ(1023),DRMP3_DQ(2047),DRMP3_DQ(4095),DRMP3_DQ(8191),DRMP3_DQ(16383),DRMP3_DQ(32767),DRMP3_DQ(65535),DRMP3_DQ(3),DRMP3_DQ(5),DRMP3_DQ(9)
943 };
944 int i, m;
945 for (i = 0; i < bands; i++)
946 {
947 float s = 0;
948 int ba = *pba++;
949 int mask = ba ? 4 + ((19 >> scfcod[i]) & 3) : 0;
950 for (m = 4; m; m >>= 1)
951 {
952 if (mask & m)
953 {
954 int b = drmp3_bs_get_bits(bs, 6);
955 s = g_deq_L12[ba*3 - 6 + b % 3]*(int)(1 << 21 >> b/3);
956 }
957 *scf++ = s;
958 }
959 }
960}
961
962static void drmp3_L12_read_scale_info(const drmp3_uint8 *hdr, drmp3_bs *bs, drmp3_L12_scale_info *sci)
963{
964 static const drmp3_uint8 g_bitalloc_code_tab[] = {
965 0,17, 3, 4, 5,6,7, 8,9,10,11,12,13,14,15,16,
966 0,17,18, 3,19,4,5, 6,7, 8, 9,10,11,12,13,16,
967 0,17,18, 3,19,4,5,16,
968 0,17,18,16,
969 0,17,18,19, 4,5,6, 7,8, 9,10,11,12,13,14,15,
970 0,17,18, 3,19,4,5, 6,7, 8, 9,10,11,12,13,14,
971 0, 2, 3, 4, 5,6,7, 8,9,10,11,12,13,14,15,16
972 };
973 const drmp3_L12_subband_alloc *subband_alloc = drmp3_L12_subband_alloc_table(hdr, sci);
974
975 int i, k = 0, ba_bits = 0;
976 const drmp3_uint8 *ba_code_tab = g_bitalloc_code_tab;
977
978 for (i = 0; i < sci->total_bands; i++)
979 {
980 drmp3_uint8 ba;
981 if (i == k)
982 {
983 k += subband_alloc->band_count;
984 ba_bits = subband_alloc->code_tab_width;
985 ba_code_tab = g_bitalloc_code_tab + subband_alloc->tab_offset;
986 subband_alloc++;
987 }
988 ba = ba_code_tab[drmp3_bs_get_bits(bs, ba_bits)];
989 sci->bitalloc[2*i] = ba;
990 if (i < sci->stereo_bands)
991 {
992 ba = ba_code_tab[drmp3_bs_get_bits(bs, ba_bits)];
993 }
994 sci->bitalloc[2*i + 1] = sci->stereo_bands ? ba : 0;
995 }
996
997 for (i = 0; i < 2*sci->total_bands; i++)
998 {
999 sci->scfcod[i] = (drmp3_uint8)(sci->bitalloc[i] ? DRMP3_HDR_IS_LAYER_1(hdr) ? 2 : drmp3_bs_get_bits(bs, 2) : 6);
1000 }
1001
1002 drmp3_L12_read_scalefactors(bs, sci->bitalloc, sci->scfcod, sci->total_bands*2, sci->scf);
1003
1004 for (i = sci->stereo_bands; i < sci->total_bands; i++)
1005 {
1006 sci->bitalloc[2*i + 1] = 0;
1007 }
1008}
1009
1010static int drmp3_L12_dequantize_granule(float *grbuf, drmp3_bs *bs, drmp3_L12_scale_info *sci, int group_size)
1011{
1012 int i, j, k, choff = 576;
1013 for (j = 0; j < 4; j++)
1014 {
1015 float *dst = grbuf + group_size*j;
1016 for (i = 0; i < 2*sci->total_bands; i++)
1017 {
1018 int ba = sci->bitalloc[i];
1019 if (ba != 0)
1020 {
1021 if (ba < 17)
1022 {
1023 int half = (1 << (ba - 1)) - 1;
1024 for (k = 0; k < group_size; k++)
1025 {
1026 dst[k] = (float)((int)drmp3_bs_get_bits(bs, ba) - half);
1027 }
1028 } else
1029 {
1030 unsigned mod = (2 << (ba - 17)) + 1; /* 3, 5, 9 */
1031 unsigned code = drmp3_bs_get_bits(bs, mod + 2 - (mod >> 3)); /* 5, 7, 10 */
1032 for (k = 0; k < group_size; k++, code /= mod)
1033 {
1034 dst[k] = (float)((int)(code % mod - mod/2));
1035 }
1036 }
1037 }
1038 dst += choff;
1039 choff = 18 - choff;
1040 }
1041 }
1042 return group_size*4;
1043}
1044
1045static void drmp3_L12_apply_scf_384(drmp3_L12_scale_info *sci, const float *scf, float *dst)
1046{
1047 int i, k;
1048 DRMP3_COPY_MEMORY(dst + 576 + sci->stereo_bands*18, dst + sci->stereo_bands*18, (sci->total_bands - sci->stereo_bands)*18*sizeof(float));
1049 for (i = 0; i < sci->total_bands; i++, dst += 18, scf += 6)
1050 {
1051 for (k = 0; k < 12; k++)
1052 {
1053 dst[k + 0] *= scf[0];
1054 dst[k + 576] *= scf[3];
1055 }
1056 }
1057}
1058#endif
1059
1060static int drmp3_L3_read_side_info(drmp3_bs *bs, drmp3_L3_gr_info *gr, const drmp3_uint8 *hdr)
1061{
1062 static const drmp3_uint8 g_scf_long[8][23] = {
1063 { 6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54,0 },
1064 { 12,12,12,12,12,12,16,20,24,28,32,40,48,56,64,76,90,2,2,2,2,2,0 },
1065 { 6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54,0 },
1066 { 6,6,6,6,6,6,8,10,12,14,16,18,22,26,32,38,46,54,62,70,76,36,0 },
1067 { 6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54,0 },
1068 { 4,4,4,4,4,4,6,6,8,8,10,12,16,20,24,28,34,42,50,54,76,158,0 },
1069 { 4,4,4,4,4,4,6,6,6,8,10,12,16,18,22,28,34,40,46,54,54,192,0 },
1070 { 4,4,4,4,4,4,6,6,8,10,12,16,20,24,30,38,46,56,68,84,102,26,0 }
1071 };
1072 static const drmp3_uint8 g_scf_short[8][40] = {
1073 { 4,4,4,4,4,4,4,4,4,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,24,24,24,30,30,30,40,40,40,18,18,18,0 },
1074 { 8,8,8,8,8,8,8,8,8,12,12,12,16,16,16,20,20,20,24,24,24,28,28,28,36,36,36,2,2,2,2,2,2,2,2,2,26,26,26,0 },
1075 { 4,4,4,4,4,4,4,4,4,6,6,6,6,6,6,8,8,8,10,10,10,14,14,14,18,18,18,26,26,26,32,32,32,42,42,42,18,18,18,0 },
1076 { 4,4,4,4,4,4,4,4,4,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,24,24,24,32,32,32,44,44,44,12,12,12,0 },
1077 { 4,4,4,4,4,4,4,4,4,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,24,24,24,30,30,30,40,40,40,18,18,18,0 },
1078 { 4,4,4,4,4,4,4,4,4,4,4,4,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,22,22,22,30,30,30,56,56,56,0 },
1079 { 4,4,4,4,4,4,4,4,4,4,4,4,6,6,6,6,6,6,10,10,10,12,12,12,14,14,14,16,16,16,20,20,20,26,26,26,66,66,66,0 },
1080 { 4,4,4,4,4,4,4,4,4,4,4,4,6,6,6,8,8,8,12,12,12,16,16,16,20,20,20,26,26,26,34,34,34,42,42,42,12,12,12,0 }
1081 };
1082 static const drmp3_uint8 g_scf_mixed[8][40] = {
1083 { 6,6,6,6,6,6,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,24,24,24,30,30,30,40,40,40,18,18,18,0 },
1084 { 12,12,12,4,4,4,8,8,8,12,12,12,16,16,16,20,20,20,24,24,24,28,28,28,36,36,36,2,2,2,2,2,2,2,2,2,26,26,26,0 },
1085 { 6,6,6,6,6,6,6,6,6,6,6,6,8,8,8,10,10,10,14,14,14,18,18,18,26,26,26,32,32,32,42,42,42,18,18,18,0 },
1086 { 6,6,6,6,6,6,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,24,24,24,32,32,32,44,44,44,12,12,12,0 },
1087 { 6,6,6,6,6,6,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,24,24,24,30,30,30,40,40,40,18,18,18,0 },
1088 { 4,4,4,4,4,4,6,6,4,4,4,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,22,22,22,30,30,30,56,56,56,0 },
1089 { 4,4,4,4,4,4,6,6,4,4,4,6,6,6,6,6,6,10,10,10,12,12,12,14,14,14,16,16,16,20,20,20,26,26,26,66,66,66,0 },
1090 { 4,4,4,4,4,4,6,6,4,4,4,6,6,6,8,8,8,12,12,12,16,16,16,20,20,20,26,26,26,34,34,34,42,42,42,12,12,12,0 }
1091 };
1092
1093 unsigned tables, scfsi = 0;
1094 int main_data_begin, part_23_sum = 0;
1095 int gr_count = DRMP3_HDR_IS_MONO(hdr) ? 1 : 2;
1096 int sr_idx = DRMP3_HDR_GET_MY_SAMPLE_RATE(hdr); sr_idx -= (sr_idx != 0);
1097
1098 if (DRMP3_HDR_TEST_MPEG1(hdr))
1099 {
1100 gr_count *= 2;
1101 main_data_begin = drmp3_bs_get_bits(bs, 9);
1102 scfsi = drmp3_bs_get_bits(bs, 7 + gr_count);
1103 } else
1104 {
1105 main_data_begin = drmp3_bs_get_bits(bs, 8 + gr_count) >> gr_count;
1106 }
1107
1108 do
1109 {
1110 if (DRMP3_HDR_IS_MONO(hdr))
1111 {
1112 scfsi <<= 4;
1113 }
1114 gr->part_23_length = (drmp3_uint16)drmp3_bs_get_bits(bs, 12);
1115 part_23_sum += gr->part_23_length;
1116 gr->big_values = (drmp3_uint16)drmp3_bs_get_bits(bs, 9);
1117 if (gr->big_values > 288)
1118 {
1119 return -1;
1120 }
1121 gr->global_gain = (drmp3_uint8)drmp3_bs_get_bits(bs, 8);
1122 gr->scalefac_compress = (drmp3_uint16)drmp3_bs_get_bits(bs, DRMP3_HDR_TEST_MPEG1(hdr) ? 4 : 9);
1123 gr->sfbtab = g_scf_long[sr_idx];
1124 gr->n_long_sfb = 22;
1125 gr->n_short_sfb = 0;
1126 if (drmp3_bs_get_bits(bs, 1))
1127 {
1128 gr->block_type = (drmp3_uint8)drmp3_bs_get_bits(bs, 2);
1129 if (!gr->block_type)
1130 {
1131 return -1;
1132 }
1133 gr->mixed_block_flag = (drmp3_uint8)drmp3_bs_get_bits(bs, 1);
1134 gr->region_count[0] = 7;
1135 gr->region_count[1] = 255;
1136 if (gr->block_type == DRMP3_SHORT_BLOCK_TYPE)
1137 {
1138 scfsi &= 0x0F0F;
1139 if (!gr->mixed_block_flag)
1140 {
1141 gr->region_count[0] = 8;
1142 gr->sfbtab = g_scf_short[sr_idx];
1143 gr->n_long_sfb = 0;
1144 gr->n_short_sfb = 39;
1145 } else
1146 {
1147 gr->sfbtab = g_scf_mixed[sr_idx];
1148 gr->n_long_sfb = DRMP3_HDR_TEST_MPEG1(hdr) ? 8 : 6;
1149 gr->n_short_sfb = 30;
1150 }
1151 }
1152 tables = drmp3_bs_get_bits(bs, 10);
1153 tables <<= 5;
1154 gr->subblock_gain[0] = (drmp3_uint8)drmp3_bs_get_bits(bs, 3);
1155 gr->subblock_gain[1] = (drmp3_uint8)drmp3_bs_get_bits(bs, 3);
1156 gr->subblock_gain[2] = (drmp3_uint8)drmp3_bs_get_bits(bs, 3);
1157 } else
1158 {
1159 gr->block_type = 0;
1160 gr->mixed_block_flag = 0;
1161 tables = drmp3_bs_get_bits(bs, 15);
1162 gr->region_count[0] = (drmp3_uint8)drmp3_bs_get_bits(bs, 4);
1163 gr->region_count[1] = (drmp3_uint8)drmp3_bs_get_bits(bs, 3);
1164 gr->region_count[2] = 255;
1165 }
1166 gr->table_select[0] = (drmp3_uint8)(tables >> 10);
1167 gr->table_select[1] = (drmp3_uint8)((tables >> 5) & 31);
1168 gr->table_select[2] = (drmp3_uint8)((tables) & 31);
1169 gr->preflag = (drmp3_uint8)(DRMP3_HDR_TEST_MPEG1(hdr) ? drmp3_bs_get_bits(bs, 1) : (gr->scalefac_compress >= 500));
1170 gr->scalefac_scale = (drmp3_uint8)drmp3_bs_get_bits(bs, 1);
1171 gr->count1_table = (drmp3_uint8)drmp3_bs_get_bits(bs, 1);
1172 gr->scfsi = (drmp3_uint8)((scfsi >> 12) & 15);
1173 scfsi <<= 4;
1174 gr++;
1175 } while(--gr_count);
1176
1177 if (part_23_sum + bs->pos > bs->limit + main_data_begin*8)
1178 {
1179 return -1;
1180 }
1181
1182 return main_data_begin;
1183}
1184
1185static void drmp3_L3_read_scalefactors(drmp3_uint8 *scf, drmp3_uint8 *ist_pos, const drmp3_uint8 *scf_size, const drmp3_uint8 *scf_count, drmp3_bs *bitbuf, int scfsi)
1186{
1187 int i, k;
1188 for (i = 0; i < 4 && scf_count[i]; i++, scfsi *= 2)
1189 {
1190 int cnt = scf_count[i];
1191 if (scfsi & 8)
1192 {
1193 DRMP3_COPY_MEMORY(scf, ist_pos, cnt);
1194 } else
1195 {
1196 int bits = scf_size[i];
1197 if (!bits)
1198 {
1199 DRMP3_ZERO_MEMORY(scf, cnt);
1200 DRMP3_ZERO_MEMORY(ist_pos, cnt);
1201 } else
1202 {
1203 int max_scf = (scfsi < 0) ? (1 << bits) - 1 : -1;
1204 for (k = 0; k < cnt; k++)
1205 {
1206 int s = drmp3_bs_get_bits(bitbuf, bits);
1207 ist_pos[k] = (drmp3_uint8)(s == max_scf ? -1 : s);
1208 scf[k] = (drmp3_uint8)s;
1209 }
1210 }
1211 }
1212 ist_pos += cnt;
1213 scf += cnt;
1214 }
1215 scf[0] = scf[1] = scf[2] = 0;
1216}
1217
1218static float drmp3_L3_ldexp_q2(float y, int exp_q2)
1219{
1220 static const float g_expfrac[4] = { 9.31322575e-10f,7.83145814e-10f,6.58544508e-10f,5.53767716e-10f };
1221 int e;
1222 do
1223 {
1224 e = DRMP3_MIN(30*4, exp_q2);
1225 y *= g_expfrac[e & 3]*(1 << 30 >> (e >> 2));
1226 } while ((exp_q2 -= e) > 0);
1227 return y;
1228}
1229
1230static void drmp3_L3_decode_scalefactors(const drmp3_uint8 *hdr, drmp3_uint8 *ist_pos, drmp3_bs *bs, const drmp3_L3_gr_info *gr, float *scf, int ch)
1231{
1232 static const drmp3_uint8 g_scf_partitions[3][28] = {
1233 { 6,5,5, 5,6,5,5,5,6,5, 7,3,11,10,0,0, 7, 7, 7,0, 6, 6,6,3, 8, 8,5,0 },
1234 { 8,9,6,12,6,9,9,9,6,9,12,6,15,18,0,0, 6,15,12,0, 6,12,9,6, 6,18,9,0 },
1235 { 9,9,6,12,9,9,9,9,9,9,12,6,18,18,0,0,12,12,12,0,12, 9,9,6,15,12,9,0 }
1236 };
1237 const drmp3_uint8 *scf_partition = g_scf_partitions[!!gr->n_short_sfb + !gr->n_long_sfb];
1238 drmp3_uint8 scf_size[4], iscf[40];
1239 int i, scf_shift = gr->scalefac_scale + 1, gain_exp, scfsi = gr->scfsi;
1240 float gain;
1241
1242 if (DRMP3_HDR_TEST_MPEG1(hdr))
1243 {
1244 static const drmp3_uint8 g_scfc_decode[16] = { 0,1,2,3, 12,5,6,7, 9,10,11,13, 14,15,18,19 };
1245 int part = g_scfc_decode[gr->scalefac_compress];
1246 scf_size[1] = scf_size[0] = (drmp3_uint8)(part >> 2);
1247 scf_size[3] = scf_size[2] = (drmp3_uint8)(part & 3);
1248 } else
1249 {
1250 static const drmp3_uint8 g_mod[6*4] = { 5,5,4,4,5,5,4,1,4,3,1,1,5,6,6,1,4,4,4,1,4,3,1,1 };
1251 int k, modprod, sfc, ist = DRMP3_HDR_TEST_I_STEREO(hdr) && ch;
1252 sfc = gr->scalefac_compress >> ist;
1253 for (k = ist*3*4; sfc >= 0; sfc -= modprod, k += 4)
1254 {
1255 for (modprod = 1, i = 3; i >= 0; i--)
1256 {
1257 scf_size[i] = (drmp3_uint8)(sfc / modprod % g_mod[k + i]);
1258 modprod *= g_mod[k + i];
1259 }
1260 }
1261 scf_partition += k;
1262 scfsi = -16;
1263 }
1264 drmp3_L3_read_scalefactors(iscf, ist_pos, scf_size, scf_partition, bs, scfsi);
1265
1266 if (gr->n_short_sfb)
1267 {
1268 int sh = 3 - scf_shift;
1269 for (i = 0; i < gr->n_short_sfb; i += 3)
1270 {
1271 iscf[gr->n_long_sfb + i + 0] = (drmp3_uint8)(iscf[gr->n_long_sfb + i + 0] + (gr->subblock_gain[0] << sh));
1272 iscf[gr->n_long_sfb + i + 1] = (drmp3_uint8)(iscf[gr->n_long_sfb + i + 1] + (gr->subblock_gain[1] << sh));
1273 iscf[gr->n_long_sfb + i + 2] = (drmp3_uint8)(iscf[gr->n_long_sfb + i + 2] + (gr->subblock_gain[2] << sh));
1274 }
1275 } else if (gr->preflag)
1276 {
1277 static const drmp3_uint8 g_preamp[10] = { 1,1,1,1,2,2,3,3,3,2 };
1278 for (i = 0; i < 10; i++)
1279 {
1280 iscf[11 + i] = (drmp3_uint8)(iscf[11 + i] + g_preamp[i]);
1281 }
1282 }
1283
1284 gain_exp = gr->global_gain + DRMP3_BITS_DEQUANTIZER_OUT*4 - 210 - (DRMP3_HDR_IS_MS_STEREO(hdr) ? 2 : 0);
1285 gain = drmp3_L3_ldexp_q2(1 << (DRMP3_MAX_SCFI/4), DRMP3_MAX_SCFI - gain_exp);
1286 for (i = 0; i < (int)(gr->n_long_sfb + gr->n_short_sfb); i++)
1287 {
1288 scf[i] = drmp3_L3_ldexp_q2(gain, iscf[i] << scf_shift);
1289 }
1290}
1291
1292static const float g_drmp3_pow43[129 + 16] = {
1293 0,-1,-2.519842f,-4.326749f,-6.349604f,-8.549880f,-10.902724f,-13.390518f,-16.000000f,-18.720754f,-21.544347f,-24.463781f,-27.473142f,-30.567351f,-33.741992f,-36.993181f,
1294 0,1,2.519842f,4.326749f,6.349604f,8.549880f,10.902724f,13.390518f,16.000000f,18.720754f,21.544347f,24.463781f,27.473142f,30.567351f,33.741992f,36.993181f,40.317474f,43.711787f,47.173345f,50.699631f,54.288352f,57.937408f,61.644865f,65.408941f,69.227979f,73.100443f,77.024898f,81.000000f,85.024491f,89.097188f,93.216975f,97.382800f,101.593667f,105.848633f,110.146801f,114.487321f,118.869381f,123.292209f,127.755065f,132.257246f,136.798076f,141.376907f,145.993119f,150.646117f,155.335327f,160.060199f,164.820202f,169.614826f,174.443577f,179.305980f,184.201575f,189.129918f,194.090580f,199.083145f,204.107210f,209.162385f,214.248292f,219.364564f,224.510845f,229.686789f,234.892058f,240.126328f,245.389280f,250.680604f,256.000000f,261.347174f,266.721841f,272.123723f,277.552547f,283.008049f,288.489971f,293.998060f,299.532071f,305.091761f,310.676898f,316.287249f,321.922592f,327.582707f,333.267377f,338.976394f,344.709550f,350.466646f,356.247482f,362.051866f,367.879608f,373.730522f,379.604427f,385.501143f,391.420496f,397.362314f,403.326427f,409.312672f,415.320884f,421.350905f,427.402579f,433.475750f,439.570269f,445.685987f,451.822757f,457.980436f,464.158883f,470.357960f,476.577530f,482.817459f,489.077615f,495.357868f,501.658090f,507.978156f,514.317941f,520.677324f,527.056184f,533.454404f,539.871867f,546.308458f,552.764065f,559.238575f,565.731879f,572.243870f,578.774440f,585.323483f,591.890898f,598.476581f,605.080431f,611.702349f,618.342238f,625.000000f,631.675540f,638.368763f,645.079578f
1295};
1296
1297static float drmp3_L3_pow_43(int x)
1298{
1299 float frac;
1300 int sign, mult = 256;
1301
1302 if (x < 129)
1303 {
1304 return g_drmp3_pow43[16 + x];
1305 }
1306
1307 if (x < 1024)
1308 {
1309 mult = 16;
1310 x <<= 3;
1311 }
1312
1313 sign = 2*x & 64;
1314 frac = (float)((x & 63) - sign) / ((x & ~63) + sign);
1315 return g_drmp3_pow43[16 + ((x + sign) >> 6)]*(1.f + frac*((4.f/3) + frac*(2.f/9)))*mult;
1316}
1317
1318static void drmp3_L3_huffman(float *dst, drmp3_bs *bs, const drmp3_L3_gr_info *gr_info, const float *scf, int layer3gr_limit)
1319{
1320 static const drmp3_int16 tabs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1321 785,785,785,785,784,784,784,784,513,513,513,513,513,513,513,513,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,
1322 -255,1313,1298,1282,785,785,785,785,784,784,784,784,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,290,288,
1323 -255,1313,1298,1282,769,769,769,769,529,529,529,529,529,529,529,529,528,528,528,528,528,528,528,528,512,512,512,512,512,512,512,512,290,288,
1324 -253,-318,-351,-367,785,785,785,785,784,784,784,784,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,819,818,547,547,275,275,275,275,561,560,515,546,289,274,288,258,
1325 -254,-287,1329,1299,1314,1312,1057,1057,1042,1042,1026,1026,784,784,784,784,529,529,529,529,529,529,529,529,769,769,769,769,768,768,768,768,563,560,306,306,291,259,
1326 -252,-413,-477,-542,1298,-575,1041,1041,784,784,784,784,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,-383,-399,1107,1092,1106,1061,849,849,789,789,1104,1091,773,773,1076,1075,341,340,325,309,834,804,577,577,532,532,516,516,832,818,803,816,561,561,531,531,515,546,289,289,288,258,
1327 -252,-429,-493,-559,1057,1057,1042,1042,529,529,529,529,529,529,529,529,784,784,784,784,769,769,769,769,512,512,512,512,512,512,512,512,-382,1077,-415,1106,1061,1104,849,849,789,789,1091,1076,1029,1075,834,834,597,581,340,340,339,324,804,833,532,532,832,772,818,803,817,787,816,771,290,290,290,290,288,258,
1328 -253,-349,-414,-447,-463,1329,1299,-479,1314,1312,1057,1057,1042,1042,1026,1026,785,785,785,785,784,784,784,784,769,769,769,769,768,768,768,768,-319,851,821,-335,836,850,805,849,341,340,325,336,533,533,579,579,564,564,773,832,578,548,563,516,321,276,306,291,304,259,
1329 -251,-572,-733,-830,-863,-879,1041,1041,784,784,784,784,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,-511,-527,-543,1396,1351,1381,1366,1395,1335,1380,-559,1334,1138,1138,1063,1063,1350,1392,1031,1031,1062,1062,1364,1363,1120,1120,1333,1348,881,881,881,881,375,374,359,373,343,358,341,325,791,791,1123,1122,-703,1105,1045,-719,865,865,790,790,774,774,1104,1029,338,293,323,308,-799,-815,833,788,772,818,803,816,322,292,307,320,561,531,515,546,289,274,288,258,
1330 -251,-525,-605,-685,-765,-831,-846,1298,1057,1057,1312,1282,785,785,785,785,784,784,784,784,769,769,769,769,512,512,512,512,512,512,512,512,1399,1398,1383,1367,1382,1396,1351,-511,1381,1366,1139,1139,1079,1079,1124,1124,1364,1349,1363,1333,882,882,882,882,807,807,807,807,1094,1094,1136,1136,373,341,535,535,881,775,867,822,774,-591,324,338,-671,849,550,550,866,864,609,609,293,336,534,534,789,835,773,-751,834,804,308,307,833,788,832,772,562,562,547,547,305,275,560,515,290,290,
1331 -252,-397,-477,-557,-622,-653,-719,-735,-750,1329,1299,1314,1057,1057,1042,1042,1312,1282,1024,1024,785,785,785,785,784,784,784,784,769,769,769,769,-383,1127,1141,1111,1126,1140,1095,1110,869,869,883,883,1079,1109,882,882,375,374,807,868,838,881,791,-463,867,822,368,263,852,837,836,-543,610,610,550,550,352,336,534,534,865,774,851,821,850,805,593,533,579,564,773,832,578,578,548,548,577,577,307,276,306,291,516,560,259,259,
1332 -250,-2107,-2507,-2764,-2909,-2974,-3007,-3023,1041,1041,1040,1040,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,-767,-1052,-1213,-1277,-1358,-1405,-1469,-1535,-1550,-1582,-1614,-1647,-1662,-1694,-1726,-1759,-1774,-1807,-1822,-1854,-1886,1565,-1919,-1935,-1951,-1967,1731,1730,1580,1717,-1983,1729,1564,-1999,1548,-2015,-2031,1715,1595,-2047,1714,-2063,1610,-2079,1609,-2095,1323,1323,1457,1457,1307,1307,1712,1547,1641,1700,1699,1594,1685,1625,1442,1442,1322,1322,-780,-973,-910,1279,1278,1277,1262,1276,1261,1275,1215,1260,1229,-959,974,974,989,989,-943,735,478,478,495,463,506,414,-1039,1003,958,1017,927,942,987,957,431,476,1272,1167,1228,-1183,1256,-1199,895,895,941,941,1242,1227,1212,1135,1014,1014,490,489,503,487,910,1013,985,925,863,894,970,955,1012,847,-1343,831,755,755,984,909,428,366,754,559,-1391,752,486,457,924,997,698,698,983,893,740,740,908,877,739,739,667,667,953,938,497,287,271,271,683,606,590,712,726,574,302,302,738,736,481,286,526,725,605,711,636,724,696,651,589,681,666,710,364,467,573,695,466,466,301,465,379,379,709,604,665,679,316,316,634,633,436,436,464,269,424,394,452,332,438,363,347,408,393,448,331,422,362,407,392,421,346,406,391,376,375,359,1441,1306,-2367,1290,-2383,1337,-2399,-2415,1426,1321,-2431,1411,1336,-2447,-2463,-2479,1169,1169,1049,1049,1424,1289,1412,1352,1319,-2495,1154,1154,1064,1064,1153,1153,416,390,360,404,403,389,344,374,373,343,358,372,327,357,342,311,356,326,1395,1394,1137,1137,1047,1047,1365,1392,1287,1379,1334,1364,1349,1378,1318,1363,792,792,792,792,1152,1152,1032,1032,1121,1121,1046,1046,1120,1120,1030,1030,-2895,1106,1061,1104,849,849,789,789,1091,1076,1029,1090,1060,1075,833,833,309,324,532,532,832,772,818,803,561,561,531,560,515,546,289,274,288,258,
1333 -250,-1179,-1579,-1836,-1996,-2124,-2253,-2333,-2413,-2477,-2542,-2574,-2607,-2622,-2655,1314,1313,1298,1312,1282,785,785,785,785,1040,1040,1025,1025,768,768,768,768,-766,-798,-830,-862,-895,-911,-927,-943,-959,-975,-991,-1007,-1023,-1039,-1055,-1070,1724,1647,-1103,-1119,1631,1767,1662,1738,1708,1723,-1135,1780,1615,1779,1599,1677,1646,1778,1583,-1151,1777,1567,1737,1692,1765,1722,1707,1630,1751,1661,1764,1614,1736,1676,1763,1750,1645,1598,1721,1691,1762,1706,1582,1761,1566,-1167,1749,1629,767,766,751,765,494,494,735,764,719,749,734,763,447,447,748,718,477,506,431,491,446,476,461,505,415,430,475,445,504,399,460,489,414,503,383,474,429,459,502,502,746,752,488,398,501,473,413,472,486,271,480,270,-1439,-1455,1357,-1471,-1487,-1503,1341,1325,-1519,1489,1463,1403,1309,-1535,1372,1448,1418,1476,1356,1462,1387,-1551,1475,1340,1447,1402,1386,-1567,1068,1068,1474,1461,455,380,468,440,395,425,410,454,364,467,466,464,453,269,409,448,268,432,1371,1473,1432,1417,1308,1460,1355,1446,1459,1431,1083,1083,1401,1416,1458,1445,1067,1067,1370,1457,1051,1051,1291,1430,1385,1444,1354,1415,1400,1443,1082,1082,1173,1113,1186,1066,1185,1050,-1967,1158,1128,1172,1097,1171,1081,-1983,1157,1112,416,266,375,400,1170,1142,1127,1065,793,793,1169,1033,1156,1096,1141,1111,1155,1080,1126,1140,898,898,808,808,897,897,792,792,1095,1152,1032,1125,1110,1139,1079,1124,882,807,838,881,853,791,-2319,867,368,263,822,852,837,866,806,865,-2399,851,352,262,534,534,821,836,594,594,549,549,593,593,533,533,848,773,579,579,564,578,548,563,276,276,577,576,306,291,516,560,305,305,275,259,
1334 -251,-892,-2058,-2620,-2828,-2957,-3023,-3039,1041,1041,1040,1040,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,-511,-527,-543,-559,1530,-575,-591,1528,1527,1407,1526,1391,1023,1023,1023,1023,1525,1375,1268,1268,1103,1103,1087,1087,1039,1039,1523,-604,815,815,815,815,510,495,509,479,508,463,507,447,431,505,415,399,-734,-782,1262,-815,1259,1244,-831,1258,1228,-847,-863,1196,-879,1253,987,987,748,-767,493,493,462,477,414,414,686,669,478,446,461,445,474,429,487,458,412,471,1266,1264,1009,1009,799,799,-1019,-1276,-1452,-1581,-1677,-1757,-1821,-1886,-1933,-1997,1257,1257,1483,1468,1512,1422,1497,1406,1467,1496,1421,1510,1134,1134,1225,1225,1466,1451,1374,1405,1252,1252,1358,1480,1164,1164,1251,1251,1238,1238,1389,1465,-1407,1054,1101,-1423,1207,-1439,830,830,1248,1038,1237,1117,1223,1148,1236,1208,411,426,395,410,379,269,1193,1222,1132,1235,1221,1116,976,976,1192,1162,1177,1220,1131,1191,963,963,-1647,961,780,-1663,558,558,994,993,437,408,393,407,829,978,813,797,947,-1743,721,721,377,392,844,950,828,890,706,706,812,859,796,960,948,843,934,874,571,571,-1919,690,555,689,421,346,539,539,944,779,918,873,932,842,903,888,570,570,931,917,674,674,-2575,1562,-2591,1609,-2607,1654,1322,1322,1441,1441,1696,1546,1683,1593,1669,1624,1426,1426,1321,1321,1639,1680,1425,1425,1305,1305,1545,1668,1608,1623,1667,1592,1638,1666,1320,1320,1652,1607,1409,1409,1304,1304,1288,1288,1664,1637,1395,1395,1335,1335,1622,1636,1394,1394,1319,1319,1606,1621,1392,1392,1137,1137,1137,1137,345,390,360,375,404,373,1047,-2751,-2767,-2783,1062,1121,1046,-2799,1077,-2815,1106,1061,789,789,1105,1104,263,355,310,340,325,354,352,262,339,324,1091,1076,1029,1090,1060,1075,833,833,788,788,1088,1028,818,818,803,803,561,561,531,531,816,771,546,546,289,274,288,258,
1335 -253,-317,-381,-446,-478,-509,1279,1279,-811,-1179,-1451,-1756,-1900,-2028,-2189,-2253,-2333,-2414,-2445,-2511,-2526,1313,1298,-2559,1041,1041,1040,1040,1025,1025,1024,1024,1022,1007,1021,991,1020,975,1019,959,687,687,1018,1017,671,671,655,655,1016,1015,639,639,758,758,623,623,757,607,756,591,755,575,754,559,543,543,1009,783,-575,-621,-685,-749,496,-590,750,749,734,748,974,989,1003,958,988,973,1002,942,987,957,972,1001,926,986,941,971,956,1000,910,985,925,999,894,970,-1071,-1087,-1102,1390,-1135,1436,1509,1451,1374,-1151,1405,1358,1480,1420,-1167,1507,1494,1389,1342,1465,1435,1450,1326,1505,1310,1493,1373,1479,1404,1492,1464,1419,428,443,472,397,736,526,464,464,486,457,442,471,484,482,1357,1449,1434,1478,1388,1491,1341,1490,1325,1489,1463,1403,1309,1477,1372,1448,1418,1433,1476,1356,1462,1387,-1439,1475,1340,1447,1402,1474,1324,1461,1371,1473,269,448,1432,1417,1308,1460,-1711,1459,-1727,1441,1099,1099,1446,1386,1431,1401,-1743,1289,1083,1083,1160,1160,1458,1445,1067,1067,1370,1457,1307,1430,1129,1129,1098,1098,268,432,267,416,266,400,-1887,1144,1187,1082,1173,1113,1186,1066,1050,1158,1128,1143,1172,1097,1171,1081,420,391,1157,1112,1170,1142,1127,1065,1169,1049,1156,1096,1141,1111,1155,1080,1126,1154,1064,1153,1140,1095,1048,-2159,1125,1110,1137,-2175,823,823,1139,1138,807,807,384,264,368,263,868,838,853,791,867,822,852,837,866,806,865,790,-2319,851,821,836,352,262,850,805,849,-2399,533,533,835,820,336,261,578,548,563,577,532,532,832,772,562,562,547,547,305,275,560,515,290,290,288,258 };
1336 static const drmp3_uint8 tab32[] = { 130,162,193,209,44,28,76,140,9,9,9,9,9,9,9,9,190,254,222,238,126,94,157,157,109,61,173,205};
1337 static const drmp3_uint8 tab33[] = { 252,236,220,204,188,172,156,140,124,108,92,76,60,44,28,12 };
1338 static const drmp3_int16 tabindex[2*16] = { 0,32,64,98,0,132,180,218,292,364,426,538,648,746,0,1126,1460,1460,1460,1460,1460,1460,1460,1460,1842,1842,1842,1842,1842,1842,1842,1842 };
1339 static const drmp3_uint8 g_linbits[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,3,4,6,8,10,13,4,5,6,7,8,9,11,13 };
1340
1341#define DRMP3_PEEK_BITS(n) (bs_cache >> (32 - (n)))
1342#define DRMP3_FLUSH_BITS(n) { bs_cache <<= (n); bs_sh += (n); }
1343#define DRMP3_CHECK_BITS while (bs_sh >= 0) { bs_cache |= (drmp3_uint32)*bs_next_ptr++ << bs_sh; bs_sh -= 8; }
1344#define DRMP3_BSPOS ((bs_next_ptr - bs->buf)*8 - 24 + bs_sh)
1345
1346 float one = 0.0f;
1347 int ireg = 0, big_val_cnt = gr_info->big_values;
1348 const drmp3_uint8 *sfb = gr_info->sfbtab;
1349 const drmp3_uint8 *bs_next_ptr = bs->buf + bs->pos/8;
1350 drmp3_uint32 bs_cache = (((bs_next_ptr[0]*256u + bs_next_ptr[1])*256u + bs_next_ptr[2])*256u + bs_next_ptr[3]) << (bs->pos & 7);
1351 int pairs_to_decode, np, bs_sh = (bs->pos & 7) - 8;
1352 bs_next_ptr += 4;
1353
1354 while (big_val_cnt > 0)
1355 {
1356 int tab_num = gr_info->table_select[ireg];
1357 int sfb_cnt = gr_info->region_count[ireg++];
1358 const drmp3_int16 *codebook = tabs + tabindex[tab_num];
1359 int linbits = g_linbits[tab_num];
1360 if (linbits)
1361 {
1362 do
1363 {
1364 np = *sfb++ / 2;
1365 pairs_to_decode = DRMP3_MIN(big_val_cnt, np);
1366 one = *scf++;
1367 do
1368 {
1369 int j, w = 5;
1370 int leaf = codebook[DRMP3_PEEK_BITS(w)];
1371 while (leaf < 0)
1372 {
1373 DRMP3_FLUSH_BITS(w);
1374 w = leaf & 7;
1375 leaf = codebook[DRMP3_PEEK_BITS(w) - (leaf >> 3)];
1376 }
1377 DRMP3_FLUSH_BITS(leaf >> 8);
1378
1379 for (j = 0; j < 2; j++, dst++, leaf >>= 4)
1380 {
1381 int lsb = leaf & 0x0F;
1382 if (lsb == 15)
1383 {
1384 lsb += DRMP3_PEEK_BITS(linbits);
1385 DRMP3_FLUSH_BITS(linbits);
1386 DRMP3_CHECK_BITS;
1387 *dst = one*drmp3_L3_pow_43(lsb)*((drmp3_int32)bs_cache < 0 ? -1: 1);
1388 } else
1389 {
1390 *dst = g_drmp3_pow43[16 + lsb - 16*(bs_cache >> 31)]*one;
1391 }
1392 DRMP3_FLUSH_BITS(lsb ? 1 : 0);
1393 }
1394 DRMP3_CHECK_BITS;
1395 } while (--pairs_to_decode);
1396 } while ((big_val_cnt -= np) > 0 && --sfb_cnt >= 0);
1397 } else
1398 {
1399 do
1400 {
1401 np = *sfb++ / 2;
1402 pairs_to_decode = DRMP3_MIN(big_val_cnt, np);
1403 one = *scf++;
1404 do
1405 {
1406 int j, w = 5;
1407 int leaf = codebook[DRMP3_PEEK_BITS(w)];
1408 while (leaf < 0)
1409 {
1410 DRMP3_FLUSH_BITS(w);
1411 w = leaf & 7;
1412 leaf = codebook[DRMP3_PEEK_BITS(w) - (leaf >> 3)];
1413 }
1414 DRMP3_FLUSH_BITS(leaf >> 8);
1415
1416 for (j = 0; j < 2; j++, dst++, leaf >>= 4)
1417 {
1418 int lsb = leaf & 0x0F;
1419 *dst = g_drmp3_pow43[16 + lsb - 16*(bs_cache >> 31)]*one;
1420 DRMP3_FLUSH_BITS(lsb ? 1 : 0);
1421 }
1422 DRMP3_CHECK_BITS;
1423 } while (--pairs_to_decode);
1424 } while ((big_val_cnt -= np) > 0 && --sfb_cnt >= 0);
1425 }
1426 }
1427
1428 for (np = 1 - big_val_cnt;; dst += 4)
1429 {
1430 const drmp3_uint8 *codebook_count1 = (gr_info->count1_table) ? tab33 : tab32;
1431 int leaf = codebook_count1[DRMP3_PEEK_BITS(4)];
1432 if (!(leaf & 8))
1433 {
1434 leaf = codebook_count1[(leaf >> 3) + (bs_cache << 4 >> (32 - (leaf & 3)))];
1435 }
1436 DRMP3_FLUSH_BITS(leaf & 7);
1437 if (DRMP3_BSPOS > layer3gr_limit)
1438 {
1439 break;
1440 }
1441#define DRMP3_RELOAD_SCALEFACTOR if (!--np) { np = *sfb++/2; if (!np) break; one = *scf++; }
1442#define DRMP3_DEQ_COUNT1(s) if (leaf & (128 >> s)) { dst[s] = ((drmp3_int32)bs_cache < 0) ? -one : one; DRMP3_FLUSH_BITS(1) }
1443 DRMP3_RELOAD_SCALEFACTOR;
1444 DRMP3_DEQ_COUNT1(0);
1445 DRMP3_DEQ_COUNT1(1);
1446 DRMP3_RELOAD_SCALEFACTOR;
1447 DRMP3_DEQ_COUNT1(2);
1448 DRMP3_DEQ_COUNT1(3);
1449 DRMP3_CHECK_BITS;
1450 }
1451
1452 bs->pos = layer3gr_limit;
1453}
1454
1455static void drmp3_L3_midside_stereo(float *left, int n)
1456{
1457 int i = 0;
1458 float *right = left + 576;
1459#if DRMP3_HAVE_SIMD
1460 if (drmp3_have_simd())
1461 {
1462 for (; i < n - 3; i += 4)
1463 {
1464 drmp3_f4 vl = DRMP3_VLD(left + i);
1465 drmp3_f4 vr = DRMP3_VLD(right + i);
1466 DRMP3_VSTORE(left + i, DRMP3_VADD(vl, vr));
1467 DRMP3_VSTORE(right + i, DRMP3_VSUB(vl, vr));
1468 }
1469#ifdef __GNUC__
1470 /* Workaround for spurious -Waggressive-loop-optimizations warning from gcc.
1471 * For more info see: https://github.com/lieff/minimp3/issues/88
1472 */
1473 if (__builtin_constant_p(n % 4 == 0) && n % 4 == 0)
1474 return;
1475#endif
1476 }
1477#endif
1478 for (; i < n; i++)
1479 {
1480 float a = left[i];
1481 float b = right[i];
1482 left[i] = a + b;
1483 right[i] = a - b;
1484 }
1485}
1486
1487static void drmp3_L3_intensity_stereo_band(float *left, int n, float kl, float kr)
1488{
1489 int i;
1490 for (i = 0; i < n; i++)
1491 {
1492 left[i + 576] = left[i]*kr;
1493 left[i] = left[i]*kl;
1494 }
1495}
1496
1497static void drmp3_L3_stereo_top_band(const float *right, const drmp3_uint8 *sfb, int nbands, int max_band[3])
1498{
1499 int i, k;
1500
1501 max_band[0] = max_band[1] = max_band[2] = -1;
1502
1503 for (i = 0; i < nbands; i++)
1504 {
1505 for (k = 0; k < sfb[i]; k += 2)
1506 {
1507 if (right[k] != 0 || right[k + 1] != 0)
1508 {
1509 max_band[i % 3] = i;
1510 break;
1511 }
1512 }
1513 right += sfb[i];
1514 }
1515}
1516
1517static void drmp3_L3_stereo_process(float *left, const drmp3_uint8 *ist_pos, const drmp3_uint8 *sfb, const drmp3_uint8 *hdr, int max_band[3], int mpeg2_sh)
1518{
1519 static const float g_pan[7*2] = { 0,1,0.21132487f,0.78867513f,0.36602540f,0.63397460f,0.5f,0.5f,0.63397460f,0.36602540f,0.78867513f,0.21132487f,1,0 };
1520 unsigned i, max_pos = DRMP3_HDR_TEST_MPEG1(hdr) ? 7 : 64;
1521
1522 for (i = 0; sfb[i]; i++)
1523 {
1524 unsigned ipos = ist_pos[i];
1525 if ((int)i > max_band[i % 3] && ipos < max_pos)
1526 {
1527 float kl, kr, s = DRMP3_HDR_TEST_MS_STEREO(hdr) ? 1.41421356f : 1;
1528 if (DRMP3_HDR_TEST_MPEG1(hdr))
1529 {
1530 kl = g_pan[2*ipos];
1531 kr = g_pan[2*ipos + 1];
1532 } else
1533 {
1534 kl = 1;
1535 kr = drmp3_L3_ldexp_q2(1, (ipos + 1) >> 1 << mpeg2_sh);
1536 if (ipos & 1)
1537 {
1538 kl = kr;
1539 kr = 1;
1540 }
1541 }
1542 drmp3_L3_intensity_stereo_band(left, sfb[i], kl*s, kr*s);
1543 } else if (DRMP3_HDR_TEST_MS_STEREO(hdr))
1544 {
1545 drmp3_L3_midside_stereo(left, sfb[i]);
1546 }
1547 left += sfb[i];
1548 }
1549}
1550
1551static void drmp3_L3_intensity_stereo(float *left, drmp3_uint8 *ist_pos, const drmp3_L3_gr_info *gr, const drmp3_uint8 *hdr)
1552{
1553 int max_band[3], n_sfb = gr->n_long_sfb + gr->n_short_sfb;
1554 int i, max_blocks = gr->n_short_sfb ? 3 : 1;
1555
1556 drmp3_L3_stereo_top_band(left + 576, gr->sfbtab, n_sfb, max_band);
1557 if (gr->n_long_sfb)
1558 {
1559 max_band[0] = max_band[1] = max_band[2] = DRMP3_MAX(DRMP3_MAX(max_band[0], max_band[1]), max_band[2]);
1560 }
1561 for (i = 0; i < max_blocks; i++)
1562 {
1563 int default_pos = DRMP3_HDR_TEST_MPEG1(hdr) ? 3 : 0;
1564 int itop = n_sfb - max_blocks + i;
1565 int prev = itop - max_blocks;
1566 ist_pos[itop] = (drmp3_uint8)(max_band[i] >= prev ? default_pos : ist_pos[prev]);
1567 }
1568 drmp3_L3_stereo_process(left, ist_pos, gr->sfbtab, hdr, max_band, gr[1].scalefac_compress & 1);
1569}
1570
1571static void drmp3_L3_reorder(float *grbuf, float *scratch, const drmp3_uint8 *sfb)
1572{
1573 int i, len;
1574 float *src = grbuf, *dst = scratch;
1575
1576 for (;0 != (len = *sfb); sfb += 3, src += 2*len)
1577 {
1578 for (i = 0; i < len; i++, src++)
1579 {
1580 *dst++ = src[0*len];
1581 *dst++ = src[1*len];
1582 *dst++ = src[2*len];
1583 }
1584 }
1585 DRMP3_COPY_MEMORY(grbuf, scratch, (dst - scratch)*sizeof(float));
1586}
1587
1588static void drmp3_L3_antialias(float *grbuf, int nbands)
1589{
1590 static const float g_aa[2][8] = {
1591 {0.85749293f,0.88174200f,0.94962865f,0.98331459f,0.99551782f,0.99916056f,0.99989920f,0.99999316f},
1592 {0.51449576f,0.47173197f,0.31337745f,0.18191320f,0.09457419f,0.04096558f,0.01419856f,0.00369997f}
1593 };
1594
1595 for (; nbands > 0; nbands--, grbuf += 18)
1596 {
1597 int i = 0;
1598#if DRMP3_HAVE_SIMD
1599 if (drmp3_have_simd()) for (; i < 8; i += 4)
1600 {
1601 drmp3_f4 vu = DRMP3_VLD(grbuf + 18 + i);
1602 drmp3_f4 vd = DRMP3_VLD(grbuf + 14 - i);
1603 drmp3_f4 vc0 = DRMP3_VLD(g_aa[0] + i);
1604 drmp3_f4 vc1 = DRMP3_VLD(g_aa[1] + i);
1605 vd = DRMP3_VREV(vd);
1606 DRMP3_VSTORE(grbuf + 18 + i, DRMP3_VSUB(DRMP3_VMUL(vu, vc0), DRMP3_VMUL(vd, vc1)));
1607 vd = DRMP3_VADD(DRMP3_VMUL(vu, vc1), DRMP3_VMUL(vd, vc0));
1608 DRMP3_VSTORE(grbuf + 14 - i, DRMP3_VREV(vd));
1609 }
1610#endif
1611#ifndef DR_MP3_ONLY_SIMD
1612 for(; i < 8; i++)
1613 {
1614 float u = grbuf[18 + i];
1615 float d = grbuf[17 - i];
1616 grbuf[18 + i] = u*g_aa[0][i] - d*g_aa[1][i];
1617 grbuf[17 - i] = u*g_aa[1][i] + d*g_aa[0][i];
1618 }
1619#endif
1620 }
1621}
1622
1623static void drmp3_L3_dct3_9(float *y)
1624{
1625 float s0, s1, s2, s3, s4, s5, s6, s7, s8, t0, t2, t4;
1626
1627 s0 = y[0]; s2 = y[2]; s4 = y[4]; s6 = y[6]; s8 = y[8];
1628 t0 = s0 + s6*0.5f;
1629 s0 -= s6;
1630 t4 = (s4 + s2)*0.93969262f;
1631 t2 = (s8 + s2)*0.76604444f;
1632 s6 = (s4 - s8)*0.17364818f;
1633 s4 += s8 - s2;
1634
1635 s2 = s0 - s4*0.5f;
1636 y[4] = s4 + s0;
1637 s8 = t0 - t2 + s6;
1638 s0 = t0 - t4 + t2;
1639 s4 = t0 + t4 - s6;
1640
1641 s1 = y[1]; s3 = y[3]; s5 = y[5]; s7 = y[7];
1642
1643 s3 *= 0.86602540f;
1644 t0 = (s5 + s1)*0.98480775f;
1645 t4 = (s5 - s7)*0.34202014f;
1646 t2 = (s1 + s7)*0.64278761f;
1647 s1 = (s1 - s5 - s7)*0.86602540f;
1648
1649 s5 = t0 - s3 - t2;
1650 s7 = t4 - s3 - t0;
1651 s3 = t4 + s3 - t2;
1652
1653 y[0] = s4 - s7;
1654 y[1] = s2 + s1;
1655 y[2] = s0 - s3;
1656 y[3] = s8 + s5;
1657 y[5] = s8 - s5;
1658 y[6] = s0 + s3;
1659 y[7] = s2 - s1;
1660 y[8] = s4 + s7;
1661}
1662
1663static void drmp3_L3_imdct36(float *grbuf, float *overlap, const float *window, int nbands)
1664{
1665 int i, j;
1666 static const float g_twid9[18] = {
1667 0.73727734f,0.79335334f,0.84339145f,0.88701083f,0.92387953f,0.95371695f,0.97629601f,0.99144486f,0.99904822f,0.67559021f,0.60876143f,0.53729961f,0.46174861f,0.38268343f,0.30070580f,0.21643961f,0.13052619f,0.04361938f
1668 };
1669
1670 for (j = 0; j < nbands; j++, grbuf += 18, overlap += 9)
1671 {
1672 float co[9], si[9];
1673 co[0] = -grbuf[0];
1674 si[0] = grbuf[17];
1675 for (i = 0; i < 4; i++)
1676 {
1677 si[8 - 2*i] = grbuf[4*i + 1] - grbuf[4*i + 2];
1678 co[1 + 2*i] = grbuf[4*i + 1] + grbuf[4*i + 2];
1679 si[7 - 2*i] = grbuf[4*i + 4] - grbuf[4*i + 3];
1680 co[2 + 2*i] = -(grbuf[4*i + 3] + grbuf[4*i + 4]);
1681 }
1682 drmp3_L3_dct3_9(co);
1683 drmp3_L3_dct3_9(si);
1684
1685 si[1] = -si[1];
1686 si[3] = -si[3];
1687 si[5] = -si[5];
1688 si[7] = -si[7];
1689
1690 i = 0;
1691
1692#if DRMP3_HAVE_SIMD
1693 if (drmp3_have_simd()) for (; i < 8; i += 4)
1694 {
1695 drmp3_f4 vovl = DRMP3_VLD(overlap + i);
1696 drmp3_f4 vc = DRMP3_VLD(co + i);
1697 drmp3_f4 vs = DRMP3_VLD(si + i);
1698 drmp3_f4 vr0 = DRMP3_VLD(g_twid9 + i);
1699 drmp3_f4 vr1 = DRMP3_VLD(g_twid9 + 9 + i);
1700 drmp3_f4 vw0 = DRMP3_VLD(window + i);
1701 drmp3_f4 vw1 = DRMP3_VLD(window + 9 + i);
1702 drmp3_f4 vsum = DRMP3_VADD(DRMP3_VMUL(vc, vr1), DRMP3_VMUL(vs, vr0));
1703 DRMP3_VSTORE(overlap + i, DRMP3_VSUB(DRMP3_VMUL(vc, vr0), DRMP3_VMUL(vs, vr1)));
1704 DRMP3_VSTORE(grbuf + i, DRMP3_VSUB(DRMP3_VMUL(vovl, vw0), DRMP3_VMUL(vsum, vw1)));
1705 vsum = DRMP3_VADD(DRMP3_VMUL(vovl, vw1), DRMP3_VMUL(vsum, vw0));
1706 DRMP3_VSTORE(grbuf + 14 - i, DRMP3_VREV(vsum));
1707 }
1708#endif
1709 for (; i < 9; i++)
1710 {
1711 float ovl = overlap[i];
1712 float sum = co[i]*g_twid9[9 + i] + si[i]*g_twid9[0 + i];
1713 overlap[i] = co[i]*g_twid9[0 + i] - si[i]*g_twid9[9 + i];
1714 grbuf[i] = ovl*window[0 + i] - sum*window[9 + i];
1715 grbuf[17 - i] = ovl*window[9 + i] + sum*window[0 + i];
1716 }
1717 }
1718}
1719
1720static void drmp3_L3_idct3(float x0, float x1, float x2, float *dst)
1721{
1722 float m1 = x1*0.86602540f;
1723 float a1 = x0 - x2*0.5f;
1724 dst[1] = x0 + x2;
1725 dst[0] = a1 + m1;
1726 dst[2] = a1 - m1;
1727}
1728
1729static void drmp3_L3_imdct12(float *x, float *dst, float *overlap)
1730{
1731 static const float g_twid3[6] = { 0.79335334f,0.92387953f,0.99144486f, 0.60876143f,0.38268343f,0.13052619f };
1732 float co[3], si[3];
1733 int i;
1734
1735 drmp3_L3_idct3(-x[0], x[6] + x[3], x[12] + x[9], co);
1736 drmp3_L3_idct3(x[15], x[12] - x[9], x[6] - x[3], si);
1737 si[1] = -si[1];
1738
1739 for (i = 0; i < 3; i++)
1740 {
1741 float ovl = overlap[i];
1742 float sum = co[i]*g_twid3[3 + i] + si[i]*g_twid3[0 + i];
1743 overlap[i] = co[i]*g_twid3[0 + i] - si[i]*g_twid3[3 + i];
1744 dst[i] = ovl*g_twid3[2 - i] - sum*g_twid3[5 - i];
1745 dst[5 - i] = ovl*g_twid3[5 - i] + sum*g_twid3[2 - i];
1746 }
1747}
1748
1749static void drmp3_L3_imdct_short(float *grbuf, float *overlap, int nbands)
1750{
1751 for (;nbands > 0; nbands--, overlap += 9, grbuf += 18)
1752 {
1753 float tmp[18];
1754 DRMP3_COPY_MEMORY(tmp, grbuf, sizeof(tmp));
1755 DRMP3_COPY_MEMORY(grbuf, overlap, 6*sizeof(float));
1756 drmp3_L3_imdct12(tmp, grbuf + 6, overlap + 6);
1757 drmp3_L3_imdct12(tmp + 1, grbuf + 12, overlap + 6);
1758 drmp3_L3_imdct12(tmp + 2, overlap, overlap + 6);
1759 }
1760}
1761
1762static void drmp3_L3_change_sign(float *grbuf)
1763{
1764 int b, i;
1765 for (b = 0, grbuf += 18; b < 32; b += 2, grbuf += 36)
1766 for (i = 1; i < 18; i += 2)
1767 grbuf[i] = -grbuf[i];
1768}
1769
1770static void drmp3_L3_imdct_gr(float *grbuf, float *overlap, unsigned block_type, unsigned n_long_bands)
1771{
1772 static const float g_mdct_window[2][18] = {
1773 { 0.99904822f,0.99144486f,0.97629601f,0.95371695f,0.92387953f,0.88701083f,0.84339145f,0.79335334f,0.73727734f,0.04361938f,0.13052619f,0.21643961f,0.30070580f,0.38268343f,0.46174861f,0.53729961f,0.60876143f,0.67559021f },
1774 { 1,1,1,1,1,1,0.99144486f,0.92387953f,0.79335334f,0,0,0,0,0,0,0.13052619f,0.38268343f,0.60876143f }
1775 };
1776 if (n_long_bands)
1777 {
1778 drmp3_L3_imdct36(grbuf, overlap, g_mdct_window[0], n_long_bands);
1779 grbuf += 18*n_long_bands;
1780 overlap += 9*n_long_bands;
1781 }
1782 if (block_type == DRMP3_SHORT_BLOCK_TYPE)
1783 drmp3_L3_imdct_short(grbuf, overlap, 32 - n_long_bands);
1784 else
1785 drmp3_L3_imdct36(grbuf, overlap, g_mdct_window[block_type == DRMP3_STOP_BLOCK_TYPE], 32 - n_long_bands);
1786}
1787
1788static void drmp3_L3_save_reservoir(drmp3dec *h, drmp3dec_scratch *s)
1789{
1790 int pos = (s->bs.pos + 7)/8u;
1791 int remains = s->bs.limit/8u - pos;
1792 if (remains > DRMP3_MAX_BITRESERVOIR_BYTES)
1793 {
1794 pos += remains - DRMP3_MAX_BITRESERVOIR_BYTES;
1795 remains = DRMP3_MAX_BITRESERVOIR_BYTES;
1796 }
1797 if (remains > 0)
1798 {
1799 DRMP3_MOVE_MEMORY(h->reserv_buf, s->maindata + pos, remains);
1800 }
1801 h->reserv = remains;
1802}
1803
1804static int drmp3_L3_restore_reservoir(drmp3dec *h, drmp3_bs *bs, drmp3dec_scratch *s, int main_data_begin)
1805{
1806 int frame_bytes = (bs->limit - bs->pos)/8;
1807 int bytes_have = DRMP3_MIN(h->reserv, main_data_begin);
1808 DRMP3_COPY_MEMORY(s->maindata, h->reserv_buf + DRMP3_MAX(0, h->reserv - main_data_begin), DRMP3_MIN(h->reserv, main_data_begin));
1809 DRMP3_COPY_MEMORY(s->maindata + bytes_have, bs->buf + bs->pos/8, frame_bytes);
1810 drmp3_bs_init(&s->bs, s->maindata, bytes_have + frame_bytes);
1811 return h->reserv >= main_data_begin;
1812}
1813
1814static void drmp3_L3_decode(drmp3dec *h, drmp3dec_scratch *s, drmp3_L3_gr_info *gr_info, int nch)
1815{
1816 int ch;
1817
1818 for (ch = 0; ch < nch; ch++)
1819 {
1820 int layer3gr_limit = s->bs.pos + gr_info[ch].part_23_length;
1821 drmp3_L3_decode_scalefactors(h->header, s->ist_pos[ch], &s->bs, gr_info + ch, s->scf, ch);
1822 drmp3_L3_huffman(s->grbuf[ch], &s->bs, gr_info + ch, s->scf, layer3gr_limit);
1823 }
1824
1825 if (DRMP3_HDR_TEST_I_STEREO(h->header))
1826 {
1827 drmp3_L3_intensity_stereo(s->grbuf[0], s->ist_pos[1], gr_info, h->header);
1828 } else if (DRMP3_HDR_IS_MS_STEREO(h->header))
1829 {
1830 drmp3_L3_midside_stereo(s->grbuf[0], 576);
1831 }
1832
1833 for (ch = 0; ch < nch; ch++, gr_info++)
1834 {
1835 int aa_bands = 31;
1836 int n_long_bands = (gr_info->mixed_block_flag ? 2 : 0) << (int)(DRMP3_HDR_GET_MY_SAMPLE_RATE(h->header) == 2);
1837
1838 if (gr_info->n_short_sfb)
1839 {
1840 aa_bands = n_long_bands - 1;
1841 drmp3_L3_reorder(s->grbuf[ch] + n_long_bands*18, s->syn[0], gr_info->sfbtab + gr_info->n_long_sfb);
1842 }
1843
1844 drmp3_L3_antialias(s->grbuf[ch], aa_bands);
1845 drmp3_L3_imdct_gr(s->grbuf[ch], h->mdct_overlap[ch], gr_info->block_type, n_long_bands);
1846 drmp3_L3_change_sign(s->grbuf[ch]);
1847 }
1848}
1849
1850static void drmp3d_DCT_II(float *grbuf, int n)
1851{
1852 static const float g_sec[24] = {
1853 10.19000816f,0.50060302f,0.50241929f,3.40760851f,0.50547093f,0.52249861f,2.05778098f,0.51544732f,0.56694406f,1.48416460f,0.53104258f,0.64682180f,1.16943991f,0.55310392f,0.78815460f,0.97256821f,0.58293498f,1.06067765f,0.83934963f,0.62250412f,1.72244716f,0.74453628f,0.67480832f,5.10114861f
1854 };
1855 int i, k = 0;
1856#if DRMP3_HAVE_SIMD
1857 if (drmp3_have_simd()) for (; k < n; k += 4)
1858 {
1859 drmp3_f4 t[4][8], *x;
1860 float *y = grbuf + k;
1861
1862 for (x = t[0], i = 0; i < 8; i++, x++)
1863 {
1864 drmp3_f4 x0 = DRMP3_VLD(&y[i*18]);
1865 drmp3_f4 x1 = DRMP3_VLD(&y[(15 - i)*18]);
1866 drmp3_f4 x2 = DRMP3_VLD(&y[(16 + i)*18]);
1867 drmp3_f4 x3 = DRMP3_VLD(&y[(31 - i)*18]);
1868 drmp3_f4 t0 = DRMP3_VADD(x0, x3);
1869 drmp3_f4 t1 = DRMP3_VADD(x1, x2);
1870 drmp3_f4 t2 = DRMP3_VMUL_S(DRMP3_VSUB(x1, x2), g_sec[3*i + 0]);
1871 drmp3_f4 t3 = DRMP3_VMUL_S(DRMP3_VSUB(x0, x3), g_sec[3*i + 1]);
1872 x[0] = DRMP3_VADD(t0, t1);
1873 x[8] = DRMP3_VMUL_S(DRMP3_VSUB(t0, t1), g_sec[3*i + 2]);
1874 x[16] = DRMP3_VADD(t3, t2);
1875 x[24] = DRMP3_VMUL_S(DRMP3_VSUB(t3, t2), g_sec[3*i + 2]);
1876 }
1877 for (x = t[0], i = 0; i < 4; i++, x += 8)
1878 {
1879 drmp3_f4 x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3], x4 = x[4], x5 = x[5], x6 = x[6], x7 = x[7], xt;
1880 xt = DRMP3_VSUB(x0, x7); x0 = DRMP3_VADD(x0, x7);
1881 x7 = DRMP3_VSUB(x1, x6); x1 = DRMP3_VADD(x1, x6);
1882 x6 = DRMP3_VSUB(x2, x5); x2 = DRMP3_VADD(x2, x5);
1883 x5 = DRMP3_VSUB(x3, x4); x3 = DRMP3_VADD(x3, x4);
1884 x4 = DRMP3_VSUB(x0, x3); x0 = DRMP3_VADD(x0, x3);
1885 x3 = DRMP3_VSUB(x1, x2); x1 = DRMP3_VADD(x1, x2);
1886 x[0] = DRMP3_VADD(x0, x1);
1887 x[4] = DRMP3_VMUL_S(DRMP3_VSUB(x0, x1), 0.70710677f);
1888 x5 = DRMP3_VADD(x5, x6);
1889 x6 = DRMP3_VMUL_S(DRMP3_VADD(x6, x7), 0.70710677f);
1890 x7 = DRMP3_VADD(x7, xt);
1891 x3 = DRMP3_VMUL_S(DRMP3_VADD(x3, x4), 0.70710677f);
1892 x5 = DRMP3_VSUB(x5, DRMP3_VMUL_S(x7, 0.198912367f)); /* rotate by PI/8 */
1893 x7 = DRMP3_VADD(x7, DRMP3_VMUL_S(x5, 0.382683432f));
1894 x5 = DRMP3_VSUB(x5, DRMP3_VMUL_S(x7, 0.198912367f));
1895 x0 = DRMP3_VSUB(xt, x6); xt = DRMP3_VADD(xt, x6);
1896 x[1] = DRMP3_VMUL_S(DRMP3_VADD(xt, x7), 0.50979561f);
1897 x[2] = DRMP3_VMUL_S(DRMP3_VADD(x4, x3), 0.54119611f);
1898 x[3] = DRMP3_VMUL_S(DRMP3_VSUB(x0, x5), 0.60134488f);
1899 x[5] = DRMP3_VMUL_S(DRMP3_VADD(x0, x5), 0.89997619f);
1900 x[6] = DRMP3_VMUL_S(DRMP3_VSUB(x4, x3), 1.30656302f);
1901 x[7] = DRMP3_VMUL_S(DRMP3_VSUB(xt, x7), 2.56291556f);
1902 }
1903
1904 if (k > n - 3)
1905 {
1906#if DRMP3_HAVE_SSE
1907#define DRMP3_VSAVE2(i, v) _mm_storel_pi((__m64 *)(void*)&y[i*18], v)
1908#else
1909#define DRMP3_VSAVE2(i, v) vst1_f32((float32_t *)&y[(i)*18], vget_low_f32(v))
1910#endif
1911 for (i = 0; i < 7; i++, y += 4*18)
1912 {
1913 drmp3_f4 s = DRMP3_VADD(t[3][i], t[3][i + 1]);
1914 DRMP3_VSAVE2(0, t[0][i]);
1915 DRMP3_VSAVE2(1, DRMP3_VADD(t[2][i], s));
1916 DRMP3_VSAVE2(2, DRMP3_VADD(t[1][i], t[1][i + 1]));
1917 DRMP3_VSAVE2(3, DRMP3_VADD(t[2][1 + i], s));
1918 }
1919 DRMP3_VSAVE2(0, t[0][7]);
1920 DRMP3_VSAVE2(1, DRMP3_VADD(t[2][7], t[3][7]));
1921 DRMP3_VSAVE2(2, t[1][7]);
1922 DRMP3_VSAVE2(3, t[3][7]);
1923 } else
1924 {
1925#define DRMP3_VSAVE4(i, v) DRMP3_VSTORE(&y[(i)*18], v)
1926 for (i = 0; i < 7; i++, y += 4*18)
1927 {
1928 drmp3_f4 s = DRMP3_VADD(t[3][i], t[3][i + 1]);
1929 DRMP3_VSAVE4(0, t[0][i]);
1930 DRMP3_VSAVE4(1, DRMP3_VADD(t[2][i], s));
1931 DRMP3_VSAVE4(2, DRMP3_VADD(t[1][i], t[1][i + 1]));
1932 DRMP3_VSAVE4(3, DRMP3_VADD(t[2][1 + i], s));
1933 }
1934 DRMP3_VSAVE4(0, t[0][7]);
1935 DRMP3_VSAVE4(1, DRMP3_VADD(t[2][7], t[3][7]));
1936 DRMP3_VSAVE4(2, t[1][7]);
1937 DRMP3_VSAVE4(3, t[3][7]);
1938 }
1939 } else
1940#endif
1941#ifdef DR_MP3_ONLY_SIMD
1942 {} /* for HAVE_SIMD=1, MINIMP3_ONLY_SIMD=1 case we do not need non-intrinsic "else" branch */
1943#else
1944 for (; k < n; k++)
1945 {
1946 float t[4][8], *x, *y = grbuf + k;
1947
1948 for (x = t[0], i = 0; i < 8; i++, x++)
1949 {
1950 float x0 = y[i*18];
1951 float x1 = y[(15 - i)*18];
1952 float x2 = y[(16 + i)*18];
1953 float x3 = y[(31 - i)*18];
1954 float t0 = x0 + x3;
1955 float t1 = x1 + x2;
1956 float t2 = (x1 - x2)*g_sec[3*i + 0];
1957 float t3 = (x0 - x3)*g_sec[3*i + 1];
1958 x[0] = t0 + t1;
1959 x[8] = (t0 - t1)*g_sec[3*i + 2];
1960 x[16] = t3 + t2;
1961 x[24] = (t3 - t2)*g_sec[3*i + 2];
1962 }
1963 for (x = t[0], i = 0; i < 4; i++, x += 8)
1964 {
1965 float x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3], x4 = x[4], x5 = x[5], x6 = x[6], x7 = x[7], xt;
1966 xt = x0 - x7; x0 += x7;
1967 x7 = x1 - x6; x1 += x6;
1968 x6 = x2 - x5; x2 += x5;
1969 x5 = x3 - x4; x3 += x4;
1970 x4 = x0 - x3; x0 += x3;
1971 x3 = x1 - x2; x1 += x2;
1972 x[0] = x0 + x1;
1973 x[4] = (x0 - x1)*0.70710677f;
1974 x5 = x5 + x6;
1975 x6 = (x6 + x7)*0.70710677f;
1976 x7 = x7 + xt;
1977 x3 = (x3 + x4)*0.70710677f;
1978 x5 -= x7*0.198912367f; /* rotate by PI/8 */
1979 x7 += x5*0.382683432f;
1980 x5 -= x7*0.198912367f;
1981 x0 = xt - x6; xt += x6;
1982 x[1] = (xt + x7)*0.50979561f;
1983 x[2] = (x4 + x3)*0.54119611f;
1984 x[3] = (x0 - x5)*0.60134488f;
1985 x[5] = (x0 + x5)*0.89997619f;
1986 x[6] = (x4 - x3)*1.30656302f;
1987 x[7] = (xt - x7)*2.56291556f;
1988
1989 }
1990 for (i = 0; i < 7; i++, y += 4*18)
1991 {
1992 y[0*18] = t[0][i];
1993 y[1*18] = t[2][i] + t[3][i] + t[3][i + 1];
1994 y[2*18] = t[1][i] + t[1][i + 1];
1995 y[3*18] = t[2][i + 1] + t[3][i] + t[3][i + 1];
1996 }
1997 y[0*18] = t[0][7];
1998 y[1*18] = t[2][7] + t[3][7];
1999 y[2*18] = t[1][7];
2000 y[3*18] = t[3][7];
2001 }
2002#endif
2003}
2004
2005#ifndef DR_MP3_FLOAT_OUTPUT
2006typedef drmp3_int16 drmp3d_sample_t;
2007
2008static drmp3_int16 drmp3d_scale_pcm(float sample)
2009{
2010 drmp3_int16 s;
2011#if DRMP3_HAVE_ARMV6
2012 drmp3_int32 s32 = (drmp3_int32)(sample + .5f);
2013 s32 -= (s32 < 0);
2014 s = (drmp3_int16)drmp3_clip_int16_arm(s32);
2015#else
2016 if (sample >= 32766.5f) return (drmp3_int16) 32767;
2017 if (sample <= -32767.5f) return (drmp3_int16)-32768;
2018 s = (drmp3_int16)(sample + .5f);
2019 s -= (s < 0); /* away from zero, to be compliant */
2020#endif
2021 return s;
2022}
2023#else
2024typedef float drmp3d_sample_t;
2025
2026static float drmp3d_scale_pcm(float sample)
2027{
2028 return sample*(1.f/32768.f);
2029}
2030#endif
2031
2032static void drmp3d_synth_pair(drmp3d_sample_t *pcm, int nch, const float *z)
2033{
2034 float a;
2035 a = (z[14*64] - z[ 0]) * 29;
2036 a += (z[ 1*64] + z[13*64]) * 213;
2037 a += (z[12*64] - z[ 2*64]) * 459;
2038 a += (z[ 3*64] + z[11*64]) * 2037;
2039 a += (z[10*64] - z[ 4*64]) * 5153;
2040 a += (z[ 5*64] + z[ 9*64]) * 6574;
2041 a += (z[ 8*64] - z[ 6*64]) * 37489;
2042 a += z[ 7*64] * 75038;
2043 pcm[0] = drmp3d_scale_pcm(a);
2044
2045 z += 2;
2046 a = z[14*64] * 104;
2047 a += z[12*64] * 1567;
2048 a += z[10*64] * 9727;
2049 a += z[ 8*64] * 64019;
2050 a += z[ 6*64] * -9975;
2051 a += z[ 4*64] * -45;
2052 a += z[ 2*64] * 146;
2053 a += z[ 0*64] * -5;
2054 pcm[16*nch] = drmp3d_scale_pcm(a);
2055}
2056
2057static void drmp3d_synth(float *xl, drmp3d_sample_t *dstl, int nch, float *lins)
2058{
2059 int i;
2060 float *xr = xl + 576*(nch - 1);
2061 drmp3d_sample_t *dstr = dstl + (nch - 1);
2062
2063 static const float g_win[] = {
2064 -1,26,-31,208,218,401,-519,2063,2000,4788,-5517,7134,5959,35640,-39336,74992,
2065 -1,24,-35,202,222,347,-581,2080,1952,4425,-5879,7640,5288,33791,-41176,74856,
2066 -1,21,-38,196,225,294,-645,2087,1893,4063,-6237,8092,4561,31947,-43006,74630,
2067 -1,19,-41,190,227,244,-711,2085,1822,3705,-6589,8492,3776,30112,-44821,74313,
2068 -1,17,-45,183,228,197,-779,2075,1739,3351,-6935,8840,2935,28289,-46617,73908,
2069 -1,16,-49,176,228,153,-848,2057,1644,3004,-7271,9139,2037,26482,-48390,73415,
2070 -2,14,-53,169,227,111,-919,2032,1535,2663,-7597,9389,1082,24694,-50137,72835,
2071 -2,13,-58,161,224,72,-991,2001,1414,2330,-7910,9592,70,22929,-51853,72169,
2072 -2,11,-63,154,221,36,-1064,1962,1280,2006,-8209,9750,-998,21189,-53534,71420,
2073 -2,10,-68,147,215,2,-1137,1919,1131,1692,-8491,9863,-2122,19478,-55178,70590,
2074 -3,9,-73,139,208,-29,-1210,1870,970,1388,-8755,9935,-3300,17799,-56778,69679,
2075 -3,8,-79,132,200,-57,-1283,1817,794,1095,-8998,9966,-4533,16155,-58333,68692,
2076 -4,7,-85,125,189,-83,-1356,1759,605,814,-9219,9959,-5818,14548,-59838,67629,
2077 -4,7,-91,117,177,-106,-1428,1698,402,545,-9416,9916,-7154,12980,-61289,66494,
2078 -5,6,-97,111,163,-127,-1498,1634,185,288,-9585,9838,-8540,11455,-62684,65290
2079 };
2080 float *zlin = lins + 15*64;
2081 const float *w = g_win;
2082
2083 zlin[4*15] = xl[18*16];
2084 zlin[4*15 + 1] = xr[18*16];
2085 zlin[4*15 + 2] = xl[0];
2086 zlin[4*15 + 3] = xr[0];
2087
2088 zlin[4*31] = xl[1 + 18*16];
2089 zlin[4*31 + 1] = xr[1 + 18*16];
2090 zlin[4*31 + 2] = xl[1];
2091 zlin[4*31 + 3] = xr[1];
2092
2093 drmp3d_synth_pair(dstr, nch, lins + 4*15 + 1);
2094 drmp3d_synth_pair(dstr + 32*nch, nch, lins + 4*15 + 64 + 1);
2095 drmp3d_synth_pair(dstl, nch, lins + 4*15);
2096 drmp3d_synth_pair(dstl + 32*nch, nch, lins + 4*15 + 64);
2097
2098#if DRMP3_HAVE_SIMD
2099 if (drmp3_have_simd()) for (i = 14; i >= 0; i--)
2100 {
2101#define DRMP3_VLOAD(k) drmp3_f4 w0 = DRMP3_VSET(*w++); drmp3_f4 w1 = DRMP3_VSET(*w++); drmp3_f4 vz = DRMP3_VLD(&zlin[4*i - 64*k]); drmp3_f4 vy = DRMP3_VLD(&zlin[4*i - 64*(15 - k)]);
2102#define DRMP3_V0(k) { DRMP3_VLOAD(k) b = DRMP3_VADD(DRMP3_VMUL(vz, w1), DRMP3_VMUL(vy, w0)) ; a = DRMP3_VSUB(DRMP3_VMUL(vz, w0), DRMP3_VMUL(vy, w1)); }
2103#define DRMP3_V1(k) { DRMP3_VLOAD(k) b = DRMP3_VADD(b, DRMP3_VADD(DRMP3_VMUL(vz, w1), DRMP3_VMUL(vy, w0))); a = DRMP3_VADD(a, DRMP3_VSUB(DRMP3_VMUL(vz, w0), DRMP3_VMUL(vy, w1))); }
2104#define DRMP3_V2(k) { DRMP3_VLOAD(k) b = DRMP3_VADD(b, DRMP3_VADD(DRMP3_VMUL(vz, w1), DRMP3_VMUL(vy, w0))); a = DRMP3_VADD(a, DRMP3_VSUB(DRMP3_VMUL(vy, w1), DRMP3_VMUL(vz, w0))); }
2105 drmp3_f4 a, b;
2106 zlin[4*i] = xl[18*(31 - i)];
2107 zlin[4*i + 1] = xr[18*(31 - i)];
2108 zlin[4*i + 2] = xl[1 + 18*(31 - i)];
2109 zlin[4*i + 3] = xr[1 + 18*(31 - i)];
2110 zlin[4*i + 64] = xl[1 + 18*(1 + i)];
2111 zlin[4*i + 64 + 1] = xr[1 + 18*(1 + i)];
2112 zlin[4*i - 64 + 2] = xl[18*(1 + i)];
2113 zlin[4*i - 64 + 3] = xr[18*(1 + i)];
2114
2115 DRMP3_V0(0) DRMP3_V2(1) DRMP3_V1(2) DRMP3_V2(3) DRMP3_V1(4) DRMP3_V2(5) DRMP3_V1(6) DRMP3_V2(7)
2116
2117 {
2118#ifndef DR_MP3_FLOAT_OUTPUT
2119#if DRMP3_HAVE_SSE
2120 static const drmp3_f4 g_max = { 32767.0f, 32767.0f, 32767.0f, 32767.0f };
2121 static const drmp3_f4 g_min = { -32768.0f, -32768.0f, -32768.0f, -32768.0f };
2122 __m128i pcm8 = _mm_packs_epi32(_mm_cvtps_epi32(_mm_max_ps(_mm_min_ps(a, g_max), g_min)),
2123 _mm_cvtps_epi32(_mm_max_ps(_mm_min_ps(b, g_max), g_min)));
2124 dstr[(15 - i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 1);
2125 dstr[(17 + i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 5);
2126 dstl[(15 - i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 0);
2127 dstl[(17 + i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 4);
2128 dstr[(47 - i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 3);
2129 dstr[(49 + i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 7);
2130 dstl[(47 - i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 2);
2131 dstl[(49 + i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 6);
2132#else
2133 int16x4_t pcma, pcmb;
2134 a = DRMP3_VADD(a, DRMP3_VSET(0.5f));
2135 b = DRMP3_VADD(b, DRMP3_VSET(0.5f));
2136 pcma = vqmovn_s32(vqaddq_s32(vcvtq_s32_f32(a), vreinterpretq_s32_u32(vcltq_f32(a, DRMP3_VSET(0)))));
2137 pcmb = vqmovn_s32(vqaddq_s32(vcvtq_s32_f32(b), vreinterpretq_s32_u32(vcltq_f32(b, DRMP3_VSET(0)))));
2138 vst1_lane_s16(dstr + (15 - i)*nch, pcma, 1);
2139 vst1_lane_s16(dstr + (17 + i)*nch, pcmb, 1);
2140 vst1_lane_s16(dstl + (15 - i)*nch, pcma, 0);
2141 vst1_lane_s16(dstl + (17 + i)*nch, pcmb, 0);
2142 vst1_lane_s16(dstr + (47 - i)*nch, pcma, 3);
2143 vst1_lane_s16(dstr + (49 + i)*nch, pcmb, 3);
2144 vst1_lane_s16(dstl + (47 - i)*nch, pcma, 2);
2145 vst1_lane_s16(dstl + (49 + i)*nch, pcmb, 2);
2146#endif
2147#else
2148 #if DRMP3_HAVE_SSE
2149 static const drmp3_f4 g_scale = { 1.0f/32768.0f, 1.0f/32768.0f, 1.0f/32768.0f, 1.0f/32768.0f };
2150 #else
2151 const drmp3_f4 g_scale = vdupq_n_f32(1.0f/32768.0f);
2152 #endif
2153 a = DRMP3_VMUL(a, g_scale);
2154 b = DRMP3_VMUL(b, g_scale);
2155#if DRMP3_HAVE_SSE
2156 _mm_store_ss(dstr + (15 - i)*nch, _mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 1, 1, 1)));
2157 _mm_store_ss(dstr + (17 + i)*nch, _mm_shuffle_ps(b, b, _MM_SHUFFLE(1, 1, 1, 1)));
2158 _mm_store_ss(dstl + (15 - i)*nch, _mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0)));
2159 _mm_store_ss(dstl + (17 + i)*nch, _mm_shuffle_ps(b, b, _MM_SHUFFLE(0, 0, 0, 0)));
2160 _mm_store_ss(dstr + (47 - i)*nch, _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 3, 3, 3)));
2161 _mm_store_ss(dstr + (49 + i)*nch, _mm_shuffle_ps(b, b, _MM_SHUFFLE(3, 3, 3, 3)));
2162 _mm_store_ss(dstl + (47 - i)*nch, _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2)));
2163 _mm_store_ss(dstl + (49 + i)*nch, _mm_shuffle_ps(b, b, _MM_SHUFFLE(2, 2, 2, 2)));
2164#else
2165 vst1q_lane_f32(dstr + (15 - i)*nch, a, 1);
2166 vst1q_lane_f32(dstr + (17 + i)*nch, b, 1);
2167 vst1q_lane_f32(dstl + (15 - i)*nch, a, 0);
2168 vst1q_lane_f32(dstl + (17 + i)*nch, b, 0);
2169 vst1q_lane_f32(dstr + (47 - i)*nch, a, 3);
2170 vst1q_lane_f32(dstr + (49 + i)*nch, b, 3);
2171 vst1q_lane_f32(dstl + (47 - i)*nch, a, 2);
2172 vst1q_lane_f32(dstl + (49 + i)*nch, b, 2);
2173#endif
2174#endif /* DR_MP3_FLOAT_OUTPUT */
2175 }
2176 } else
2177#endif
2178#ifdef DR_MP3_ONLY_SIMD
2179 {} /* for HAVE_SIMD=1, MINIMP3_ONLY_SIMD=1 case we do not need non-intrinsic "else" branch */
2180#else
2181 for (i = 14; i >= 0; i--)
2182 {
2183#define DRMP3_LOAD(k) float w0 = *w++; float w1 = *w++; float *vz = &zlin[4*i - k*64]; float *vy = &zlin[4*i - (15 - k)*64];
2184#define DRMP3_S0(k) { int j; DRMP3_LOAD(k); for (j = 0; j < 4; j++) b[j] = vz[j]*w1 + vy[j]*w0, a[j] = vz[j]*w0 - vy[j]*w1; }
2185#define DRMP3_S1(k) { int j; DRMP3_LOAD(k); for (j = 0; j < 4; j++) b[j] += vz[j]*w1 + vy[j]*w0, a[j] += vz[j]*w0 - vy[j]*w1; }
2186#define DRMP3_S2(k) { int j; DRMP3_LOAD(k); for (j = 0; j < 4; j++) b[j] += vz[j]*w1 + vy[j]*w0, a[j] += vy[j]*w1 - vz[j]*w0; }
2187 float a[4], b[4];
2188
2189 zlin[4*i] = xl[18*(31 - i)];
2190 zlin[4*i + 1] = xr[18*(31 - i)];
2191 zlin[4*i + 2] = xl[1 + 18*(31 - i)];
2192 zlin[4*i + 3] = xr[1 + 18*(31 - i)];
2193 zlin[4*(i + 16)] = xl[1 + 18*(1 + i)];
2194 zlin[4*(i + 16) + 1] = xr[1 + 18*(1 + i)];
2195 zlin[4*(i - 16) + 2] = xl[18*(1 + i)];
2196 zlin[4*(i - 16) + 3] = xr[18*(1 + i)];
2197
2198 DRMP3_S0(0) DRMP3_S2(1) DRMP3_S1(2) DRMP3_S2(3) DRMP3_S1(4) DRMP3_S2(5) DRMP3_S1(6) DRMP3_S2(7)
2199
2200 dstr[(15 - i)*nch] = drmp3d_scale_pcm(a[1]);
2201 dstr[(17 + i)*nch] = drmp3d_scale_pcm(b[1]);
2202 dstl[(15 - i)*nch] = drmp3d_scale_pcm(a[0]);
2203 dstl[(17 + i)*nch] = drmp3d_scale_pcm(b[0]);
2204 dstr[(47 - i)*nch] = drmp3d_scale_pcm(a[3]);
2205 dstr[(49 + i)*nch] = drmp3d_scale_pcm(b[3]);
2206 dstl[(47 - i)*nch] = drmp3d_scale_pcm(a[2]);
2207 dstl[(49 + i)*nch] = drmp3d_scale_pcm(b[2]);
2208 }
2209#endif
2210}
2211
2212static void drmp3d_synth_granule(float *qmf_state, float *grbuf, int nbands, int nch, drmp3d_sample_t *pcm, float *lins)
2213{
2214 int i;
2215 for (i = 0; i < nch; i++)
2216 {
2217 drmp3d_DCT_II(grbuf + 576*i, nbands);
2218 }
2219
2220 DRMP3_COPY_MEMORY(lins, qmf_state, sizeof(float)*15*64);
2221
2222 for (i = 0; i < nbands; i += 2)
2223 {
2224 drmp3d_synth(grbuf + i, pcm + 32*nch*i, nch, lins + i*64);
2225 }
2226#ifndef DR_MP3_NONSTANDARD_BUT_LOGICAL
2227 if (nch == 1)
2228 {
2229 for (i = 0; i < 15*64; i += 2)
2230 {
2231 qmf_state[i] = lins[nbands*64 + i];
2232 }
2233 } else
2234#endif
2235 {
2236 DRMP3_COPY_MEMORY(qmf_state, lins + nbands*64, sizeof(float)*15*64);
2237 }
2238}
2239
2240static int drmp3d_match_frame(const drmp3_uint8 *hdr, int mp3_bytes, int frame_bytes)
2241{
2242 int i, nmatch;
2243 for (i = 0, nmatch = 0; nmatch < DRMP3_MAX_FRAME_SYNC_MATCHES; nmatch++)
2244 {
2245 i += drmp3_hdr_frame_bytes(hdr + i, frame_bytes) + drmp3_hdr_padding(hdr + i);
2246 if (i + DRMP3_HDR_SIZE > mp3_bytes)
2247 return nmatch > 0;
2248 if (!drmp3_hdr_compare(hdr, hdr + i))
2249 return 0;
2250 }
2251 return 1;
2252}
2253
2254static int drmp3d_find_frame(const drmp3_uint8 *mp3, int mp3_bytes, int *free_format_bytes, int *ptr_frame_bytes)
2255{
2256 int i, k;
2257 for (i = 0; i < mp3_bytes - DRMP3_HDR_SIZE; i++, mp3++)
2258 {
2259 if (drmp3_hdr_valid(mp3))
2260 {
2261 int frame_bytes = drmp3_hdr_frame_bytes(mp3, *free_format_bytes);
2262 int frame_and_padding = frame_bytes + drmp3_hdr_padding(mp3);
2263
2264 for (k = DRMP3_HDR_SIZE; !frame_bytes && k < DRMP3_MAX_FREE_FORMAT_FRAME_SIZE && i + 2*k < mp3_bytes - DRMP3_HDR_SIZE; k++)
2265 {
2266 if (drmp3_hdr_compare(mp3, mp3 + k))
2267 {
2268 int fb = k - drmp3_hdr_padding(mp3);
2269 int nextfb = fb + drmp3_hdr_padding(mp3 + k);
2270 if (i + k + nextfb + DRMP3_HDR_SIZE > mp3_bytes || !drmp3_hdr_compare(mp3, mp3 + k + nextfb))
2271 continue;
2272 frame_and_padding = k;
2273 frame_bytes = fb;
2274 *free_format_bytes = fb;
2275 }
2276 }
2277
2278 if ((frame_bytes && i + frame_and_padding <= mp3_bytes &&
2279 drmp3d_match_frame(mp3, mp3_bytes - i, frame_bytes)) ||
2280 (!i && frame_and_padding == mp3_bytes))
2281 {
2282 *ptr_frame_bytes = frame_and_padding;
2283 return i;
2284 }
2285 *free_format_bytes = 0;
2286 }
2287 }
2288 *ptr_frame_bytes = 0;
2289 return mp3_bytes;
2290}
2291
2293{
2294 dec->header[0] = 0;
2295}
2296
2297DRMP3_API int drmp3dec_decode_frame(drmp3dec *dec, const drmp3_uint8 *mp3, int mp3_bytes, void *pcm, drmp3dec_frame_info *info)
2298{
2299 int i = 0, igr, frame_size = 0, success = 1;
2300 const drmp3_uint8 *hdr;
2301 drmp3_bs bs_frame[1];
2302 drmp3dec_scratch scratch;
2303
2304 if (mp3_bytes > 4 && dec->header[0] == 0xff && drmp3_hdr_compare(dec->header, mp3))
2305 {
2306 frame_size = drmp3_hdr_frame_bytes(mp3, dec->free_format_bytes) + drmp3_hdr_padding(mp3);
2307 if (frame_size != mp3_bytes && (frame_size + DRMP3_HDR_SIZE > mp3_bytes || !drmp3_hdr_compare(mp3, mp3 + frame_size)))
2308 {
2309 frame_size = 0;
2310 }
2311 }
2312 if (!frame_size)
2313 {
2314 DRMP3_ZERO_MEMORY(dec, sizeof(drmp3dec));
2315 i = drmp3d_find_frame(mp3, mp3_bytes, &dec->free_format_bytes, &frame_size);
2316 if (!frame_size || i + frame_size > mp3_bytes)
2317 {
2318 info->frame_bytes = i;
2319 return 0;
2320 }
2321 }
2322
2323 hdr = mp3 + i;
2324 DRMP3_COPY_MEMORY(dec->header, hdr, DRMP3_HDR_SIZE);
2325 info->frame_bytes = i + frame_size;
2326 info->channels = DRMP3_HDR_IS_MONO(hdr) ? 1 : 2;
2327 info->sample_rate = drmp3_hdr_sample_rate_hz(hdr);
2328 info->layer = 4 - DRMP3_HDR_GET_LAYER(hdr);
2329 info->bitrate_kbps = drmp3_hdr_bitrate_kbps(hdr);
2330
2331 drmp3_bs_init(bs_frame, hdr + DRMP3_HDR_SIZE, frame_size - DRMP3_HDR_SIZE);
2332 if (DRMP3_HDR_IS_CRC(hdr))
2333 {
2334 drmp3_bs_get_bits(bs_frame, 16);
2335 }
2336
2337 if (info->layer == 3)
2338 {
2339 int main_data_begin = drmp3_L3_read_side_info(bs_frame, scratch.gr_info, hdr);
2340 if (main_data_begin < 0 || bs_frame->pos > bs_frame->limit)
2341 {
2342 drmp3dec_init(dec);
2343 return 0;
2344 }
2345 success = drmp3_L3_restore_reservoir(dec, bs_frame, &scratch, main_data_begin);
2346 if (success && pcm != NULL)
2347 {
2348 for (igr = 0; igr < (DRMP3_HDR_TEST_MPEG1(hdr) ? 2 : 1); igr++, pcm = DRMP3_OFFSET_PTR(pcm, sizeof(drmp3d_sample_t)*576*info->channels))
2349 {
2350 DRMP3_ZERO_MEMORY(scratch.grbuf[0], 576*2*sizeof(float));
2351 drmp3_L3_decode(dec, &scratch, scratch.gr_info + igr*info->channels, info->channels);
2352 drmp3d_synth_granule(dec->qmf_state, scratch.grbuf[0], 18, info->channels, (drmp3d_sample_t*)pcm, scratch.syn[0]);
2353 }
2354 }
2355 drmp3_L3_save_reservoir(dec, &scratch);
2356 } else
2357 {
2358#ifdef DR_MP3_ONLY_MP3
2359 return 0;
2360#else
2361 drmp3_L12_scale_info sci[1];
2362
2363 if (pcm == NULL) {
2364 return drmp3_hdr_frame_samples(hdr);
2365 }
2366
2367 drmp3_L12_read_scale_info(hdr, bs_frame, sci);
2368
2369 DRMP3_ZERO_MEMORY(scratch.grbuf[0], 576*2*sizeof(float));
2370 for (i = 0, igr = 0; igr < 3; igr++)
2371 {
2372 if (12 == (i += drmp3_L12_dequantize_granule(scratch.grbuf[0] + i, bs_frame, sci, info->layer | 1)))
2373 {
2374 i = 0;
2375 drmp3_L12_apply_scf_384(sci, sci->scf + igr, scratch.grbuf[0]);
2376 drmp3d_synth_granule(dec->qmf_state, scratch.grbuf[0], 12, info->channels, (drmp3d_sample_t*)pcm, scratch.syn[0]);
2377 DRMP3_ZERO_MEMORY(scratch.grbuf[0], 576*2*sizeof(float));
2378 pcm = DRMP3_OFFSET_PTR(pcm, sizeof(drmp3d_sample_t)*384*info->channels);
2379 }
2380 if (bs_frame->pos > bs_frame->limit)
2381 {
2382 drmp3dec_init(dec);
2383 return 0;
2384 }
2385 }
2386#endif
2387 }
2388
2389 return success*drmp3_hdr_frame_samples(dec->header);
2390}
2391
2392DRMP3_API void drmp3dec_f32_to_s16(const float *in, drmp3_int16 *out, size_t num_samples)
2393{
2394 size_t i = 0;
2395#if DRMP3_HAVE_SIMD
2396 size_t aligned_count = num_samples & ~7;
2397 for(; i < aligned_count; i+=8)
2398 {
2399 drmp3_f4 scale = DRMP3_VSET(32768.0f);
2400 drmp3_f4 a = DRMP3_VMUL(DRMP3_VLD(&in[i ]), scale);
2401 drmp3_f4 b = DRMP3_VMUL(DRMP3_VLD(&in[i+4]), scale);
2402#if DRMP3_HAVE_SSE
2403 drmp3_f4 s16max = DRMP3_VSET( 32767.0f);
2404 drmp3_f4 s16min = DRMP3_VSET(-32768.0f);
2405 __m128i pcm8 = _mm_packs_epi32(_mm_cvtps_epi32(_mm_max_ps(_mm_min_ps(a, s16max), s16min)),
2406 _mm_cvtps_epi32(_mm_max_ps(_mm_min_ps(b, s16max), s16min)));
2407 out[i ] = (drmp3_int16)_mm_extract_epi16(pcm8, 0);
2408 out[i+1] = (drmp3_int16)_mm_extract_epi16(pcm8, 1);
2409 out[i+2] = (drmp3_int16)_mm_extract_epi16(pcm8, 2);
2410 out[i+3] = (drmp3_int16)_mm_extract_epi16(pcm8, 3);
2411 out[i+4] = (drmp3_int16)_mm_extract_epi16(pcm8, 4);
2412 out[i+5] = (drmp3_int16)_mm_extract_epi16(pcm8, 5);
2413 out[i+6] = (drmp3_int16)_mm_extract_epi16(pcm8, 6);
2414 out[i+7] = (drmp3_int16)_mm_extract_epi16(pcm8, 7);
2415#else
2416 int16x4_t pcma, pcmb;
2417 a = DRMP3_VADD(a, DRMP3_VSET(0.5f));
2418 b = DRMP3_VADD(b, DRMP3_VSET(0.5f));
2419 pcma = vqmovn_s32(vqaddq_s32(vcvtq_s32_f32(a), vreinterpretq_s32_u32(vcltq_f32(a, DRMP3_VSET(0)))));
2420 pcmb = vqmovn_s32(vqaddq_s32(vcvtq_s32_f32(b), vreinterpretq_s32_u32(vcltq_f32(b, DRMP3_VSET(0)))));
2421 vst1_lane_s16(out+i , pcma, 0);
2422 vst1_lane_s16(out+i+1, pcma, 1);
2423 vst1_lane_s16(out+i+2, pcma, 2);
2424 vst1_lane_s16(out+i+3, pcma, 3);
2425 vst1_lane_s16(out+i+4, pcmb, 0);
2426 vst1_lane_s16(out+i+5, pcmb, 1);
2427 vst1_lane_s16(out+i+6, pcmb, 2);
2428 vst1_lane_s16(out+i+7, pcmb, 3);
2429#endif
2430 }
2431#endif
2432 for(; i < num_samples; i++)
2433 {
2434 float sample = in[i] * 32768.0f;
2435 if (sample >= 32766.5f)
2436 out[i] = (drmp3_int16) 32767;
2437 else if (sample <= -32767.5f)
2438 out[i] = (drmp3_int16)-32768;
2439 else
2440 {
2441 short s = (drmp3_int16)(sample + .5f);
2442 s -= (s < 0); /* away from zero, to be compliant */
2443 out[i] = s;
2444 }
2445 }
2446}
2447
2448
2449
2450/************************************************************************************************************************************************************
2451
2452 Main Public API
2453
2454 ************************************************************************************************************************************************************/
2455/* SIZE_MAX */
2456#if defined(SIZE_MAX)
2457 #define DRMP3_SIZE_MAX SIZE_MAX
2458#else
2459 #if defined(_WIN64) || defined(_LP64) || defined(__LP64__)
2460 #define DRMP3_SIZE_MAX ((drmp3_uint64)0xFFFFFFFFFFFFFFFF)
2461 #else
2462 #define DRMP3_SIZE_MAX 0xFFFFFFFF
2463 #endif
2464#endif
2465/* End SIZE_MAX */
2466
2467/* Options. */
2468#ifndef DRMP3_SEEK_LEADING_MP3_FRAMES
2469#define DRMP3_SEEK_LEADING_MP3_FRAMES 2
2470#endif
2471
2472#define DRMP3_MIN_DATA_CHUNK_SIZE 16384
2473
2474/* The size in bytes of each chunk of data to read from the MP3 stream. minimp3 recommends at least 16K, but in an attempt to reduce data movement I'm making this slightly larger. */
2475#ifndef DRMP3_DATA_CHUNK_SIZE
2476#define DRMP3_DATA_CHUNK_SIZE (DRMP3_MIN_DATA_CHUNK_SIZE*4)
2477#endif
2478
2479
2480#define DRMP3_COUNTOF(x) (sizeof(x) / sizeof(x[0]))
2481#define DRMP3_CLAMP(x, lo, hi) (DRMP3_MAX(lo, DRMP3_MIN(x, hi)))
2482
2483#ifndef DRMP3_PI_D
2484#define DRMP3_PI_D 3.14159265358979323846264
2485#endif
2486
2487#define DRMP3_DEFAULT_RESAMPLER_LPF_ORDER 2
2488
2489static DRMP3_INLINE float drmp3_mix_f32(float x, float y, float a)
2490{
2491 return x*(1-a) + y*a;
2492}
2493static DRMP3_INLINE float drmp3_mix_f32_fast(float x, float y, float a)
2494{
2495 float r0 = (y - x);
2496 float r1 = r0*a;
2497 return x + r1;
2498 /*return x + (y - x)*a;*/
2499}
2500
2501
2502/*
2503Greatest common factor using Euclid's algorithm iteratively.
2504*/
2505static DRMP3_INLINE drmp3_uint32 drmp3_gcf_u32(drmp3_uint32 a, drmp3_uint32 b)
2506{
2507 for (;;) {
2508 if (b == 0) {
2509 break;
2510 } else {
2511 drmp3_uint32 t = a;
2512 a = b;
2513 b = t % a;
2514 }
2515 }
2516
2517 return a;
2518}
2519
2520
2521static void* drmp3__malloc_default(size_t sz, void* pUserData)
2522{
2523 (void)pUserData;
2524 return DRMP3_MALLOC(sz);
2525}
2526
2527static void* drmp3__realloc_default(void* p, size_t sz, void* pUserData)
2528{
2529 (void)pUserData;
2530 return DRMP3_REALLOC(p, sz);
2531}
2532
2533static void drmp3__free_default(void* p, void* pUserData)
2534{
2535 (void)pUserData;
2536 DRMP3_FREE(p);
2537}
2538
2539
2540static void* drmp3__malloc_from_callbacks(size_t sz, const drmp3_allocation_callbacks* pAllocationCallbacks)
2541{
2542 if (pAllocationCallbacks == NULL) {
2543 return NULL;
2544 }
2545
2546 if (pAllocationCallbacks->onMalloc != NULL) {
2547 return pAllocationCallbacks->onMalloc(sz, pAllocationCallbacks->pUserData);
2548 }
2549
2550 /* Try using realloc(). */
2551 if (pAllocationCallbacks->onRealloc != NULL) {
2552 return pAllocationCallbacks->onRealloc(NULL, sz, pAllocationCallbacks->pUserData);
2553 }
2554
2555 return NULL;
2556}
2557
2558static void* drmp3__realloc_from_callbacks(void* p, size_t szNew, size_t szOld, const drmp3_allocation_callbacks* pAllocationCallbacks)
2559{
2560 if (pAllocationCallbacks == NULL) {
2561 return NULL;
2562 }
2563
2564 if (pAllocationCallbacks->onRealloc != NULL) {
2565 return pAllocationCallbacks->onRealloc(p, szNew, pAllocationCallbacks->pUserData);
2566 }
2567
2568 /* Try emulating realloc() in terms of malloc()/free(). */
2569 if (pAllocationCallbacks->onMalloc != NULL && pAllocationCallbacks->onFree != NULL) {
2570 void* p2;
2571
2572 p2 = pAllocationCallbacks->onMalloc(szNew, pAllocationCallbacks->pUserData);
2573 if (p2 == NULL) {
2574 return NULL;
2575 }
2576
2577 if (p != NULL) {
2578 DRMP3_COPY_MEMORY(p2, p, szOld);
2579 pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
2580 }
2581
2582 return p2;
2583 }
2584
2585 return NULL;
2586}
2587
2588static void drmp3__free_from_callbacks(void* p, const drmp3_allocation_callbacks* pAllocationCallbacks)
2589{
2590 if (p == NULL || pAllocationCallbacks == NULL) {
2591 return;
2592 }
2593
2594 if (pAllocationCallbacks->onFree != NULL) {
2595 pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
2596 }
2597}
2598
2599
2600static drmp3_allocation_callbacks drmp3_copy_allocation_callbacks_or_defaults(const drmp3_allocation_callbacks* pAllocationCallbacks)
2601{
2602 if (pAllocationCallbacks != NULL) {
2603 /* Copy. */
2604 return *pAllocationCallbacks;
2605 } else {
2606 /* Defaults. */
2607 drmp3_allocation_callbacks allocationCallbacks;
2608 allocationCallbacks.pUserData = NULL;
2609 allocationCallbacks.onMalloc = drmp3__malloc_default;
2610 allocationCallbacks.onRealloc = drmp3__realloc_default;
2611 allocationCallbacks.onFree = drmp3__free_default;
2612 return allocationCallbacks;
2613 }
2614}
2615
2616
2617
2618static size_t drmp3__on_read(drmp3* pMP3, void* pBufferOut, size_t bytesToRead)
2619{
2620 size_t bytesRead;
2621
2622 DRMP3_ASSERT(pMP3 != NULL);
2623 DRMP3_ASSERT(pMP3->onRead != NULL);
2624
2625 /*
2626 Don't try reading 0 bytes from the callback. This can happen when the stream is clamped against
2627 ID3v1 or APE tags at the end of the stream.
2628 */
2629 if (bytesToRead == 0) {
2630 return 0;
2631 }
2632
2633 bytesRead = pMP3->onRead(pMP3->pUserData, pBufferOut, bytesToRead);
2634 pMP3->streamCursor += bytesRead;
2635
2636 return bytesRead;
2637}
2638
2639static size_t drmp3__on_read_clamped(drmp3* pMP3, void* pBufferOut, size_t bytesToRead)
2640{
2641 DRMP3_ASSERT(pMP3 != NULL);
2642 DRMP3_ASSERT(pMP3->onRead != NULL);
2643
2644 if (pMP3->streamLength == DRMP3_UINT64_MAX) {
2645 return drmp3__on_read(pMP3, pBufferOut, bytesToRead);
2646 } else {
2647 drmp3_uint64 bytesRemaining;
2648
2649 bytesRemaining = (pMP3->streamLength - pMP3->streamCursor);
2650 if (bytesToRead > bytesRemaining) {
2651 bytesToRead = (size_t)bytesRemaining;
2652 }
2653
2654 return drmp3__on_read(pMP3, pBufferOut, bytesToRead);
2655 }
2656}
2657
2658static drmp3_bool32 drmp3__on_seek(drmp3* pMP3, int offset, drmp3_seek_origin origin)
2659{
2660 DRMP3_ASSERT(offset >= 0);
2661 DRMP3_ASSERT(origin == drmp3_seek_origin_start || origin == drmp3_seek_origin_current);
2662
2663 if (!pMP3->onSeek(pMP3->pUserData, offset, origin)) {
2664 return DRMP3_FALSE;
2665 }
2666
2667 if (origin == drmp3_seek_origin_start) {
2668 pMP3->streamCursor = (drmp3_uint64)offset;
2669 } else{
2670 pMP3->streamCursor += offset;
2671 }
2672
2673 return DRMP3_TRUE;
2674}
2675
2676static drmp3_bool32 drmp3__on_seek_64(drmp3* pMP3, drmp3_uint64 offset, drmp3_seek_origin origin)
2677{
2678 if (offset <= 0x7FFFFFFF) {
2679 return drmp3__on_seek(pMP3, (int)offset, origin);
2680 }
2681
2682 /* Getting here "offset" is too large for a 32-bit integer. We just keep seeking forward until we hit the offset. */
2683 if (!drmp3__on_seek(pMP3, 0x7FFFFFFF, drmp3_seek_origin_start)) {
2684 return DRMP3_FALSE;
2685 }
2686
2687 offset -= 0x7FFFFFFF;
2688 while (offset > 0) {
2689 if (offset <= 0x7FFFFFFF) {
2690 if (!drmp3__on_seek(pMP3, (int)offset, drmp3_seek_origin_current)) {
2691 return DRMP3_FALSE;
2692 }
2693 offset = 0;
2694 } else {
2695 if (!drmp3__on_seek(pMP3, 0x7FFFFFFF, drmp3_seek_origin_current)) {
2696 return DRMP3_FALSE;
2697 }
2698 offset -= 0x7FFFFFFF;
2699 }
2700 }
2701
2702 return DRMP3_TRUE;
2703}
2704
2705static void drmp3__on_meta(drmp3* pMP3, drmp3_metadata_type type, const void* pRawData, size_t rawDataSize)
2706{
2707 if (pMP3->onMeta) {
2708 drmp3_metadata metadata;
2709
2710 DRMP3_ZERO_OBJECT(&metadata);
2711 metadata.type = type;
2712 metadata.pRawData = pRawData;
2713 metadata.rawDataSize = rawDataSize;
2714
2715 pMP3->onMeta(pMP3->pUserDataMeta, &metadata);
2716 }
2717}
2718
2719
2720static drmp3_uint32 drmp3_decode_next_frame_ex__callbacks(drmp3* pMP3, drmp3d_sample_t* pPCMFrames, drmp3dec_frame_info* pMP3FrameInfo, const drmp3_uint8** ppMP3FrameData)
2721{
2722 drmp3_uint32 pcmFramesRead = 0;
2723
2724 DRMP3_ASSERT(pMP3 != NULL);
2725 DRMP3_ASSERT(pMP3->onRead != NULL);
2726
2727 if (pMP3->atEnd) {
2728 return 0;
2729 }
2730
2731 for (;;) {
2733
2734 /* minimp3 recommends doing data submission in chunks of at least 16K. If we don't have at least 16K bytes available, get more. */
2735 if (pMP3->dataSize < DRMP3_MIN_DATA_CHUNK_SIZE) {
2736 size_t bytesRead;
2737
2738 /* First we need to move the data down. */
2739 if (pMP3->pData != NULL) {
2740 DRMP3_MOVE_MEMORY(pMP3->pData, pMP3->pData + pMP3->dataConsumed, pMP3->dataSize);
2741 }
2742
2743 pMP3->dataConsumed = 0;
2744
2745 if (pMP3->dataCapacity < DRMP3_DATA_CHUNK_SIZE) {
2746 drmp3_uint8* pNewData;
2747 size_t newDataCap;
2748
2749 newDataCap = DRMP3_DATA_CHUNK_SIZE;
2750
2751 pNewData = (drmp3_uint8*)drmp3__realloc_from_callbacks(pMP3->pData, newDataCap, pMP3->dataCapacity, &pMP3->allocationCallbacks);
2752 if (pNewData == NULL) {
2753 return 0; /* Out of memory. */
2754 }
2755
2756 pMP3->pData = pNewData;
2757 pMP3->dataCapacity = newDataCap;
2758 }
2759
2760 bytesRead = drmp3__on_read_clamped(pMP3, pMP3->pData + pMP3->dataSize, (pMP3->dataCapacity - pMP3->dataSize));
2761 if (bytesRead == 0) {
2762 if (pMP3->dataSize == 0) {
2763 pMP3->atEnd = DRMP3_TRUE;
2764 return 0; /* No data. */
2765 }
2766 }
2767
2768 pMP3->dataSize += bytesRead;
2769 }
2770
2771 if (pMP3->dataSize > INT_MAX) {
2772 pMP3->atEnd = DRMP3_TRUE;
2773 return 0; /* File too big. */
2774 }
2775
2776 DRMP3_ASSERT(pMP3->pData != NULL);
2777 DRMP3_ASSERT(pMP3->dataCapacity > 0);
2778
2779 /* Do a runtime check here to try silencing a false-positive from clang-analyzer. */
2780 if (pMP3->pData == NULL) {
2781 return 0;
2782 }
2783
2784 pcmFramesRead = drmp3dec_decode_frame(&pMP3->decoder, pMP3->pData + pMP3->dataConsumed, (int)pMP3->dataSize, pPCMFrames, &info); /* <-- Safe size_t -> int conversion thanks to the check above. */
2785
2786 /* Consume the data. */
2787 pMP3->dataConsumed += (size_t)info.frame_bytes;
2788 pMP3->dataSize -= (size_t)info.frame_bytes;
2789
2790 /* pcmFramesRead will be equal to 0 if decoding failed. If it is zero and info.frame_bytes > 0 then we have successfully decoded the frame. */
2791 if (pcmFramesRead > 0) {
2792 pcmFramesRead = drmp3_hdr_frame_samples(pMP3->decoder.header);
2794 pMP3->pcmFramesRemainingInMP3Frame = pcmFramesRead;
2795 pMP3->mp3FrameChannels = info.channels;
2796 pMP3->mp3FrameSampleRate = info.sample_rate;
2797
2798 if (pMP3FrameInfo != NULL) {
2799 *pMP3FrameInfo = info;
2800 }
2801
2802 if (ppMP3FrameData != NULL) {
2803 *ppMP3FrameData = pMP3->pData + pMP3->dataConsumed - (size_t)info.frame_bytes;
2804 }
2805
2806 break;
2807 } else if (info.frame_bytes == 0) {
2808 /* Need more data. minimp3 recommends doing data submission in 16K chunks. */
2809 size_t bytesRead;
2810
2811 /* First we need to move the data down. */
2812 DRMP3_MOVE_MEMORY(pMP3->pData, pMP3->pData + pMP3->dataConsumed, pMP3->dataSize);
2813 pMP3->dataConsumed = 0;
2814
2815 if (pMP3->dataCapacity == pMP3->dataSize) {
2816 /* No room. Expand. */
2817 drmp3_uint8* pNewData;
2818 size_t newDataCap;
2819
2820 newDataCap = pMP3->dataCapacity + DRMP3_DATA_CHUNK_SIZE;
2821
2822 pNewData = (drmp3_uint8*)drmp3__realloc_from_callbacks(pMP3->pData, newDataCap, pMP3->dataCapacity, &pMP3->allocationCallbacks);
2823 if (pNewData == NULL) {
2824 return 0; /* Out of memory. */
2825 }
2826
2827 pMP3->pData = pNewData;
2828 pMP3->dataCapacity = newDataCap;
2829 }
2830
2831 /* Fill in a chunk. */
2832 bytesRead = drmp3__on_read_clamped(pMP3, pMP3->pData + pMP3->dataSize, (pMP3->dataCapacity - pMP3->dataSize));
2833 if (bytesRead == 0) {
2834 pMP3->atEnd = DRMP3_TRUE;
2835 return 0; /* Error reading more data. */
2836 }
2837
2838 pMP3->dataSize += bytesRead;
2839 }
2840 };
2841
2842 return pcmFramesRead;
2843}
2844
2845static drmp3_uint32 drmp3_decode_next_frame_ex__memory(drmp3* pMP3, drmp3d_sample_t* pPCMFrames, drmp3dec_frame_info* pMP3FrameInfo, const drmp3_uint8** ppMP3FrameData)
2846{
2847 drmp3_uint32 pcmFramesRead = 0;
2849
2850 DRMP3_ASSERT(pMP3 != NULL);
2851 DRMP3_ASSERT(pMP3->memory.pData != NULL);
2852
2853 if (pMP3->atEnd) {
2854 return 0;
2855 }
2856
2857 for (;;) {
2858 pcmFramesRead = drmp3dec_decode_frame(&pMP3->decoder, pMP3->memory.pData + pMP3->memory.currentReadPos, (int)(pMP3->memory.dataSize - pMP3->memory.currentReadPos), pPCMFrames, &info);
2859 if (pcmFramesRead > 0) {
2860 pcmFramesRead = drmp3_hdr_frame_samples(pMP3->decoder.header);
2862 pMP3->pcmFramesRemainingInMP3Frame = pcmFramesRead;
2863 pMP3->mp3FrameChannels = info.channels;
2864 pMP3->mp3FrameSampleRate = info.sample_rate;
2865
2866 if (pMP3FrameInfo != NULL) {
2867 *pMP3FrameInfo = info;
2868 }
2869
2870 if (ppMP3FrameData != NULL) {
2871 *ppMP3FrameData = pMP3->memory.pData + pMP3->memory.currentReadPos;
2872 }
2873
2874 break;
2875 } else if (info.frame_bytes > 0) {
2876 /* No frames were read, but it looks like we skipped past one. Read the next MP3 frame. */
2877 pMP3->memory.currentReadPos += (size_t)info.frame_bytes;
2878 pMP3->streamCursor += (size_t)info.frame_bytes;
2879 } else {
2880 /* Nothing at all was read. Abort. */
2881 break;
2882 }
2883 }
2884
2885 /* Consume the data. */
2886 pMP3->memory.currentReadPos += (size_t)info.frame_bytes;
2887 pMP3->streamCursor += (size_t)info.frame_bytes;
2888
2889 return pcmFramesRead;
2890}
2891
2892static drmp3_uint32 drmp3_decode_next_frame_ex(drmp3* pMP3, drmp3d_sample_t* pPCMFrames, drmp3dec_frame_info* pMP3FrameInfo, const drmp3_uint8** ppMP3FrameData)
2893{
2894 if (pMP3->memory.pData != NULL && pMP3->memory.dataSize > 0) {
2895 return drmp3_decode_next_frame_ex__memory(pMP3, pPCMFrames, pMP3FrameInfo, ppMP3FrameData);
2896 } else {
2897 return drmp3_decode_next_frame_ex__callbacks(pMP3, pPCMFrames, pMP3FrameInfo, ppMP3FrameData);
2898 }
2899}
2900
2901static drmp3_uint32 drmp3_decode_next_frame(drmp3* pMP3)
2902{
2903 DRMP3_ASSERT(pMP3 != NULL);
2904 return drmp3_decode_next_frame_ex(pMP3, (drmp3d_sample_t*)pMP3->pcmFrames, NULL, NULL);
2905}
2906
2907#if 0
2908static drmp3_uint32 drmp3_seek_next_frame(drmp3* pMP3)
2909{
2910 drmp3_uint32 pcmFrameCount;
2911
2912 DRMP3_ASSERT(pMP3 != NULL);
2913
2914 pcmFrameCount = drmp3_decode_next_frame_ex(pMP3, NULL, NULL, NULL);
2915 if (pcmFrameCount == 0) {
2916 return 0;
2917 }
2918
2919 /* We have essentially just skipped past the frame, so just set the remaining samples to 0. */
2920 pMP3->currentPCMFrame += pcmFrameCount;
2921 pMP3->pcmFramesConsumedInMP3Frame = pcmFrameCount;
2923
2924 return pcmFrameCount;
2925}
2926#endif
2927
2928static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drmp3_seek_proc onSeek, drmp3_tell_proc onTell, drmp3_meta_proc onMeta, void* pUserData, void* pUserDataMeta, const drmp3_allocation_callbacks* pAllocationCallbacks)
2929{
2930 drmp3dec_frame_info firstFrameInfo;
2931 const drmp3_uint8* pFirstFrameData;
2932 drmp3_uint32 firstFramePCMFrameCount;
2933 drmp3_uint32 detectedMP3FrameCount = 0xFFFFFFFF;
2934
2935 DRMP3_ASSERT(pMP3 != NULL);
2936 DRMP3_ASSERT(onRead != NULL);
2937
2938 /* This function assumes the output object has already been reset to 0. Do not do that here, otherwise things will break. */
2939 drmp3dec_init(&pMP3->decoder);
2940
2941 pMP3->onRead = onRead;
2942 pMP3->onSeek = onSeek;
2943 pMP3->onMeta = onMeta;
2944 pMP3->pUserData = pUserData;
2945 pMP3->pUserDataMeta = pUserDataMeta;
2946 pMP3->allocationCallbacks = drmp3_copy_allocation_callbacks_or_defaults(pAllocationCallbacks);
2947
2948 if (pMP3->allocationCallbacks.onFree == NULL || (pMP3->allocationCallbacks.onMalloc == NULL && pMP3->allocationCallbacks.onRealloc == NULL)) {
2949 return DRMP3_FALSE; /* Invalid allocation callbacks. */
2950 }
2951
2952 pMP3->streamCursor = 0;
2954 pMP3->streamStartOffset = 0;
2955 pMP3->delayInPCMFrames = 0;
2956 pMP3->paddingInPCMFrames = 0;
2958
2959 /* We'll first check for any ID3v1 or APE tags. */
2960 #if 1
2961 if (onSeek != NULL && onTell != NULL) {
2962 if (onSeek(pUserData, 0, drmp3_seek_origin_end)) {
2963 drmp3_int64 streamLen;
2964 int streamEndOffset = 0;
2965
2966 /* First get the length of the stream. We need this so we can ensure the stream is big enough to store the tags. */
2967 if (onTell(pUserData, &streamLen)) {
2968 /* ID3v1 */
2969 if (streamLen > 128) {
2970 char id3[3];
2971 if (onSeek(pUserData, streamEndOffset - 128, drmp3_seek_origin_end)) {
2972 if (onRead(pUserData, id3, 3) == 3 && id3[0] == 'T' && id3[1] == 'A' && id3[2] == 'G') {
2973 /* We have an ID3v1 tag. */
2974 streamEndOffset -= 128;
2975 streamLen -= 128;
2976
2977 /* Fire a metadata callback for the TAG data. */
2978 if (onMeta != NULL) {
2979 drmp3_uint8 tag[128];
2980 tag[0] = 'T'; tag[1] = 'A'; tag[2] = 'G';
2981
2982 if (onRead(pUserData, tag + 3, 125) == 125) {
2983 drmp3__on_meta(pMP3, DRMP3_METADATA_TYPE_ID3V1, tag, 128);
2984 }
2985 }
2986 } else {
2987 /* No ID3v1 tag. */
2988 }
2989 } else {
2990 /* Failed to seek to the ID3v1 tag. */
2991 }
2992 } else {
2993 /* Stream too short. No ID3v1 tag. */
2994 }
2995
2996 /* APE */
2997 if (streamLen > 32) {
2998 char ape[32]; /* The footer. */
2999 if (onSeek(pUserData, streamEndOffset - 32, drmp3_seek_origin_end)) {
3000 if (onRead(pUserData, ape, 32) == 32 && ape[0] == 'A' && ape[1] == 'P' && ape[2] == 'E' && ape[3] == 'T' && ape[4] == 'A' && ape[5] == 'G' && ape[6] == 'E' && ape[7] == 'X') {
3001 /* We have an APE tag. */
3002 drmp3_uint32 tagSize =
3003 ((drmp3_uint32)ape[24] << 0) |
3004 ((drmp3_uint32)ape[25] << 8) |
3005 ((drmp3_uint32)ape[26] << 16) |
3006 ((drmp3_uint32)ape[27] << 24);
3007
3008 streamEndOffset -= 32 + tagSize;
3009 streamLen -= 32 + tagSize;
3010
3011 /* Fire a metadata callback for the APE data. Must include both the main content and footer. */
3012 if (onMeta != NULL) {
3013 /* We first need to seek to the start of the APE tag. */
3014 if (onSeek(pUserData, streamEndOffset, drmp3_seek_origin_end)) {
3015 size_t apeTagSize = (size_t)tagSize + 32;
3016 drmp3_uint8* pTagData = (drmp3_uint8*)drmp3_malloc(apeTagSize, pAllocationCallbacks);
3017 if (pTagData != NULL) {
3018 if (onRead(pUserData, pTagData, apeTagSize) == apeTagSize) {
3019 drmp3__on_meta(pMP3, DRMP3_METADATA_TYPE_APE, pTagData, apeTagSize);
3020 }
3021
3022 drmp3_free(pTagData, pAllocationCallbacks);
3023 }
3024 }
3025 }
3026 }
3027 }
3028 } else {
3029 /* Stream too short. No APE tag. */
3030 }
3031
3032 /* Seek back to the start. */
3033 if (!onSeek(pUserData, 0, drmp3_seek_origin_start)) {
3034 return DRMP3_FALSE; /* Failed to seek back to the start. */
3035 }
3036
3037 pMP3->streamLength = (drmp3_uint64)streamLen;
3038
3039 if (pMP3->memory.pData != NULL) {
3040 pMP3->memory.dataSize = (size_t)pMP3->streamLength;
3041 }
3042 } else {
3043 /* Failed to get the length of the stream. ID3v1 and APE tags cannot be skipped. */
3044 if (!onSeek(pUserData, 0, drmp3_seek_origin_start)) {
3045 return DRMP3_FALSE; /* Failed to seek back to the start. */
3046 }
3047 }
3048 } else {
3049 /* Failed to seek to the end. Cannot skip ID3v1 or APE tags. */
3050 }
3051 } else {
3052 /* No onSeek or onTell callback. Cannot skip ID3v1 or APE tags. */
3053 }
3054 #endif
3055
3056
3057 /* ID3v2 tags */
3058 #if 1
3059 {
3060 char header[10];
3061 if (onRead(pUserData, header, 10) == 10) {
3062 if (header[0] == 'I' && header[1] == 'D' && header[2] == '3') {
3063 drmp3_uint32 tagSize =
3064 (((drmp3_uint32)header[6] & 0x7F) << 21) |
3065 (((drmp3_uint32)header[7] & 0x7F) << 14) |
3066 (((drmp3_uint32)header[8] & 0x7F) << 7) |
3067 (((drmp3_uint32)header[9] & 0x7F) << 0);
3068
3069 /* Account for the footer. */
3070 if (header[5] & 0x10) {
3071 tagSize += 10;
3072 }
3073
3074 /* Read the tag content and fire a metadata callback. */
3075 if (onMeta != NULL) {
3076 size_t tagSizeWithHeader = 10 + tagSize;
3077 drmp3_uint8* pTagData = (drmp3_uint8*)drmp3_malloc(tagSizeWithHeader, pAllocationCallbacks);
3078 if (pTagData != NULL) {
3079 DRMP3_COPY_MEMORY(pTagData, header, 10);
3080
3081 if (onRead(pUserData, pTagData + 10, tagSize) == tagSize) {
3082 drmp3__on_meta(pMP3, DRMP3_METADATA_TYPE_ID3V2, pTagData, tagSizeWithHeader);
3083 }
3084
3085 drmp3_free(pTagData, pAllocationCallbacks);
3086 }
3087 } else {
3088 /* Don't have a metadata callback, so just skip the tag. */
3089 if (onSeek != NULL) {
3090 if (!onSeek(pUserData, tagSize, drmp3_seek_origin_current)) {
3091 return DRMP3_FALSE; /* Failed to seek past the ID3v2 tag. */
3092 }
3093 } else {
3094 /* Don't have a seek callback. Read and discard. */
3095 char discard[1024];
3096
3097 while (tagSize > 0) {
3098 size_t bytesToRead = tagSize;
3099 if (bytesToRead > sizeof(discard)) {
3100 bytesToRead = sizeof(discard);
3101 }
3102
3103 if (onRead(pUserData, discard, bytesToRead) != bytesToRead) {
3104 return DRMP3_FALSE; /* Failed to read data. */
3105 }
3106
3107 tagSize -= (drmp3_uint32)bytesToRead;
3108 }
3109 }
3110 }
3111
3112 pMP3->streamStartOffset += 10 + tagSize; /* +10 for the header. */
3113 pMP3->streamCursor = pMP3->streamStartOffset;
3114 } else {
3115 /* Not an ID3v2 tag. Seek back to the start. */
3116 if (onSeek != NULL) {
3117 if (!onSeek(pUserData, 0, drmp3_seek_origin_start)) {
3118 return DRMP3_FALSE; /* Failed to seek back to the start. */
3119 }
3120 } else {
3121 /* Don't have a seek callback to move backwards. We'll just fall through and let the decoding process re-sync. The ideal solution here would be to read into the cache. */
3122
3123 /*
3124 TODO: Copy the header into the cache. Will need to allocate space. See drmp3_decode_next_frame_ex__callbacks. There is not need
3125 to handle the memory case because that will always have a seek implementation and will never hit this code path.
3126 */
3127 }
3128 }
3129 } else {
3130 /* Failed to read the header. We can return false here. If we couldn't read 10 bytes there's no way we'll have a valid MP3 stream. */
3131 return DRMP3_FALSE;
3132 }
3133 }
3134 #endif
3135
3136 /*
3137 Decode the first frame to confirm that it is indeed a valid MP3 stream. Note that it's possible the first frame
3138 is actually a Xing/LAME/VBRI header. If this is the case we need to skip over it.
3139 */
3140 firstFramePCMFrameCount = drmp3_decode_next_frame_ex(pMP3, (drmp3d_sample_t*)pMP3->pcmFrames, &firstFrameInfo, &pFirstFrameData);
3141 if (firstFramePCMFrameCount > 0) {
3142 DRMP3_ASSERT(pFirstFrameData != NULL);
3143
3144 /*
3145 It might be a header. If so, we need to clear out the cached PCM frames in order to trigger a reload of fresh
3146 data when decoding starts. We can assume all validation has already been performed to check if this is a valid
3147 MP3 frame and that there is more than 0 bytes making up the frame.
3148
3149 We're going to be basing this parsing code off the minimp3_ex implementation.
3150 */
3151 #if 1
3152 DRMP3_ASSERT(firstFrameInfo.frame_bytes > 0);
3153 {
3154 drmp3_bs bs;
3155 drmp3_L3_gr_info grInfo[4];
3156 const drmp3_uint8* pTagData = pFirstFrameData;
3157
3158 drmp3_bs_init(&bs, pFirstFrameData + DRMP3_HDR_SIZE, firstFrameInfo.frame_bytes - DRMP3_HDR_SIZE);
3159
3160 if (DRMP3_HDR_IS_CRC(pFirstFrameData)) {
3161 drmp3_bs_get_bits(&bs, 16); /* CRC. */
3162 }
3163
3164 if (drmp3_L3_read_side_info(&bs, grInfo, pFirstFrameData) >= 0) {
3165 drmp3_bool32 isXing = DRMP3_FALSE;
3166 drmp3_bool32 isInfo = DRMP3_FALSE;
3167 const drmp3_uint8* pTagDataBeg;
3168
3169 pTagDataBeg = pFirstFrameData + DRMP3_HDR_SIZE + (bs.pos/8);
3170 pTagData = pTagDataBeg;
3171
3172 /* Check for both "Xing" and "Info" identifiers. */
3173 isXing = (pTagData[0] == 'X' && pTagData[1] == 'i' && pTagData[2] == 'n' && pTagData[3] == 'g');
3174 isInfo = (pTagData[0] == 'I' && pTagData[1] == 'n' && pTagData[2] == 'f' && pTagData[3] == 'o');
3175
3176 if (isXing || isInfo) {
3177 drmp3_uint32 bytes = 0;
3178 drmp3_uint32 flags = pTagData[7];
3179
3180 pTagData += 8; /* Skip past the ID and flags. */
3181
3182 if (flags & 0x01) { /* FRAMES flag. */
3183 detectedMP3FrameCount = (drmp3_uint32)pTagData[0] << 24 | (drmp3_uint32)pTagData[1] << 16 | (drmp3_uint32)pTagData[2] << 8 | (drmp3_uint32)pTagData[3];
3184 pTagData += 4;
3185 }
3186
3187 if (flags & 0x02) { /* BYTES flag. */
3188 bytes = (drmp3_uint32)pTagData[0] << 24 | (drmp3_uint32)pTagData[1] << 16 | (drmp3_uint32)pTagData[2] << 8 | (drmp3_uint32)pTagData[3];
3189 (void)bytes; /* <-- Just to silence a warning about `bytes` being assigned but unused. Want to leave this here in case I want to make use of it later. */
3190 pTagData += 4;
3191 }
3192
3193 if (flags & 0x04) { /* TOC flag. */
3194 /* TODO: Extract and bind seek points. */
3195 pTagData += 100;
3196 }
3197
3198 if (flags & 0x08) { /* SCALE flag. */
3199 pTagData += 4;
3200 }
3201
3202 /* At this point we're done with the Xing/Info header. Now we can look at the LAME data. */
3203 if (pTagData[0]) {
3204 pTagData += 21;
3205
3206 if (pTagData - pFirstFrameData + 14 < firstFrameInfo.frame_bytes) {
3207 int delayInPCMFrames;
3208 int paddingInPCMFrames;
3209
3210 delayInPCMFrames = (( (drmp3_uint32)pTagData[0] << 4) | ((drmp3_uint32)pTagData[1] >> 4)) + (528 + 1);
3211 paddingInPCMFrames = ((((drmp3_uint32)pTagData[1] & 0xF) << 8) | ((drmp3_uint32)pTagData[2] )) - (528 + 1);
3212 if (paddingInPCMFrames < 0) {
3213 paddingInPCMFrames = 0; /* Padding cannot be negative. Probably a malformed file. Ignore. */
3214 }
3215
3216 pMP3->delayInPCMFrames = (drmp3_uint32)delayInPCMFrames;
3217 pMP3->paddingInPCMFrames = (drmp3_uint32)paddingInPCMFrames;
3218 }
3219 }
3220
3221 /*
3222 My understanding is that if the "Xing" header is present we can consider this to be a VBR stream and if the "Info" header is
3223 present it's a CBR stream. If this is not the case let me know! I'm just tracking this for the time being in case I want to
3224 look at doing some CBR optimizations later on, such as faster seeking.
3225 */
3226 if (isXing) {
3227 pMP3->isVBR = DRMP3_TRUE;
3228 } else if (isInfo) {
3229 pMP3->isCBR = DRMP3_TRUE;
3230 }
3231
3232 /* Post the raw data of the tag to the metadata callback. */
3233 if (onMeta != NULL) {
3235 size_t tagDataSize;
3236
3237 tagDataSize = (size_t)firstFrameInfo.frame_bytes;
3238 tagDataSize -= (size_t)(pTagDataBeg - pFirstFrameData);
3239
3240 drmp3__on_meta(pMP3, metadataType, pTagDataBeg, tagDataSize);
3241 }
3242
3243 /* Since this was identified as a tag, we don't want to treat it as audio. We need to clear out the PCM cache. */
3245
3246 /* The start offset needs to be moved to the end of this frame so it's not included in any audio processing after seeking. */
3247 pMP3->streamStartOffset += (drmp3_uint32)(firstFrameInfo.frame_bytes);
3248 pMP3->streamCursor = pMP3->streamStartOffset;
3249 }
3250 } else {
3251 /* Failed to read the side info. */
3252 }
3253 }
3254 #endif
3255 } else {
3256 /* Not a valid MP3 stream. */
3257 drmp3__free_from_callbacks(pMP3->pData, &pMP3->allocationCallbacks); /* The call above may have allocated memory. Need to make sure it's freed before aborting. */
3258 return DRMP3_FALSE;
3259 }
3260
3261 if (detectedMP3FrameCount != 0xFFFFFFFF) {
3262 pMP3->totalPCMFrameCount = detectedMP3FrameCount * firstFramePCMFrameCount;
3263 }
3264
3265 pMP3->channels = pMP3->mp3FrameChannels;
3266 pMP3->sampleRate = pMP3->mp3FrameSampleRate;
3267
3268 return DRMP3_TRUE;
3269}
3270
3271DRMP3_API drmp3_bool32 drmp3_init(drmp3* pMP3, drmp3_read_proc onRead, drmp3_seek_proc onSeek, drmp3_tell_proc onTell, drmp3_meta_proc onMeta, void* pUserData, const drmp3_allocation_callbacks* pAllocationCallbacks)
3272{
3273 if (pMP3 == NULL || onRead == NULL) {
3274 return DRMP3_FALSE;
3275 }
3276
3277 DRMP3_ZERO_OBJECT(pMP3);
3278 return drmp3_init_internal(pMP3, onRead, onSeek, onTell, onMeta, pUserData, pUserData, pAllocationCallbacks);
3279}
3280
3281
3282static size_t drmp3__on_read_memory(void* pUserData, void* pBufferOut, size_t bytesToRead)
3283{
3284 drmp3* pMP3 = (drmp3*)pUserData;
3285 size_t bytesRemaining;
3286
3287 DRMP3_ASSERT(pMP3 != NULL);
3288 DRMP3_ASSERT(pMP3->memory.dataSize >= pMP3->memory.currentReadPos);
3289
3290 bytesRemaining = pMP3->memory.dataSize - pMP3->memory.currentReadPos;
3291 if (bytesToRead > bytesRemaining) {
3292 bytesToRead = bytesRemaining;
3293 }
3294
3295 if (bytesToRead > 0) {
3296 DRMP3_COPY_MEMORY(pBufferOut, pMP3->memory.pData + pMP3->memory.currentReadPos, bytesToRead);
3297 pMP3->memory.currentReadPos += bytesToRead;
3298 }
3299
3300 return bytesToRead;
3301}
3302
3303static drmp3_bool32 drmp3__on_seek_memory(void* pUserData, int byteOffset, drmp3_seek_origin origin)
3304{
3305 drmp3* pMP3 = (drmp3*)pUserData;
3306
3307 DRMP3_ASSERT(pMP3 != NULL);
3308
3309 if (origin == drmp3_seek_origin_current) {
3310 if (byteOffset > 0) {
3311 if (pMP3->memory.currentReadPos + byteOffset > pMP3->memory.dataSize) {
3312 return DRMP3_FALSE; /* Trying to seek too far forward. */
3313 }
3314 } else {
3315 if (pMP3->memory.currentReadPos < (size_t)-byteOffset) {
3316 return DRMP3_FALSE; /* Trying to seek too far backwards. */
3317 }
3318 }
3319
3320 /* This will never underflow thanks to the clamps above. */
3321 pMP3->memory.currentReadPos += byteOffset;
3322 } else if (origin == drmp3_seek_origin_start) {
3323 if ((drmp3_uint32)byteOffset <= pMP3->memory.dataSize) {
3324 pMP3->memory.currentReadPos = byteOffset;
3325 } else {
3326 return DRMP3_FALSE; /* Trying to seek too far forward. */
3327 }
3328 } else if (origin == drmp3_seek_origin_end) {
3329 if (byteOffset > 0) {
3330 return DRMP3_FALSE; /* Trying to seek beyond the end of the buffer. */
3331 }
3332
3333 if ((size_t)(-byteOffset) > pMP3->memory.dataSize) {
3334 return DRMP3_FALSE; /* Trying to seek too far back. */
3335 }
3336
3337 pMP3->memory.currentReadPos = pMP3->memory.dataSize - (size_t)(-byteOffset);
3338 }
3339
3340 return DRMP3_TRUE;
3341}
3342
3343static drmp3_bool32 drmp3__on_tell_memory(void* pUserData, drmp3_int64* pCursor)
3344{
3345 drmp3* pMP3 = (drmp3*)pUserData;
3346
3347 DRMP3_ASSERT(pMP3 != NULL);
3348 DRMP3_ASSERT(pCursor != NULL);
3349
3350 *pCursor = (drmp3_int64)pMP3->memory.currentReadPos;
3351 return DRMP3_TRUE;
3352}
3353
3354DRMP3_API drmp3_bool32 drmp3_init_memory_with_metadata(drmp3* pMP3, const void* pData, size_t dataSize, drmp3_meta_proc onMeta, void* pUserDataMeta, const drmp3_allocation_callbacks* pAllocationCallbacks)
3355{
3356 drmp3_bool32 result;
3357
3358 if (pMP3 == NULL) {
3359 return DRMP3_FALSE;
3360 }
3361
3362 DRMP3_ZERO_OBJECT(pMP3);
3363
3364 if (pData == NULL || dataSize == 0) {
3365 return DRMP3_FALSE;
3366 }
3367
3368 pMP3->memory.pData = (const drmp3_uint8*)pData;
3369 pMP3->memory.dataSize = dataSize;
3370 pMP3->memory.currentReadPos = 0;
3371
3372 result = drmp3_init_internal(pMP3, drmp3__on_read_memory, drmp3__on_seek_memory, drmp3__on_tell_memory, onMeta, pMP3, pUserDataMeta, pAllocationCallbacks);
3373 if (result == DRMP3_FALSE) {
3374 return DRMP3_FALSE;
3375 }
3376
3377 /* Adjust the length of the memory stream to account for ID3v1 and APE tags. */
3378 if (pMP3->streamLength <= (drmp3_uint64)DRMP3_SIZE_MAX) {
3379 pMP3->memory.dataSize = (size_t)pMP3->streamLength; /* Safe cast. */
3380 }
3381
3382 if (pMP3->streamStartOffset > (drmp3_uint64)DRMP3_SIZE_MAX) {
3383 return DRMP3_FALSE; /* Tags too big. */
3384 }
3385
3386 return DRMP3_TRUE;
3387}
3388
3389DRMP3_API drmp3_bool32 drmp3_init_memory(drmp3* pMP3, const void* pData, size_t dataSize, const drmp3_allocation_callbacks* pAllocationCallbacks)
3390{
3391 return drmp3_init_memory_with_metadata(pMP3, pData, dataSize, NULL, NULL, pAllocationCallbacks);
3392}
3393
3394
3395#ifndef DR_MP3_NO_STDIO
3396#include <stdio.h>
3397#include <wchar.h> /* For wcslen(), wcsrtombs() */
3398
3399/* Errno */
3400/* drmp3_result_from_errno() is only used inside DR_MP3_NO_STDIO for now. Move this out if it's ever used elsewhere. */
3401#include <errno.h>
3402static drmp3_result drmp3_result_from_errno(int e)
3403{
3404 switch (e)
3405 {
3406 case 0: return DRMP3_SUCCESS;
3407 #ifdef EPERM
3408 case EPERM: return DRMP3_INVALID_OPERATION;
3409 #endif
3410 #ifdef ENOENT
3411 case ENOENT: return DRMP3_DOES_NOT_EXIST;
3412 #endif
3413 #ifdef ESRCH
3414 case ESRCH: return DRMP3_DOES_NOT_EXIST;
3415 #endif
3416 #ifdef EINTR
3417 case EINTR: return DRMP3_INTERRUPT;
3418 #endif
3419 #ifdef EIO
3420 case EIO: return DRMP3_IO_ERROR;
3421 #endif
3422 #ifdef ENXIO
3423 case ENXIO: return DRMP3_DOES_NOT_EXIST;
3424 #endif
3425 #ifdef E2BIG
3426 case E2BIG: return DRMP3_INVALID_ARGS;
3427 #endif
3428 #ifdef ENOEXEC
3429 case ENOEXEC: return DRMP3_INVALID_FILE;
3430 #endif
3431 #ifdef EBADF
3432 case EBADF: return DRMP3_INVALID_FILE;
3433 #endif
3434 #ifdef ECHILD
3435 case ECHILD: return DRMP3_ERROR;
3436 #endif
3437 #ifdef EAGAIN
3438 case EAGAIN: return DRMP3_UNAVAILABLE;
3439 #endif
3440 #ifdef ENOMEM
3441 case ENOMEM: return DRMP3_OUT_OF_MEMORY;
3442 #endif
3443 #ifdef EACCES
3444 case EACCES: return DRMP3_ACCESS_DENIED;
3445 #endif
3446 #ifdef EFAULT
3447 case EFAULT: return DRMP3_BAD_ADDRESS;
3448 #endif
3449 #ifdef ENOTBLK
3450 case ENOTBLK: return DRMP3_ERROR;
3451 #endif
3452 #ifdef EBUSY
3453 case EBUSY: return DRMP3_BUSY;
3454 #endif
3455 #ifdef EEXIST
3456 case EEXIST: return DRMP3_ALREADY_EXISTS;
3457 #endif
3458 #ifdef EXDEV
3459 case EXDEV: return DRMP3_ERROR;
3460 #endif
3461 #ifdef ENODEV
3462 case ENODEV: return DRMP3_DOES_NOT_EXIST;
3463 #endif
3464 #ifdef ENOTDIR
3465 case ENOTDIR: return DRMP3_NOT_DIRECTORY;
3466 #endif
3467 #ifdef EISDIR
3468 case EISDIR: return DRMP3_IS_DIRECTORY;
3469 #endif
3470 #ifdef EINVAL
3471 case EINVAL: return DRMP3_INVALID_ARGS;
3472 #endif
3473 #ifdef ENFILE
3474 case ENFILE: return DRMP3_TOO_MANY_OPEN_FILES;
3475 #endif
3476 #ifdef EMFILE
3477 case EMFILE: return DRMP3_TOO_MANY_OPEN_FILES;
3478 #endif
3479 #ifdef ENOTTY
3480 case ENOTTY: return DRMP3_INVALID_OPERATION;
3481 #endif
3482 #ifdef ETXTBSY
3483 case ETXTBSY: return DRMP3_BUSY;
3484 #endif
3485 #ifdef EFBIG
3486 case EFBIG: return DRMP3_TOO_BIG;
3487 #endif
3488 #ifdef ENOSPC
3489 case ENOSPC: return DRMP3_NO_SPACE;
3490 #endif
3491 #ifdef ESPIPE
3492 case ESPIPE: return DRMP3_BAD_SEEK;
3493 #endif
3494 #ifdef EROFS
3495 case EROFS: return DRMP3_ACCESS_DENIED;
3496 #endif
3497 #ifdef EMLINK
3498 case EMLINK: return DRMP3_TOO_MANY_LINKS;
3499 #endif
3500 #ifdef EPIPE
3501 case EPIPE: return DRMP3_BAD_PIPE;
3502 #endif
3503 #ifdef EDOM
3504 case EDOM: return DRMP3_OUT_OF_RANGE;
3505 #endif
3506 #ifdef ERANGE
3507 case ERANGE: return DRMP3_OUT_OF_RANGE;
3508 #endif
3509 #ifdef EDEADLK
3510 case EDEADLK: return DRMP3_DEADLOCK;
3511 #endif
3512 #ifdef ENAMETOOLONG
3513 case ENAMETOOLONG: return DRMP3_PATH_TOO_LONG;
3514 #endif
3515 #ifdef ENOLCK
3516 case ENOLCK: return DRMP3_ERROR;
3517 #endif
3518 #ifdef ENOSYS
3519 case ENOSYS: return DRMP3_NOT_IMPLEMENTED;
3520 #endif
3521 #if defined(ENOTEMPTY) && ENOTEMPTY != EEXIST /* In AIX, ENOTEMPTY and EEXIST use the same value. */
3522 case ENOTEMPTY: return DRMP3_DIRECTORY_NOT_EMPTY;
3523 #endif
3524 #ifdef ELOOP
3525 case ELOOP: return DRMP3_TOO_MANY_LINKS;
3526 #endif
3527 #ifdef ENOMSG
3528 case ENOMSG: return DRMP3_NO_MESSAGE;
3529 #endif
3530 #ifdef EIDRM
3531 case EIDRM: return DRMP3_ERROR;
3532 #endif
3533 #ifdef ECHRNG
3534 case ECHRNG: return DRMP3_ERROR;
3535 #endif
3536 #ifdef EL2NSYNC
3537 case EL2NSYNC: return DRMP3_ERROR;
3538 #endif
3539 #ifdef EL3HLT
3540 case EL3HLT: return DRMP3_ERROR;
3541 #endif
3542 #ifdef EL3RST
3543 case EL3RST: return DRMP3_ERROR;
3544 #endif
3545 #ifdef ELNRNG
3546 case ELNRNG: return DRMP3_OUT_OF_RANGE;
3547 #endif
3548 #ifdef EUNATCH
3549 case EUNATCH: return DRMP3_ERROR;
3550 #endif
3551 #ifdef ENOCSI
3552 case ENOCSI: return DRMP3_ERROR;
3553 #endif
3554 #ifdef EL2HLT
3555 case EL2HLT: return DRMP3_ERROR;
3556 #endif
3557 #ifdef EBADE
3558 case EBADE: return DRMP3_ERROR;
3559 #endif
3560 #ifdef EBADR
3561 case EBADR: return DRMP3_ERROR;
3562 #endif
3563 #ifdef EXFULL
3564 case EXFULL: return DRMP3_ERROR;
3565 #endif
3566 #ifdef ENOANO
3567 case ENOANO: return DRMP3_ERROR;
3568 #endif
3569 #ifdef EBADRQC
3570 case EBADRQC: return DRMP3_ERROR;
3571 #endif
3572 #ifdef EBADSLT
3573 case EBADSLT: return DRMP3_ERROR;
3574 #endif
3575 #ifdef EBFONT
3576 case EBFONT: return DRMP3_INVALID_FILE;
3577 #endif
3578 #ifdef ENOSTR
3579 case ENOSTR: return DRMP3_ERROR;
3580 #endif
3581 #ifdef ENODATA
3582 case ENODATA: return DRMP3_NO_DATA_AVAILABLE;
3583 #endif
3584 #ifdef ETIME
3585 case ETIME: return DRMP3_TIMEOUT;
3586 #endif
3587 #ifdef ENOSR
3588 case ENOSR: return DRMP3_NO_DATA_AVAILABLE;
3589 #endif
3590 #ifdef ENONET
3591 case ENONET: return DRMP3_NO_NETWORK;
3592 #endif
3593 #ifdef ENOPKG
3594 case ENOPKG: return DRMP3_ERROR;
3595 #endif
3596 #ifdef EREMOTE
3597 case EREMOTE: return DRMP3_ERROR;
3598 #endif
3599 #ifdef ENOLINK
3600 case ENOLINK: return DRMP3_ERROR;
3601 #endif
3602 #ifdef EADV
3603 case EADV: return DRMP3_ERROR;
3604 #endif
3605 #ifdef ESRMNT
3606 case ESRMNT: return DRMP3_ERROR;
3607 #endif
3608 #ifdef ECOMM
3609 case ECOMM: return DRMP3_ERROR;
3610 #endif
3611 #ifdef EPROTO
3612 case EPROTO: return DRMP3_ERROR;
3613 #endif
3614 #ifdef EMULTIHOP
3615 case EMULTIHOP: return DRMP3_ERROR;
3616 #endif
3617 #ifdef EDOTDOT
3618 case EDOTDOT: return DRMP3_ERROR;
3619 #endif
3620 #ifdef EBADMSG
3621 case EBADMSG: return DRMP3_BAD_MESSAGE;
3622 #endif
3623 #ifdef EOVERFLOW
3624 case EOVERFLOW: return DRMP3_TOO_BIG;
3625 #endif
3626 #ifdef ENOTUNIQ
3627 case ENOTUNIQ: return DRMP3_NOT_UNIQUE;
3628 #endif
3629 #ifdef EBADFD
3630 case EBADFD: return DRMP3_ERROR;
3631 #endif
3632 #ifdef EREMCHG
3633 case EREMCHG: return DRMP3_ERROR;
3634 #endif
3635 #ifdef ELIBACC
3636 case ELIBACC: return DRMP3_ACCESS_DENIED;
3637 #endif
3638 #ifdef ELIBBAD
3639 case ELIBBAD: return DRMP3_INVALID_FILE;
3640 #endif
3641 #ifdef ELIBSCN
3642 case ELIBSCN: return DRMP3_INVALID_FILE;
3643 #endif
3644 #ifdef ELIBMAX
3645 case ELIBMAX: return DRMP3_ERROR;
3646 #endif
3647 #ifdef ELIBEXEC
3648 case ELIBEXEC: return DRMP3_ERROR;
3649 #endif
3650 #ifdef EILSEQ
3651 case EILSEQ: return DRMP3_INVALID_DATA;
3652 #endif
3653 #ifdef ERESTART
3654 case ERESTART: return DRMP3_ERROR;
3655 #endif
3656 #ifdef ESTRPIPE
3657 case ESTRPIPE: return DRMP3_ERROR;
3658 #endif
3659 #ifdef EUSERS
3660 case EUSERS: return DRMP3_ERROR;
3661 #endif
3662 #ifdef ENOTSOCK
3663 case ENOTSOCK: return DRMP3_NOT_SOCKET;
3664 #endif
3665 #ifdef EDESTADDRREQ
3666 case EDESTADDRREQ: return DRMP3_NO_ADDRESS;
3667 #endif
3668 #ifdef EMSGSIZE
3669 case EMSGSIZE: return DRMP3_TOO_BIG;
3670 #endif
3671 #ifdef EPROTOTYPE
3672 case EPROTOTYPE: return DRMP3_BAD_PROTOCOL;
3673 #endif
3674 #ifdef ENOPROTOOPT
3675 case ENOPROTOOPT: return DRMP3_PROTOCOL_UNAVAILABLE;
3676 #endif
3677 #ifdef EPROTONOSUPPORT
3678 case EPROTONOSUPPORT: return DRMP3_PROTOCOL_NOT_SUPPORTED;
3679 #endif
3680 #ifdef ESOCKTNOSUPPORT
3681 case ESOCKTNOSUPPORT: return DRMP3_SOCKET_NOT_SUPPORTED;
3682 #endif
3683 #ifdef EOPNOTSUPP
3684 case EOPNOTSUPP: return DRMP3_INVALID_OPERATION;
3685 #endif
3686 #ifdef EPFNOSUPPORT
3687 case EPFNOSUPPORT: return DRMP3_PROTOCOL_FAMILY_NOT_SUPPORTED;
3688 #endif
3689 #ifdef EAFNOSUPPORT
3690 case EAFNOSUPPORT: return DRMP3_ADDRESS_FAMILY_NOT_SUPPORTED;
3691 #endif
3692 #ifdef EADDRINUSE
3693 case EADDRINUSE: return DRMP3_ALREADY_IN_USE;
3694 #endif
3695 #ifdef EADDRNOTAVAIL
3696 case EADDRNOTAVAIL: return DRMP3_ERROR;
3697 #endif
3698 #ifdef ENETDOWN
3699 case ENETDOWN: return DRMP3_NO_NETWORK;
3700 #endif
3701 #ifdef ENETUNREACH
3702 case ENETUNREACH: return DRMP3_NO_NETWORK;
3703 #endif
3704 #ifdef ENETRESET
3705 case ENETRESET: return DRMP3_NO_NETWORK;
3706 #endif
3707 #ifdef ECONNABORTED
3708 case ECONNABORTED: return DRMP3_NO_NETWORK;
3709 #endif
3710 #ifdef ECONNRESET
3711 case ECONNRESET: return DRMP3_CONNECTION_RESET;
3712 #endif
3713 #ifdef ENOBUFS
3714 case ENOBUFS: return DRMP3_NO_SPACE;
3715 #endif
3716 #ifdef EISCONN
3717 case EISCONN: return DRMP3_ALREADY_CONNECTED;
3718 #endif
3719 #ifdef ENOTCONN
3720 case ENOTCONN: return DRMP3_NOT_CONNECTED;
3721 #endif
3722 #ifdef ESHUTDOWN
3723 case ESHUTDOWN: return DRMP3_ERROR;
3724 #endif
3725 #ifdef ETOOMANYREFS
3726 case ETOOMANYREFS: return DRMP3_ERROR;
3727 #endif
3728 #ifdef ETIMEDOUT
3729 case ETIMEDOUT: return DRMP3_TIMEOUT;
3730 #endif
3731 #ifdef ECONNREFUSED
3732 case ECONNREFUSED: return DRMP3_CONNECTION_REFUSED;
3733 #endif
3734 #ifdef EHOSTDOWN
3735 case EHOSTDOWN: return DRMP3_NO_HOST;
3736 #endif
3737 #ifdef EHOSTUNREACH
3738 case EHOSTUNREACH: return DRMP3_NO_HOST;
3739 #endif
3740 #ifdef EALREADY
3741 case EALREADY: return DRMP3_IN_PROGRESS;
3742 #endif
3743 #ifdef EINPROGRESS
3744 case EINPROGRESS: return DRMP3_IN_PROGRESS;
3745 #endif
3746 #ifdef ESTALE
3747 case ESTALE: return DRMP3_INVALID_FILE;
3748 #endif
3749 #ifdef EUCLEAN
3750 case EUCLEAN: return DRMP3_ERROR;
3751 #endif
3752 #ifdef ENOTNAM
3753 case ENOTNAM: return DRMP3_ERROR;
3754 #endif
3755 #ifdef ENAVAIL
3756 case ENAVAIL: return DRMP3_ERROR;
3757 #endif
3758 #ifdef EISNAM
3759 case EISNAM: return DRMP3_ERROR;
3760 #endif
3761 #ifdef EREMOTEIO
3762 case EREMOTEIO: return DRMP3_IO_ERROR;
3763 #endif
3764 #ifdef EDQUOT
3765 case EDQUOT: return DRMP3_NO_SPACE;
3766 #endif
3767 #ifdef ENOMEDIUM
3768 case ENOMEDIUM: return DRMP3_DOES_NOT_EXIST;
3769 #endif
3770 #ifdef EMEDIUMTYPE
3771 case EMEDIUMTYPE: return DRMP3_ERROR;
3772 #endif
3773 #ifdef ECANCELED
3774 case ECANCELED: return DRMP3_CANCELLED;
3775 #endif
3776 #ifdef ENOKEY
3777 case ENOKEY: return DRMP3_ERROR;
3778 #endif
3779 #ifdef EKEYEXPIRED
3780 case EKEYEXPIRED: return DRMP3_ERROR;
3781 #endif
3782 #ifdef EKEYREVOKED
3783 case EKEYREVOKED: return DRMP3_ERROR;
3784 #endif
3785 #ifdef EKEYREJECTED
3786 case EKEYREJECTED: return DRMP3_ERROR;
3787 #endif
3788 #ifdef EOWNERDEAD
3789 case EOWNERDEAD: return DRMP3_ERROR;
3790 #endif
3791 #ifdef ENOTRECOVERABLE
3792 case ENOTRECOVERABLE: return DRMP3_ERROR;
3793 #endif
3794 #ifdef ERFKILL
3795 case ERFKILL: return DRMP3_ERROR;
3796 #endif
3797 #ifdef EHWPOISON
3798 case EHWPOISON: return DRMP3_ERROR;
3799 #endif
3800 default: return DRMP3_ERROR;
3801 }
3802}
3803/* End Errno */
3804
3805/* fopen */
3806static drmp3_result drmp3_fopen(FILE** ppFile, const char* pFilePath, const char* pOpenMode)
3807{
3808#if defined(_MSC_VER) && _MSC_VER >= 1400
3809 errno_t err;
3810#endif
3811
3812 if (ppFile != NULL) {
3813 *ppFile = NULL; /* Safety. */
3814 }
3815
3816 if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
3817 return DRMP3_INVALID_ARGS;
3818 }
3819
3820#if defined(_MSC_VER) && _MSC_VER >= 1400
3821 err = fopen_s(ppFile, pFilePath, pOpenMode);
3822 if (err != 0) {
3823 return drmp3_result_from_errno(err);
3824 }
3825#else
3826#if defined(_WIN32) || defined(__APPLE__)
3827 *ppFile = fopen(pFilePath, pOpenMode);
3828#else
3829 #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64 && defined(_LARGEFILE64_SOURCE)
3830 *ppFile = fopen64(pFilePath, pOpenMode);
3831 #else
3832 *ppFile = fopen(pFilePath, pOpenMode);
3833 #endif
3834#endif
3835 if (*ppFile == NULL) {
3836 drmp3_result result = drmp3_result_from_errno(errno);
3837 if (result == DRMP3_SUCCESS) {
3838 result = DRMP3_ERROR; /* Just a safety check to make sure we never ever return success when pFile == NULL. */
3839 }
3840
3841 return result;
3842 }
3843#endif
3844
3845 return DRMP3_SUCCESS;
3846}
3847
3848/*
3849_wfopen() isn't always available in all compilation environments.
3850
3851 * Windows only.
3852 * MSVC seems to support it universally as far back as VC6 from what I can tell (haven't checked further back).
3853 * MinGW-64 (both 32- and 64-bit) seems to support it.
3854 * MinGW wraps it in !defined(__STRICT_ANSI__).
3855 * OpenWatcom wraps it in !defined(_NO_EXT_KEYS).
3856
3857This can be reviewed as compatibility issues arise. The preference is to use _wfopen_s() and _wfopen() as opposed to the wcsrtombs()
3858fallback, so if you notice your compiler not detecting this properly I'm happy to look at adding support.
3859*/
3860#if defined(_WIN32)
3861 #if defined(_MSC_VER) || defined(__MINGW64__) || (!defined(__STRICT_ANSI__) && !defined(_NO_EXT_KEYS))
3862 #define DRMP3_HAS_WFOPEN
3863 #endif
3864#endif
3865
3866static drmp3_result drmp3_wfopen(FILE** ppFile, const wchar_t* pFilePath, const wchar_t* pOpenMode, const drmp3_allocation_callbacks* pAllocationCallbacks)
3867{
3868 if (ppFile != NULL) {
3869 *ppFile = NULL; /* Safety. */
3870 }
3871
3872 if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
3873 return DRMP3_INVALID_ARGS;
3874 }
3875
3876#if defined(DRMP3_HAS_WFOPEN)
3877 {
3878 /* Use _wfopen() on Windows. */
3879 #if defined(_MSC_VER) && _MSC_VER >= 1400
3880 errno_t err = _wfopen_s(ppFile, pFilePath, pOpenMode);
3881 if (err != 0) {
3882 return drmp3_result_from_errno(err);
3883 }
3884 #else
3885 *ppFile = _wfopen(pFilePath, pOpenMode);
3886 if (*ppFile == NULL) {
3887 return drmp3_result_from_errno(errno);
3888 }
3889 #endif
3890 (void)pAllocationCallbacks;
3891 }
3892#else
3893 /*
3894 Use fopen() on anything other than Windows. Requires a conversion. This is annoying because
3895 fopen() is locale specific. The only real way I can think of to do this is with wcsrtombs(). Note
3896 that wcstombs() is apparently not thread-safe because it uses a static global mbstate_t object for
3897 maintaining state. I've checked this with -std=c89 and it works, but if somebody get's a compiler
3898 error I'll look into improving compatibility.
3899 */
3900
3901 /*
3902 Some compilers don't support wchar_t or wcsrtombs() which we're using below. In this case we just
3903 need to abort with an error. If you encounter a compiler lacking such support, add it to this list
3904 and submit a bug report and it'll be added to the library upstream.
3905 */
3906 #if defined(__DJGPP__)
3907 {
3908 /* Nothing to do here. This will fall through to the error check below. */
3909 }
3910 #else
3911 {
3912 mbstate_t mbs;
3913 size_t lenMB;
3914 const wchar_t* pFilePathTemp = pFilePath;
3915 char* pFilePathMB = NULL;
3916 char pOpenModeMB[32] = {0};
3917
3918 /* Get the length first. */
3919 DRMP3_ZERO_OBJECT(&mbs);
3920 lenMB = wcsrtombs(NULL, &pFilePathTemp, 0, &mbs);
3921 if (lenMB == (size_t)-1) {
3922 return drmp3_result_from_errno(errno);
3923 }
3924
3925 pFilePathMB = (char*)drmp3__malloc_from_callbacks(lenMB + 1, pAllocationCallbacks);
3926 if (pFilePathMB == NULL) {
3927 return DRMP3_OUT_OF_MEMORY;
3928 }
3929
3930 pFilePathTemp = pFilePath;
3931 DRMP3_ZERO_OBJECT(&mbs);
3932 wcsrtombs(pFilePathMB, &pFilePathTemp, lenMB + 1, &mbs);
3933
3934 /* The open mode should always consist of ASCII characters so we should be able to do a trivial conversion. */
3935 {
3936 size_t i = 0;
3937 for (;;) {
3938 if (pOpenMode[i] == 0) {
3939 pOpenModeMB[i] = '\0';
3940 break;
3941 }
3942
3943 pOpenModeMB[i] = (char)pOpenMode[i];
3944 i += 1;
3945 }
3946 }
3947
3948 *ppFile = fopen(pFilePathMB, pOpenModeMB);
3949
3950 drmp3__free_from_callbacks(pFilePathMB, pAllocationCallbacks);
3951 }
3952 #endif
3953
3954 if (*ppFile == NULL) {
3955 return DRMP3_ERROR;
3956 }
3957#endif
3958
3959 return DRMP3_SUCCESS;
3960}
3961/* End fopen */
3962
3963
3964static size_t drmp3__on_read_stdio(void* pUserData, void* pBufferOut, size_t bytesToRead)
3965{
3966 return fread(pBufferOut, 1, bytesToRead, (FILE*)pUserData);
3967}
3968
3969static drmp3_bool32 drmp3__on_seek_stdio(void* pUserData, int offset, drmp3_seek_origin origin)
3970{
3971 int whence = SEEK_SET;
3972 if (origin == drmp3_seek_origin_current) {
3973 whence = SEEK_CUR;
3974 } else if (origin == drmp3_seek_origin_end) {
3975 whence = SEEK_END;
3976 }
3977
3978 return fseek((FILE*)pUserData, offset, whence) == 0;
3979}
3980
3981static drmp3_bool32 drmp3__on_tell_stdio(void* pUserData, drmp3_int64* pCursor)
3982{
3983 FILE* pFileStdio = (FILE*)pUserData;
3984 drmp3_int64 result;
3985
3986 /* These were all validated at a higher level. */
3987 DRMP3_ASSERT(pFileStdio != NULL);
3988 DRMP3_ASSERT(pCursor != NULL);
3989
3990#if defined(_WIN32)
3991 #if defined(_MSC_VER) && _MSC_VER > 1200
3992 result = _ftelli64(pFileStdio);
3993 #else
3994 result = ftell(pFileStdio);
3995 #endif
3996#else
3997 result = ftell(pFileStdio);
3998#endif
3999
4000 *pCursor = result;
4001
4002 return DRMP3_TRUE;
4003}
4004
4005DRMP3_API drmp3_bool32 drmp3_init_file_with_metadata(drmp3* pMP3, const char* pFilePath, drmp3_meta_proc onMeta, void* pUserDataMeta, const drmp3_allocation_callbacks* pAllocationCallbacks)
4006{
4007 drmp3_bool32 result;
4008 FILE* pFile;
4009
4010 if (pMP3 == NULL) {
4011 return DRMP3_FALSE;
4012 }
4013
4014 DRMP3_ZERO_OBJECT(pMP3);
4015
4016 if (drmp3_fopen(&pFile, pFilePath, "rb") != DRMP3_SUCCESS) {
4017 return DRMP3_FALSE;
4018 }
4019
4020 result = drmp3_init_internal(pMP3, drmp3__on_read_stdio, drmp3__on_seek_stdio, drmp3__on_tell_stdio, onMeta, (void*)pFile, pUserDataMeta, pAllocationCallbacks);
4021 if (result != DRMP3_TRUE) {
4022 fclose(pFile);
4023 return result;
4024 }
4025
4026 return DRMP3_TRUE;
4027}
4028
4029DRMP3_API drmp3_bool32 drmp3_init_file_with_metadata_w(drmp3* pMP3, const wchar_t* pFilePath, drmp3_meta_proc onMeta, void* pUserDataMeta, const drmp3_allocation_callbacks* pAllocationCallbacks)
4030{
4031 drmp3_bool32 result;
4032 FILE* pFile;
4033
4034 if (pMP3 == NULL) {
4035 return DRMP3_FALSE;
4036 }
4037
4038 DRMP3_ZERO_OBJECT(pMP3);
4039
4040 if (drmp3_wfopen(&pFile, pFilePath, L"rb", pAllocationCallbacks) != DRMP3_SUCCESS) {
4041 return DRMP3_FALSE;
4042 }
4043
4044 result = drmp3_init_internal(pMP3, drmp3__on_read_stdio, drmp3__on_seek_stdio, drmp3__on_tell_stdio, onMeta, (void*)pFile, pUserDataMeta, pAllocationCallbacks);
4045 if (result != DRMP3_TRUE) {
4046 fclose(pFile);
4047 return result;
4048 }
4049
4050 return DRMP3_TRUE;
4051}
4052
4053DRMP3_API drmp3_bool32 drmp3_init_file(drmp3* pMP3, const char* pFilePath, const drmp3_allocation_callbacks* pAllocationCallbacks)
4054{
4055 return drmp3_init_file_with_metadata(pMP3, pFilePath, NULL, NULL, pAllocationCallbacks);
4056}
4057
4058DRMP3_API drmp3_bool32 drmp3_init_file_w(drmp3* pMP3, const wchar_t* pFilePath, const drmp3_allocation_callbacks* pAllocationCallbacks)
4059{
4060 return drmp3_init_file_with_metadata_w(pMP3, pFilePath, NULL, NULL, pAllocationCallbacks);
4061}
4062#endif
4063
4064DRMP3_API void drmp3_uninit(drmp3* pMP3)
4065{
4066 if (pMP3 == NULL) {
4067 return;
4068 }
4069
4070#ifndef DR_MP3_NO_STDIO
4071 if (pMP3->onRead == drmp3__on_read_stdio) {
4072 FILE* pFile = (FILE*)pMP3->pUserData;
4073 if (pFile != NULL) {
4074 fclose(pFile);
4075 pMP3->pUserData = NULL; /* Make sure the file handle is cleared to NULL to we don't attempt to close it a second time. */
4076 }
4077 }
4078#endif
4079
4080 drmp3__free_from_callbacks(pMP3->pData, &pMP3->allocationCallbacks);
4081}
4082
4083#if defined(DR_MP3_FLOAT_OUTPUT)
4084static void drmp3_f32_to_s16(drmp3_int16* dst, const float* src, drmp3_uint64 sampleCount)
4085{
4086 drmp3_uint64 i;
4087 drmp3_uint64 i4;
4088 drmp3_uint64 sampleCount4;
4089
4090 /* Unrolled. */
4091 i = 0;
4092 sampleCount4 = sampleCount >> 2;
4093 for (i4 = 0; i4 < sampleCount4; i4 += 1) {
4094 float x0 = src[i+0];
4095 float x1 = src[i+1];
4096 float x2 = src[i+2];
4097 float x3 = src[i+3];
4098
4099 x0 = ((x0 < -1) ? -1 : ((x0 > 1) ? 1 : x0));
4100 x1 = ((x1 < -1) ? -1 : ((x1 > 1) ? 1 : x1));
4101 x2 = ((x2 < -1) ? -1 : ((x2 > 1) ? 1 : x2));
4102 x3 = ((x3 < -1) ? -1 : ((x3 > 1) ? 1 : x3));
4103
4104 x0 = x0 * 32767.0f;
4105 x1 = x1 * 32767.0f;
4106 x2 = x2 * 32767.0f;
4107 x3 = x3 * 32767.0f;
4108
4109 dst[i+0] = (drmp3_int16)x0;
4110 dst[i+1] = (drmp3_int16)x1;
4111 dst[i+2] = (drmp3_int16)x2;
4112 dst[i+3] = (drmp3_int16)x3;
4113
4114 i += 4;
4115 }
4116
4117 /* Leftover. */
4118 for (; i < sampleCount; i += 1) {
4119 float x = src[i];
4120 x = ((x < -1) ? -1 : ((x > 1) ? 1 : x)); /* clip */
4121 x = x * 32767.0f; /* -1..1 to -32767..32767 */
4122
4123 dst[i] = (drmp3_int16)x;
4124 }
4125}
4126#endif
4127
4128#if !defined(DR_MP3_FLOAT_OUTPUT)
4129static void drmp3_s16_to_f32(float* dst, const drmp3_int16* src, drmp3_uint64 sampleCount)
4130{
4131 drmp3_uint64 i;
4132 for (i = 0; i < sampleCount; i += 1) {
4133 float x = (float)src[i];
4134 x = x * 0.000030517578125f; /* -32768..32767 to -1..0.999969482421875 */
4135 dst[i] = x;
4136 }
4137}
4138#endif
4139
4140
4141static drmp3_uint64 drmp3_read_pcm_frames_raw(drmp3* pMP3, drmp3_uint64 framesToRead, void* pBufferOut)
4142{
4143 drmp3_uint64 totalFramesRead = 0;
4144
4145 DRMP3_ASSERT(pMP3 != NULL);
4146 DRMP3_ASSERT(pMP3->onRead != NULL);
4147
4148 while (framesToRead > 0) {
4149 drmp3_uint32 framesToConsume;
4150
4151 /* Skip frames if necessary. */
4152 if (pMP3->currentPCMFrame < pMP3->delayInPCMFrames) {
4153 drmp3_uint32 framesToSkip = (drmp3_uint32)DRMP3_MIN(pMP3->pcmFramesRemainingInMP3Frame, pMP3->delayInPCMFrames - pMP3->currentPCMFrame);
4154
4155 pMP3->currentPCMFrame += framesToSkip;
4156 pMP3->pcmFramesConsumedInMP3Frame += framesToSkip;
4157 pMP3->pcmFramesRemainingInMP3Frame -= framesToSkip;
4158 }
4159
4160 framesToConsume = (drmp3_uint32)DRMP3_MIN(pMP3->pcmFramesRemainingInMP3Frame, framesToRead);
4161
4162 /* Clamp the number of frames to read to the padding. */
4164 if (pMP3->currentPCMFrame < (pMP3->totalPCMFrameCount - pMP3->paddingInPCMFrames)) {
4165 drmp3_uint64 framesRemainigToPadding = (pMP3->totalPCMFrameCount - pMP3->paddingInPCMFrames) - pMP3->currentPCMFrame;
4166 if (framesToConsume > framesRemainigToPadding) {
4167 framesToConsume = (drmp3_uint32)framesRemainigToPadding;
4168 }
4169 } else {
4170 /* We're into the padding. Abort. */
4171 break;
4172 }
4173 }
4174
4175 if (pBufferOut != NULL) {
4176 #if defined(DR_MP3_FLOAT_OUTPUT)
4177 {
4178 /* f32 */
4179 float* pFramesOutF32 = (float*)DRMP3_OFFSET_PTR(pBufferOut, sizeof(float) * totalFramesRead * pMP3->channels);
4180 float* pFramesInF32 = (float*)DRMP3_OFFSET_PTR(&pMP3->pcmFrames[0], sizeof(float) * pMP3->pcmFramesConsumedInMP3Frame * pMP3->mp3FrameChannels);
4181 DRMP3_COPY_MEMORY(pFramesOutF32, pFramesInF32, sizeof(float) * framesToConsume * pMP3->channels);
4182 }
4183 #else
4184 {
4185 /* s16 */
4186 drmp3_int16* pFramesOutS16 = (drmp3_int16*)DRMP3_OFFSET_PTR(pBufferOut, sizeof(drmp3_int16) * totalFramesRead * pMP3->channels);
4187 drmp3_int16* pFramesInS16 = (drmp3_int16*)DRMP3_OFFSET_PTR(&pMP3->pcmFrames[0], sizeof(drmp3_int16) * pMP3->pcmFramesConsumedInMP3Frame * pMP3->mp3FrameChannels);
4188 DRMP3_COPY_MEMORY(pFramesOutS16, pFramesInS16, sizeof(drmp3_int16) * framesToConsume * pMP3->channels);
4189 }
4190 #endif
4191 }
4192
4193 pMP3->currentPCMFrame += framesToConsume;
4194 pMP3->pcmFramesConsumedInMP3Frame += framesToConsume;
4195 pMP3->pcmFramesRemainingInMP3Frame -= framesToConsume;
4196 totalFramesRead += framesToConsume;
4197 framesToRead -= framesToConsume;
4198
4199 if (framesToRead == 0) {
4200 break;
4201 }
4202
4203 /* If the cursor is already at the padding we need to abort. */
4205 break;
4206 }
4207
4208 DRMP3_ASSERT(pMP3->pcmFramesRemainingInMP3Frame == 0);
4209
4210 /* At this point we have exhausted our in-memory buffer so we need to re-fill. */
4211 if (drmp3_decode_next_frame(pMP3) == 0) {
4212 break;
4213 }
4214 }
4215
4216 return totalFramesRead;
4217}
4218
4219
4220DRMP3_API drmp3_uint64 drmp3_read_pcm_frames_f32(drmp3* pMP3, drmp3_uint64 framesToRead, float* pBufferOut)
4221{
4222 if (pMP3 == NULL || pMP3->onRead == NULL) {
4223 return 0;
4224 }
4225
4226#if defined(DR_MP3_FLOAT_OUTPUT)
4227 /* Fast path. No conversion required. */
4228 return drmp3_read_pcm_frames_raw(pMP3, framesToRead, pBufferOut);
4229#else
4230 /* Slow path. Convert from s16 to f32. */
4231 {
4232 drmp3_int16 pTempS16[8192];
4233 drmp3_uint64 totalPCMFramesRead = 0;
4234
4235 while (totalPCMFramesRead < framesToRead) {
4236 drmp3_uint64 framesJustRead;
4237 drmp3_uint64 framesRemaining = framesToRead - totalPCMFramesRead;
4238 drmp3_uint64 framesToReadNow = DRMP3_COUNTOF(pTempS16) / pMP3->channels;
4239 if (framesToReadNow > framesRemaining) {
4240 framesToReadNow = framesRemaining;
4241 }
4242
4243 framesJustRead = drmp3_read_pcm_frames_raw(pMP3, framesToReadNow, pTempS16);
4244 if (framesJustRead == 0) {
4245 break;
4246 }
4247
4248 drmp3_s16_to_f32((float*)DRMP3_OFFSET_PTR(pBufferOut, sizeof(float) * totalPCMFramesRead * pMP3->channels), pTempS16, framesJustRead * pMP3->channels);
4249 totalPCMFramesRead += framesJustRead;
4250 }
4251
4252 return totalPCMFramesRead;
4253 }
4254#endif
4255}
4256
4258{
4259 if (pMP3 == NULL || pMP3->onRead == NULL) {
4260 return 0;
4261 }
4262
4263#if !defined(DR_MP3_FLOAT_OUTPUT)
4264 /* Fast path. No conversion required. */
4265 return drmp3_read_pcm_frames_raw(pMP3, framesToRead, pBufferOut);
4266#else
4267 /* Slow path. Convert from f32 to s16. */
4268 {
4269 float pTempF32[4096];
4270 drmp3_uint64 totalPCMFramesRead = 0;
4271
4272 while (totalPCMFramesRead < framesToRead) {
4273 drmp3_uint64 framesJustRead;
4274 drmp3_uint64 framesRemaining = framesToRead - totalPCMFramesRead;
4275 drmp3_uint64 framesToReadNow = DRMP3_COUNTOF(pTempF32) / pMP3->channels;
4276 if (framesToReadNow > framesRemaining) {
4277 framesToReadNow = framesRemaining;
4278 }
4279
4280 framesJustRead = drmp3_read_pcm_frames_raw(pMP3, framesToReadNow, pTempF32);
4281 if (framesJustRead == 0) {
4282 break;
4283 }
4284
4285 drmp3_f32_to_s16((drmp3_int16*)DRMP3_OFFSET_PTR(pBufferOut, sizeof(drmp3_int16) * totalPCMFramesRead * pMP3->channels), pTempF32, framesJustRead * pMP3->channels);
4286 totalPCMFramesRead += framesJustRead;
4287 }
4288
4289 return totalPCMFramesRead;
4290 }
4291#endif
4292}
4293
4294static void drmp3_reset(drmp3* pMP3)
4295{
4296 DRMP3_ASSERT(pMP3 != NULL);
4297
4300 pMP3->currentPCMFrame = 0;
4301 pMP3->dataSize = 0;
4302 pMP3->atEnd = DRMP3_FALSE;
4303 drmp3dec_init(&pMP3->decoder);
4304}
4305
4306static drmp3_bool32 drmp3_seek_to_start_of_stream(drmp3* pMP3)
4307{
4308 DRMP3_ASSERT(pMP3 != NULL);
4309 DRMP3_ASSERT(pMP3->onSeek != NULL);
4310
4311 /* Seek to the start of the stream to begin with. */
4312 if (!drmp3__on_seek_64(pMP3, pMP3->streamStartOffset, drmp3_seek_origin_start)) {
4313 return DRMP3_FALSE;
4314 }
4315
4316 /* Clear any cached data. */
4317 drmp3_reset(pMP3);
4318 return DRMP3_TRUE;
4319}
4320
4321
4322static drmp3_bool32 drmp3_seek_forward_by_pcm_frames__brute_force(drmp3* pMP3, drmp3_uint64 frameOffset)
4323{
4324 drmp3_uint64 framesRead;
4325
4326 /*
4327 Just using a dumb read-and-discard for now. What would be nice is to parse only the header of the MP3 frame, and then skip over leading
4328 frames without spending the time doing a full decode. I cannot see an easy way to do this in minimp3, however, so it may involve some
4329 kind of manual processing.
4330 */
4331#if defined(DR_MP3_FLOAT_OUTPUT)
4332 framesRead = drmp3_read_pcm_frames_f32(pMP3, frameOffset, NULL);
4333#else
4334 framesRead = drmp3_read_pcm_frames_s16(pMP3, frameOffset, NULL);
4335#endif
4336 if (framesRead != frameOffset) {
4337 return DRMP3_FALSE;
4338 }
4339
4340 return DRMP3_TRUE;
4341}
4342
4343static drmp3_bool32 drmp3_seek_to_pcm_frame__brute_force(drmp3* pMP3, drmp3_uint64 frameIndex)
4344{
4345 DRMP3_ASSERT(pMP3 != NULL);
4346
4347 if (frameIndex == pMP3->currentPCMFrame) {
4348 return DRMP3_TRUE;
4349 }
4350
4351 /*
4352 If we're moving foward we just read from where we're at. Otherwise we need to move back to the start of
4353 the stream and read from the beginning.
4354 */
4355 if (frameIndex < pMP3->currentPCMFrame) {
4356 /* Moving backward. Move to the start of the stream and then move forward. */
4357 if (!drmp3_seek_to_start_of_stream(pMP3)) {
4358 return DRMP3_FALSE;
4359 }
4360 }
4361
4362 DRMP3_ASSERT(frameIndex >= pMP3->currentPCMFrame);
4363 return drmp3_seek_forward_by_pcm_frames__brute_force(pMP3, (frameIndex - pMP3->currentPCMFrame));
4364}
4365
4366static drmp3_bool32 drmp3_find_closest_seek_point(drmp3* pMP3, drmp3_uint64 frameIndex, drmp3_uint32* pSeekPointIndex)
4367{
4368 drmp3_uint32 iSeekPoint;
4369
4370 DRMP3_ASSERT(pSeekPointIndex != NULL);
4371
4372 *pSeekPointIndex = 0;
4373
4374 if (frameIndex < pMP3->pSeekPoints[0].pcmFrameIndex) {
4375 return DRMP3_FALSE;
4376 }
4377
4378 /* Linear search for simplicity to begin with while I'm getting this thing working. Once it's all working change this to a binary search. */
4379 for (iSeekPoint = 0; iSeekPoint < pMP3->seekPointCount; ++iSeekPoint) {
4380 if (pMP3->pSeekPoints[iSeekPoint].pcmFrameIndex > frameIndex) {
4381 break; /* Found it. */
4382 }
4383
4384 *pSeekPointIndex = iSeekPoint;
4385 }
4386
4387 return DRMP3_TRUE;
4388}
4389
4390static drmp3_bool32 drmp3_seek_to_pcm_frame__seek_table(drmp3* pMP3, drmp3_uint64 frameIndex)
4391{
4392 drmp3_seek_point seekPoint;
4393 drmp3_uint32 priorSeekPointIndex;
4394 drmp3_uint16 iMP3Frame;
4395 drmp3_uint64 leftoverFrames;
4396
4397 DRMP3_ASSERT(pMP3 != NULL);
4398 DRMP3_ASSERT(pMP3->pSeekPoints != NULL);
4399 DRMP3_ASSERT(pMP3->seekPointCount > 0);
4400
4401 /* If there is no prior seekpoint it means the target PCM frame comes before the first seek point. Just assume a seekpoint at the start of the file in this case. */
4402 if (drmp3_find_closest_seek_point(pMP3, frameIndex, &priorSeekPointIndex)) {
4403 seekPoint = pMP3->pSeekPoints[priorSeekPointIndex];
4404 } else {
4405 seekPoint.seekPosInBytes = 0;
4406 seekPoint.pcmFrameIndex = 0;
4407 seekPoint.mp3FramesToDiscard = 0;
4408 seekPoint.pcmFramesToDiscard = 0;
4409 }
4410
4411 /* First thing to do is seek to the first byte of the relevant MP3 frame. */
4412 if (!drmp3__on_seek_64(pMP3, seekPoint.seekPosInBytes, drmp3_seek_origin_start)) {
4413 return DRMP3_FALSE; /* Failed to seek. */
4414 }
4415
4416 /* Clear any cached data. */
4417 drmp3_reset(pMP3);
4418
4419 /* Whole MP3 frames need to be discarded first. */
4420 for (iMP3Frame = 0; iMP3Frame < seekPoint.mp3FramesToDiscard; ++iMP3Frame) {
4421 drmp3_uint32 pcmFramesRead;
4422 drmp3d_sample_t* pPCMFrames;
4423
4424 /* Pass in non-null for the last frame because we want to ensure the sample rate converter is preloaded correctly. */
4425 pPCMFrames = NULL;
4426 if (iMP3Frame == seekPoint.mp3FramesToDiscard-1) {
4427 pPCMFrames = (drmp3d_sample_t*)pMP3->pcmFrames;
4428 }
4429
4430 /* We first need to decode the next frame. */
4431 pcmFramesRead = drmp3_decode_next_frame_ex(pMP3, pPCMFrames, NULL, NULL);
4432 if (pcmFramesRead == 0) {
4433 return DRMP3_FALSE;
4434 }
4435 }
4436
4437 /* We seeked to an MP3 frame in the raw stream so we need to make sure the current PCM frame is set correctly. */
4438 pMP3->currentPCMFrame = seekPoint.pcmFrameIndex - seekPoint.pcmFramesToDiscard;
4439
4440 /*
4441 Now at this point we can follow the same process as the brute force technique where we just skip over unnecessary MP3 frames and then
4442 read-and-discard at least 2 whole MP3 frames.
4443 */
4444 leftoverFrames = frameIndex - pMP3->currentPCMFrame;
4445 return drmp3_seek_forward_by_pcm_frames__brute_force(pMP3, leftoverFrames);
4446}
4447
4449{
4450 if (pMP3 == NULL || pMP3->onSeek == NULL) {
4451 return DRMP3_FALSE;
4452 }
4453
4454 if (frameIndex == 0) {
4455 return drmp3_seek_to_start_of_stream(pMP3);
4456 }
4457
4458 /* Use the seek table if we have one. */
4459 if (pMP3->pSeekPoints != NULL && pMP3->seekPointCount > 0) {
4460 return drmp3_seek_to_pcm_frame__seek_table(pMP3, frameIndex);
4461 } else {
4462 return drmp3_seek_to_pcm_frame__brute_force(pMP3, frameIndex);
4463 }
4464}
4465
4467{
4468 drmp3_uint64 currentPCMFrame;
4469 drmp3_uint64 totalPCMFrameCount;
4470 drmp3_uint64 totalMP3FrameCount;
4471
4472 if (pMP3 == NULL) {
4473 return DRMP3_FALSE;
4474 }
4475
4476 /*
4477 The way this works is we move back to the start of the stream, iterate over each MP3 frame and calculate the frame count based
4478 on our output sample rate, the seek back to the PCM frame we were sitting on before calling this function.
4479 */
4480
4481 /* The stream must support seeking for this to work. */
4482 if (pMP3->onSeek == NULL) {
4483 return DRMP3_FALSE;
4484 }
4485
4486 /* We'll need to seek back to where we were, so grab the PCM frame we're currently sitting on so we can restore later. */
4487 currentPCMFrame = pMP3->currentPCMFrame;
4488
4489 if (!drmp3_seek_to_start_of_stream(pMP3)) {
4490 return DRMP3_FALSE;
4491 }
4492
4493 totalPCMFrameCount = 0;
4494 totalMP3FrameCount = 0;
4495
4496 for (;;) {
4497 drmp3_uint32 pcmFramesInCurrentMP3Frame;
4498
4499 pcmFramesInCurrentMP3Frame = drmp3_decode_next_frame_ex(pMP3, NULL, NULL, NULL);
4500 if (pcmFramesInCurrentMP3Frame == 0) {
4501 break;
4502 }
4503
4504 totalPCMFrameCount += pcmFramesInCurrentMP3Frame;
4505 totalMP3FrameCount += 1;
4506 }
4507
4508 /* Finally, we need to seek back to where we were. */
4509 if (!drmp3_seek_to_start_of_stream(pMP3)) {
4510 return DRMP3_FALSE;
4511 }
4512
4513 if (!drmp3_seek_to_pcm_frame(pMP3, currentPCMFrame)) {
4514 return DRMP3_FALSE;
4515 }
4516
4517 if (pMP3FrameCount != NULL) {
4518 *pMP3FrameCount = totalMP3FrameCount;
4519 }
4520 if (pPCMFrameCount != NULL) {
4521 *pPCMFrameCount = totalPCMFrameCount;
4522 }
4523
4524 return DRMP3_TRUE;
4525}
4526
4528{
4529 drmp3_uint64 totalPCMFrameCount;
4530
4531 if (pMP3 == NULL) {
4532 return 0;
4533 }
4534
4535 if (pMP3->totalPCMFrameCount != DRMP3_UINT64_MAX) {
4536 totalPCMFrameCount = pMP3->totalPCMFrameCount;
4537
4538 if (totalPCMFrameCount >= pMP3->delayInPCMFrames) {
4539 totalPCMFrameCount -= pMP3->delayInPCMFrames;
4540 } else {
4541 /* The delay is greater than the frame count reported by the Xing/Info tag. Assume it's invalid and ignore. */
4542 }
4543
4544 if (totalPCMFrameCount >= pMP3->paddingInPCMFrames) {
4545 totalPCMFrameCount -= pMP3->paddingInPCMFrames;
4546 } else {
4547 /* The padding is greater than the frame count reported by the Xing/Info tag. Assume it's invalid and ignore. */
4548 }
4549
4550 return totalPCMFrameCount;
4551 } else {
4552 /* Unknown frame count. Need to calculate it. */
4553 if (!drmp3_get_mp3_and_pcm_frame_count(pMP3, NULL, &totalPCMFrameCount)) {
4554 return 0;
4555 }
4556
4557 return totalPCMFrameCount;
4558 }
4559}
4560
4562{
4563 drmp3_uint64 totalMP3FrameCount;
4564 if (!drmp3_get_mp3_and_pcm_frame_count(pMP3, &totalMP3FrameCount, NULL)) {
4565 return 0;
4566 }
4567
4568 return totalMP3FrameCount;
4569}
4570
4571static void drmp3__accumulate_running_pcm_frame_count(drmp3* pMP3, drmp3_uint32 pcmFrameCountIn, drmp3_uint64* pRunningPCMFrameCount, float* pRunningPCMFrameCountFractionalPart)
4572{
4573 float srcRatio;
4574 float pcmFrameCountOutF;
4575 drmp3_uint32 pcmFrameCountOut;
4576
4577 srcRatio = (float)pMP3->mp3FrameSampleRate / (float)pMP3->sampleRate;
4578 DRMP3_ASSERT(srcRatio > 0);
4579
4580 pcmFrameCountOutF = *pRunningPCMFrameCountFractionalPart + (pcmFrameCountIn / srcRatio);
4581 pcmFrameCountOut = (drmp3_uint32)pcmFrameCountOutF;
4582 *pRunningPCMFrameCountFractionalPart = pcmFrameCountOutF - pcmFrameCountOut;
4583 *pRunningPCMFrameCount += pcmFrameCountOut;
4584}
4585
4586typedef struct
4587{
4588 drmp3_uint64 bytePos;
4589 drmp3_uint64 pcmFrameIndex; /* <-- After sample rate conversion. */
4590} drmp3__seeking_mp3_frame_info;
4591
4593{
4594 drmp3_uint32 seekPointCount;
4595 drmp3_uint64 currentPCMFrame;
4596 drmp3_uint64 totalMP3FrameCount;
4597 drmp3_uint64 totalPCMFrameCount;
4598
4599 if (pMP3 == NULL || pSeekPointCount == NULL || pSeekPoints == NULL) {
4600 return DRMP3_FALSE; /* Invalid args. */
4601 }
4602
4603 seekPointCount = *pSeekPointCount;
4604 if (seekPointCount == 0) {
4605 return DRMP3_FALSE; /* The client has requested no seek points. Consider this to be invalid arguments since the client has probably not intended this. */
4606 }
4607
4608 /* We'll need to seek back to the current sample after calculating the seekpoints so we need to go ahead and grab the current location at the top. */
4609 currentPCMFrame = pMP3->currentPCMFrame;
4610
4611 /* We never do more than the total number of MP3 frames and we limit it to 32-bits. */
4612 if (!drmp3_get_mp3_and_pcm_frame_count(pMP3, &totalMP3FrameCount, &totalPCMFrameCount)) {
4613 return DRMP3_FALSE;
4614 }
4615
4616 /* If there's less than DRMP3_SEEK_LEADING_MP3_FRAMES+1 frames we just report 1 seek point which will be the very start of the stream. */
4617 if (totalMP3FrameCount < DRMP3_SEEK_LEADING_MP3_FRAMES+1) {
4618 seekPointCount = 1;
4619 pSeekPoints[0].seekPosInBytes = 0;
4620 pSeekPoints[0].pcmFrameIndex = 0;
4621 pSeekPoints[0].mp3FramesToDiscard = 0;
4622 pSeekPoints[0].pcmFramesToDiscard = 0;
4623 } else {
4624 drmp3_uint64 pcmFramesBetweenSeekPoints;
4625 drmp3__seeking_mp3_frame_info mp3FrameInfo[DRMP3_SEEK_LEADING_MP3_FRAMES+1];
4626 drmp3_uint64 runningPCMFrameCount = 0;
4627 float runningPCMFrameCountFractionalPart = 0;
4628 drmp3_uint64 nextTargetPCMFrame;
4629 drmp3_uint32 iMP3Frame;
4630 drmp3_uint32 iSeekPoint;
4631
4632 if (seekPointCount > totalMP3FrameCount-1) {
4633 seekPointCount = (drmp3_uint32)totalMP3FrameCount-1;
4634 }
4635
4636 pcmFramesBetweenSeekPoints = totalPCMFrameCount / (seekPointCount+1);
4637
4638 /*
4639 Here is where we actually calculate the seek points. We need to start by moving the start of the stream. We then enumerate over each
4640 MP3 frame.
4641 */
4642 if (!drmp3_seek_to_start_of_stream(pMP3)) {
4643 return DRMP3_FALSE;
4644 }
4645
4646 /*
4647 We need to cache the byte positions of the previous MP3 frames. As a new MP3 frame is iterated, we cycle the byte positions in this
4648 array. The value in the first item in this array is the byte position that will be reported in the next seek point.
4649 */
4650
4651 /* We need to initialize the array of MP3 byte positions for the leading MP3 frames. */
4652 for (iMP3Frame = 0; iMP3Frame < DRMP3_SEEK_LEADING_MP3_FRAMES+1; ++iMP3Frame) {
4653 drmp3_uint32 pcmFramesInCurrentMP3FrameIn;
4654
4655 /* The byte position of the next frame will be the stream's cursor position, minus whatever is sitting in the buffer. */
4656 DRMP3_ASSERT(pMP3->streamCursor >= pMP3->dataSize);
4657 mp3FrameInfo[iMP3Frame].bytePos = pMP3->streamCursor - pMP3->dataSize;
4658 mp3FrameInfo[iMP3Frame].pcmFrameIndex = runningPCMFrameCount;
4659
4660 /* We need to get information about this frame so we can know how many samples it contained. */
4661 pcmFramesInCurrentMP3FrameIn = drmp3_decode_next_frame_ex(pMP3, NULL, NULL, NULL);
4662 if (pcmFramesInCurrentMP3FrameIn == 0) {
4663 return DRMP3_FALSE; /* This should never happen. */
4664 }
4665
4666 drmp3__accumulate_running_pcm_frame_count(pMP3, pcmFramesInCurrentMP3FrameIn, &runningPCMFrameCount, &runningPCMFrameCountFractionalPart);
4667 }
4668
4669 /*
4670 At this point we will have extracted the byte positions of the leading MP3 frames. We can now start iterating over each seek point and
4671 calculate them.
4672 */
4673 nextTargetPCMFrame = 0;
4674 for (iSeekPoint = 0; iSeekPoint < seekPointCount; ++iSeekPoint) {
4675 nextTargetPCMFrame += pcmFramesBetweenSeekPoints;
4676
4677 for (;;) {
4678 if (nextTargetPCMFrame < runningPCMFrameCount) {
4679 /* The next seek point is in the current MP3 frame. */
4680 pSeekPoints[iSeekPoint].seekPosInBytes = mp3FrameInfo[0].bytePos;
4681 pSeekPoints[iSeekPoint].pcmFrameIndex = nextTargetPCMFrame;
4682 pSeekPoints[iSeekPoint].mp3FramesToDiscard = DRMP3_SEEK_LEADING_MP3_FRAMES;
4683 pSeekPoints[iSeekPoint].pcmFramesToDiscard = (drmp3_uint16)(nextTargetPCMFrame - mp3FrameInfo[DRMP3_SEEK_LEADING_MP3_FRAMES-1].pcmFrameIndex);
4684 break;
4685 } else {
4686 size_t i;
4687 drmp3_uint32 pcmFramesInCurrentMP3FrameIn;
4688
4689 /*
4690 The next seek point is not in the current MP3 frame, so continue on to the next one. The first thing to do is cycle the cached
4691 MP3 frame info.
4692 */
4693 for (i = 0; i < DRMP3_COUNTOF(mp3FrameInfo)-1; ++i) {
4694 mp3FrameInfo[i] = mp3FrameInfo[i+1];
4695 }
4696
4697 /* Cache previous MP3 frame info. */
4698 mp3FrameInfo[DRMP3_COUNTOF(mp3FrameInfo)-1].bytePos = pMP3->streamCursor - pMP3->dataSize;
4699 mp3FrameInfo[DRMP3_COUNTOF(mp3FrameInfo)-1].pcmFrameIndex = runningPCMFrameCount;
4700
4701 /*
4702 Go to the next MP3 frame. This shouldn't ever fail, but just in case it does we just set the seek point and break. If it happens, it
4703 should only ever do it for the last seek point.
4704 */
4705 pcmFramesInCurrentMP3FrameIn = drmp3_decode_next_frame_ex(pMP3, NULL, NULL, NULL);
4706 if (pcmFramesInCurrentMP3FrameIn == 0) {
4707 pSeekPoints[iSeekPoint].seekPosInBytes = mp3FrameInfo[0].bytePos;
4708 pSeekPoints[iSeekPoint].pcmFrameIndex = nextTargetPCMFrame;
4709 pSeekPoints[iSeekPoint].mp3FramesToDiscard = DRMP3_SEEK_LEADING_MP3_FRAMES;
4710 pSeekPoints[iSeekPoint].pcmFramesToDiscard = (drmp3_uint16)(nextTargetPCMFrame - mp3FrameInfo[DRMP3_SEEK_LEADING_MP3_FRAMES-1].pcmFrameIndex);
4711 break;
4712 }
4713
4714 drmp3__accumulate_running_pcm_frame_count(pMP3, pcmFramesInCurrentMP3FrameIn, &runningPCMFrameCount, &runningPCMFrameCountFractionalPart);
4715 }
4716 }
4717 }
4718
4719 /* Finally, we need to seek back to where we were. */
4720 if (!drmp3_seek_to_start_of_stream(pMP3)) {
4721 return DRMP3_FALSE;
4722 }
4723 if (!drmp3_seek_to_pcm_frame(pMP3, currentPCMFrame)) {
4724 return DRMP3_FALSE;
4725 }
4726 }
4727
4728 *pSeekPointCount = seekPointCount;
4729 return DRMP3_TRUE;
4730}
4731
4733{
4734 if (pMP3 == NULL) {
4735 return DRMP3_FALSE;
4736 }
4737
4738 if (seekPointCount == 0 || pSeekPoints == NULL) {
4739 /* Unbinding. */
4740 pMP3->seekPointCount = 0;
4741 pMP3->pSeekPoints = NULL;
4742 } else {
4743 /* Binding. */
4744 pMP3->seekPointCount = seekPointCount;
4745 pMP3->pSeekPoints = pSeekPoints;
4746 }
4747
4748 return DRMP3_TRUE;
4749}
4750
4751
4752static float* drmp3__full_read_and_close_f32(drmp3* pMP3, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount)
4753{
4754 drmp3_uint64 totalFramesRead = 0;
4755 drmp3_uint64 framesCapacity = 0;
4756 float* pFrames = NULL;
4757 float temp[4096];
4758
4759 DRMP3_ASSERT(pMP3 != NULL);
4760
4761 for (;;) {
4762 drmp3_uint64 framesToReadRightNow = DRMP3_COUNTOF(temp) / pMP3->channels;
4763 drmp3_uint64 framesJustRead = drmp3_read_pcm_frames_f32(pMP3, framesToReadRightNow, temp);
4764 if (framesJustRead == 0) {
4765 break;
4766 }
4767
4768 /* Reallocate the output buffer if there's not enough room. */
4769 if (framesCapacity < totalFramesRead + framesJustRead) {
4770 drmp3_uint64 oldFramesBufferSize;
4771 drmp3_uint64 newFramesBufferSize;
4772 drmp3_uint64 newFramesCap;
4773 float* pNewFrames;
4774
4775 newFramesCap = framesCapacity * 2;
4776 if (newFramesCap < totalFramesRead + framesJustRead) {
4777 newFramesCap = totalFramesRead + framesJustRead;
4778 }
4779
4780 oldFramesBufferSize = framesCapacity * pMP3->channels * sizeof(float);
4781 newFramesBufferSize = newFramesCap * pMP3->channels * sizeof(float);
4782 if (newFramesBufferSize > (drmp3_uint64)DRMP3_SIZE_MAX) {
4783 break;
4784 }
4785
4786 pNewFrames = (float*)drmp3__realloc_from_callbacks(pFrames, (size_t)newFramesBufferSize, (size_t)oldFramesBufferSize, &pMP3->allocationCallbacks);
4787 if (pNewFrames == NULL) {
4788 drmp3__free_from_callbacks(pFrames, &pMP3->allocationCallbacks);
4789 break;
4790 }
4791
4792 pFrames = pNewFrames;
4793 framesCapacity = newFramesCap;
4794 }
4795
4796 DRMP3_COPY_MEMORY(pFrames + totalFramesRead*pMP3->channels, temp, (size_t)(framesJustRead*pMP3->channels*sizeof(float)));
4797 totalFramesRead += framesJustRead;
4798
4799 /* If the number of frames we asked for is less that what we actually read it means we've reached the end. */
4800 if (framesJustRead != framesToReadRightNow) {
4801 break;
4802 }
4803 }
4804
4805 if (pConfig != NULL) {
4806 pConfig->channels = pMP3->channels;
4807 pConfig->sampleRate = pMP3->sampleRate;
4808 }
4809
4810 drmp3_uninit(pMP3);
4811
4812 if (pTotalFrameCount) {
4813 *pTotalFrameCount = totalFramesRead;
4814 }
4815
4816 return pFrames;
4817}
4818
4819static drmp3_int16* drmp3__full_read_and_close_s16(drmp3* pMP3, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount)
4820{
4821 drmp3_uint64 totalFramesRead = 0;
4822 drmp3_uint64 framesCapacity = 0;
4823 drmp3_int16* pFrames = NULL;
4824 drmp3_int16 temp[4096];
4825
4826 DRMP3_ASSERT(pMP3 != NULL);
4827
4828 for (;;) {
4829 drmp3_uint64 framesToReadRightNow = DRMP3_COUNTOF(temp) / pMP3->channels;
4830 drmp3_uint64 framesJustRead = drmp3_read_pcm_frames_s16(pMP3, framesToReadRightNow, temp);
4831 if (framesJustRead == 0) {
4832 break;
4833 }
4834
4835 /* Reallocate the output buffer if there's not enough room. */
4836 if (framesCapacity < totalFramesRead + framesJustRead) {
4837 drmp3_uint64 newFramesBufferSize;
4838 drmp3_uint64 oldFramesBufferSize;
4839 drmp3_uint64 newFramesCap;
4840 drmp3_int16* pNewFrames;
4841
4842 newFramesCap = framesCapacity * 2;
4843 if (newFramesCap < totalFramesRead + framesJustRead) {
4844 newFramesCap = totalFramesRead + framesJustRead;
4845 }
4846
4847 oldFramesBufferSize = framesCapacity * pMP3->channels * sizeof(drmp3_int16);
4848 newFramesBufferSize = newFramesCap * pMP3->channels * sizeof(drmp3_int16);
4849 if (newFramesBufferSize > (drmp3_uint64)DRMP3_SIZE_MAX) {
4850 break;
4851 }
4852
4853 pNewFrames = (drmp3_int16*)drmp3__realloc_from_callbacks(pFrames, (size_t)newFramesBufferSize, (size_t)oldFramesBufferSize, &pMP3->allocationCallbacks);
4854 if (pNewFrames == NULL) {
4855 drmp3__free_from_callbacks(pFrames, &pMP3->allocationCallbacks);
4856 break;
4857 }
4858
4859 pFrames = pNewFrames;
4860 framesCapacity = newFramesCap;
4861 }
4862
4863 DRMP3_COPY_MEMORY(pFrames + totalFramesRead*pMP3->channels, temp, (size_t)(framesJustRead*pMP3->channels*sizeof(drmp3_int16)));
4864 totalFramesRead += framesJustRead;
4865
4866 /* If the number of frames we asked for is less that what we actually read it means we've reached the end. */
4867 if (framesJustRead != framesToReadRightNow) {
4868 break;
4869 }
4870 }
4871
4872 if (pConfig != NULL) {
4873 pConfig->channels = pMP3->channels;
4874 pConfig->sampleRate = pMP3->sampleRate;
4875 }
4876
4877 drmp3_uninit(pMP3);
4878
4879 if (pTotalFrameCount) {
4880 *pTotalFrameCount = totalFramesRead;
4881 }
4882
4883 return pFrames;
4884}
4885
4886
4887DRMP3_API float* drmp3_open_and_read_pcm_frames_f32(drmp3_read_proc onRead, drmp3_seek_proc onSeek, drmp3_tell_proc onTell, void* pUserData, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks)
4888{
4889 drmp3 mp3;
4890 if (!drmp3_init(&mp3, onRead, onSeek, onTell, NULL, pUserData, pAllocationCallbacks)) {
4891 return NULL;
4892 }
4893
4894 return drmp3__full_read_and_close_f32(&mp3, pConfig, pTotalFrameCount);
4895}
4896
4897DRMP3_API drmp3_int16* drmp3_open_and_read_pcm_frames_s16(drmp3_read_proc onRead, drmp3_seek_proc onSeek, drmp3_tell_proc onTell, void* pUserData, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks)
4898{
4899 drmp3 mp3;
4900 if (!drmp3_init(&mp3, onRead, onSeek, onTell, NULL, pUserData, pAllocationCallbacks)) {
4901 return NULL;
4902 }
4903
4904 return drmp3__full_read_and_close_s16(&mp3, pConfig, pTotalFrameCount);
4905}
4906
4907
4908DRMP3_API float* drmp3_open_memory_and_read_pcm_frames_f32(const void* pData, size_t dataSize, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks)
4909{
4910 drmp3 mp3;
4911 if (!drmp3_init_memory(&mp3, pData, dataSize, pAllocationCallbacks)) {
4912 return NULL;
4913 }
4914
4915 return drmp3__full_read_and_close_f32(&mp3, pConfig, pTotalFrameCount);
4916}
4917
4918DRMP3_API drmp3_int16* drmp3_open_memory_and_read_pcm_frames_s16(const void* pData, size_t dataSize, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks)
4919{
4920 drmp3 mp3;
4921 if (!drmp3_init_memory(&mp3, pData, dataSize, pAllocationCallbacks)) {
4922 return NULL;
4923 }
4924
4925 return drmp3__full_read_and_close_s16(&mp3, pConfig, pTotalFrameCount);
4926}
4927
4928
4929#ifndef DR_MP3_NO_STDIO
4930DRMP3_API float* drmp3_open_file_and_read_pcm_frames_f32(const char* filePath, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks)
4931{
4932 drmp3 mp3;
4933 if (!drmp3_init_file(&mp3, filePath, pAllocationCallbacks)) {
4934 return NULL;
4935 }
4936
4937 return drmp3__full_read_and_close_f32(&mp3, pConfig, pTotalFrameCount);
4938}
4939
4940DRMP3_API drmp3_int16* drmp3_open_file_and_read_pcm_frames_s16(const char* filePath, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks)
4941{
4942 drmp3 mp3;
4943 if (!drmp3_init_file(&mp3, filePath, pAllocationCallbacks)) {
4944 return NULL;
4945 }
4946
4947 return drmp3__full_read_and_close_s16(&mp3, pConfig, pTotalFrameCount);
4948}
4949#endif
4950
4951DRMP3_API void* drmp3_malloc(size_t sz, const drmp3_allocation_callbacks* pAllocationCallbacks)
4952{
4953 if (pAllocationCallbacks != NULL) {
4954 return drmp3__malloc_from_callbacks(sz, pAllocationCallbacks);
4955 } else {
4956 return drmp3__malloc_default(sz, NULL);
4957 }
4958}
4959
4960DRMP3_API void drmp3_free(void* p, const drmp3_allocation_callbacks* pAllocationCallbacks)
4961{
4962 if (pAllocationCallbacks != NULL) {
4963 drmp3__free_from_callbacks(p, pAllocationCallbacks);
4964 } else {
4965 drmp3__free_default(p, NULL);
4966 }
4967}
4968
4969#endif /* dr_mp3_c */
4970#endif /*DR_MP3_IMPLEMENTATION*/
4971
4972/*
4973DIFFERENCES BETWEEN minimp3 AND dr_mp3
4974======================================
4975- First, keep in mind that minimp3 (https://github.com/lieff/minimp3) is where all the real work was done. All of the
4976 code relating to the actual decoding remains mostly unmodified, apart from some namespacing changes.
4977- dr_mp3 adds a pulling style API which allows you to deliver raw data via callbacks. So, rather than pushing data
4978 to the decoder, the decoder _pulls_ data from your callbacks.
4979- In addition to callbacks, a decoder can be initialized from a block of memory and a file.
4980- The dr_mp3 pull API reads PCM frames rather than whole MP3 frames.
4981- dr_mp3 adds convenience APIs for opening and decoding entire files in one go.
4982- dr_mp3 is fully namespaced, including the implementation section, which is more suitable when compiling projects
4983 as a single translation unit (aka unity builds). At the time of writing this, a unity build is not possible when
4984 using minimp3 in conjunction with stb_vorbis. dr_mp3 addresses this.
4985*/
4986
4987/*
4988REVISION HISTORY
4989================
4990v0.7.0 - TBD
4991 - The old `DRMP3_IMPLEMENTATION` has been removed. Use `DR_MP3_IMPLEMENTATION` instead. The reason for this change is that in the future everything will eventually be using the underscored naming convention in the future, so `drmp3` will become `dr_mp3`.
4992 - API CHANGE: Add drmp3_seek_origin_end as a seek origin for the seek callback. This is required for detection of ID3v1 and APE tags.
4993 - API CHANGE: Add onTell callback to `drmp3_init()`. This is needed in order to track the location of ID3v1 and APE tags.
4994 - API CHANGE: Add onMeta callback to `drmp3_init()`. This is used for reporting tag data back to the caller. Currently this only reports the raw tag data which means applications need to parse the data themselves.
4995 - API CHANGE: Rename `drmp3dec_frame_info.hz` to `drmp3dec_frame_info.sample_rate`.
4996 - Add detection of ID3v2, ID3v1, APE and Xing/VBRI tags. This should fix errors with some files where the decoder was reading tags as audio data.
4997 - Delay and padding samples from LAME tags are now handled.
4998 - Fix compilation for AIX OS.
4999
5000v0.6.40 - 2024-12-17
5001 - Improve detection of ARM64EC
5002
5003v0.6.39 - 2024-02-27
5004 - Fix a Wdouble-promotion warning.
5005
5006v0.6.38 - 2023-11-02
5007 - Fix build for ARMv6-M.
5008
5009v0.6.37 - 2023-07-07
5010 - Silence a static analysis warning.
5011
5012v0.6.36 - 2023-06-17
5013 - Fix an incorrect date in revision history. No functional change.
5014
5015v0.6.35 - 2023-05-22
5016 - Minor code restructure. No functional change.
5017
5018v0.6.34 - 2022-09-17
5019 - Fix compilation with DJGPP.
5020 - Fix compilation when compiling with x86 with no SSE2.
5021 - Remove an unnecessary variable from the drmp3 structure.
5022
5023v0.6.33 - 2022-04-10
5024 - Fix compilation error with the MSVC ARM64 build.
5025 - Fix compilation error on older versions of GCC.
5026 - Remove some unused functions.
5027
5028v0.6.32 - 2021-12-11
5029 - Fix a warning with Clang.
5030
5031v0.6.31 - 2021-08-22
5032 - Fix a bug when loading from memory.
5033
5034v0.6.30 - 2021-08-16
5035 - Silence some warnings.
5036 - Replace memory operations with DRMP3_* macros.
5037
5038v0.6.29 - 2021-08-08
5039 - Bring up to date with minimp3.
5040
5041v0.6.28 - 2021-07-31
5042 - Fix platform detection for ARM64.
5043 - Fix a compilation error with C89.
5044
5045v0.6.27 - 2021-02-21
5046 - Fix a warning due to referencing _MSC_VER when it is undefined.
5047
5048v0.6.26 - 2021-01-31
5049 - Bring up to date with minimp3.
5050
5051v0.6.25 - 2020-12-26
5052 - Remove DRMP3_DEFAULT_CHANNELS and DRMP3_DEFAULT_SAMPLE_RATE which are leftovers from some removed APIs.
5053
5054v0.6.24 - 2020-12-07
5055 - Fix a typo in version date for 0.6.23.
5056
5057v0.6.23 - 2020-12-03
5058 - Fix an error where a file can be closed twice when initialization of the decoder fails.
5059
5060v0.6.22 - 2020-12-02
5061 - Fix an error where it's possible for a file handle to be left open when initialization of the decoder fails.
5062
5063v0.6.21 - 2020-11-28
5064 - Bring up to date with minimp3.
5065
5066v0.6.20 - 2020-11-21
5067 - Fix compilation with OpenWatcom.
5068
5069v0.6.19 - 2020-11-13
5070 - Minor code clean up.
5071
5072v0.6.18 - 2020-11-01
5073 - Improve compiler support for older versions of GCC.
5074
5075v0.6.17 - 2020-09-28
5076 - Bring up to date with minimp3.
5077
5078v0.6.16 - 2020-08-02
5079 - Simplify sized types.
5080
5081v0.6.15 - 2020-07-25
5082 - Fix a compilation warning.
5083
5084v0.6.14 - 2020-07-23
5085 - Fix undefined behaviour with memmove().
5086
5087v0.6.13 - 2020-07-06
5088 - Fix a bug when converting from s16 to f32 in drmp3_read_pcm_frames_f32().
5089
5090v0.6.12 - 2020-06-23
5091 - Add include guard for the implementation section.
5092
5093v0.6.11 - 2020-05-26
5094 - Fix use of uninitialized variable error.
5095
5096v0.6.10 - 2020-05-16
5097 - Add compile-time and run-time version querying.
5098 - DRMP3_VERSION_MINOR
5099 - DRMP3_VERSION_MAJOR
5100 - DRMP3_VERSION_REVISION
5101 - DRMP3_VERSION_STRING
5102 - drmp3_version()
5103 - drmp3_version_string()
5104
5105v0.6.9 - 2020-04-30
5106 - Change the `pcm` parameter of drmp3dec_decode_frame() to a `const drmp3_uint8*` for consistency with internal APIs.
5107
5108v0.6.8 - 2020-04-26
5109 - Optimizations to decoding when initializing from memory.
5110
5111v0.6.7 - 2020-04-25
5112 - Fix a compilation error with DR_MP3_NO_STDIO
5113 - Optimization to decoding by reducing some data movement.
5114
5115v0.6.6 - 2020-04-23
5116 - Fix a minor bug with the running PCM frame counter.
5117
5118v0.6.5 - 2020-04-19
5119 - Fix compilation error on ARM builds.
5120
5121v0.6.4 - 2020-04-19
5122 - Bring up to date with changes to minimp3.
5123
5124v0.6.3 - 2020-04-13
5125 - Fix some pedantic warnings.
5126
5127v0.6.2 - 2020-04-10
5128 - Fix a crash in drmp3_open_*_and_read_pcm_frames_*() if the output config object is NULL.
5129
5130v0.6.1 - 2020-04-05
5131 - Fix warnings.
5132
5133v0.6.0 - 2020-04-04
5134 - API CHANGE: Remove the pConfig parameter from the following APIs:
5135 - drmp3_init()
5136 - drmp3_init_memory()
5137 - drmp3_init_file()
5138 - Add drmp3_init_file_w() for opening a file from a wchar_t encoded path.
5139
5140v0.5.6 - 2020-02-12
5141 - Bring up to date with minimp3.
5142
5143v0.5.5 - 2020-01-29
5144 - Fix a memory allocation bug in high level s16 decoding APIs.
5145
5146v0.5.4 - 2019-12-02
5147 - Fix a possible null pointer dereference when using custom memory allocators for realloc().
5148
5149v0.5.3 - 2019-11-14
5150 - Fix typos in documentation.
5151
5152v0.5.2 - 2019-11-02
5153 - Bring up to date with minimp3.
5154
5155v0.5.1 - 2019-10-08
5156 - Fix a warning with GCC.
5157
5158v0.5.0 - 2019-10-07
5159 - API CHANGE: Add support for user defined memory allocation routines. This system allows the program to specify their own memory allocation
5160 routines with a user data pointer for client-specific contextual data. This adds an extra parameter to the end of the following APIs:
5161 - drmp3_init()
5162 - drmp3_init_file()
5163 - drmp3_init_memory()
5164 - drmp3_open_and_read_pcm_frames_f32()
5165 - drmp3_open_and_read_pcm_frames_s16()
5166 - drmp3_open_memory_and_read_pcm_frames_f32()
5167 - drmp3_open_memory_and_read_pcm_frames_s16()
5168 - drmp3_open_file_and_read_pcm_frames_f32()
5169 - drmp3_open_file_and_read_pcm_frames_s16()
5170 - API CHANGE: Renamed the following APIs:
5171 - drmp3_open_and_read_f32() -> drmp3_open_and_read_pcm_frames_f32()
5172 - drmp3_open_and_read_s16() -> drmp3_open_and_read_pcm_frames_s16()
5173 - drmp3_open_memory_and_read_f32() -> drmp3_open_memory_and_read_pcm_frames_f32()
5174 - drmp3_open_memory_and_read_s16() -> drmp3_open_memory_and_read_pcm_frames_s16()
5175 - drmp3_open_file_and_read_f32() -> drmp3_open_file_and_read_pcm_frames_f32()
5176 - drmp3_open_file_and_read_s16() -> drmp3_open_file_and_read_pcm_frames_s16()
5177
5178v0.4.7 - 2019-07-28
5179 - Fix a compiler error.
5180
5181v0.4.6 - 2019-06-14
5182 - Fix a compiler error.
5183
5184v0.4.5 - 2019-06-06
5185 - Bring up to date with minimp3.
5186
5187v0.4.4 - 2019-05-06
5188 - Fixes to the VC6 build.
5189
5190v0.4.3 - 2019-05-05
5191 - Use the channel count and/or sample rate of the first MP3 frame instead of DRMP3_DEFAULT_CHANNELS and
5192 DRMP3_DEFAULT_SAMPLE_RATE when they are set to 0. To use the old behaviour, just set the relevant property to
5193 DRMP3_DEFAULT_CHANNELS or DRMP3_DEFAULT_SAMPLE_RATE.
5194 - Add s16 reading APIs
5195 - drmp3_read_pcm_frames_s16
5196 - drmp3_open_memory_and_read_pcm_frames_s16
5197 - drmp3_open_and_read_pcm_frames_s16
5198 - drmp3_open_file_and_read_pcm_frames_s16
5199 - Add drmp3_get_mp3_and_pcm_frame_count() to the public header section.
5200 - Add support for C89.
5201 - Change license to choice of public domain or MIT-0.
5202
5203v0.4.2 - 2019-02-21
5204 - Fix a warning.
5205
5206v0.4.1 - 2018-12-30
5207 - Fix a warning.
5208
5209v0.4.0 - 2018-12-16
5210 - API CHANGE: Rename some APIs:
5211 - drmp3_read_f32 -> to drmp3_read_pcm_frames_f32
5212 - drmp3_seek_to_frame -> drmp3_seek_to_pcm_frame
5213 - drmp3_open_and_decode_f32 -> drmp3_open_and_read_pcm_frames_f32
5214 - drmp3_open_and_decode_memory_f32 -> drmp3_open_memory_and_read_pcm_frames_f32
5215 - drmp3_open_and_decode_file_f32 -> drmp3_open_file_and_read_pcm_frames_f32
5216 - Add drmp3_get_pcm_frame_count().
5217 - Add drmp3_get_mp3_frame_count().
5218 - Improve seeking performance.
5219
5220v0.3.2 - 2018-09-11
5221 - Fix a couple of memory leaks.
5222 - Bring up to date with minimp3.
5223
5224v0.3.1 - 2018-08-25
5225 - Fix C++ build.
5226
5227v0.3.0 - 2018-08-25
5228 - Bring up to date with minimp3. This has a minor API change: the "pcm" parameter of drmp3dec_decode_frame() has
5229 been changed from short* to void* because it can now output both s16 and f32 samples, depending on whether or
5230 not the DR_MP3_FLOAT_OUTPUT option is set.
5231
5232v0.2.11 - 2018-08-08
5233 - Fix a bug where the last part of a file is not read.
5234
5235v0.2.10 - 2018-08-07
5236 - Improve 64-bit detection.
5237
5238v0.2.9 - 2018-08-05
5239 - Fix C++ build on older versions of GCC.
5240 - Bring up to date with minimp3.
5241
5242v0.2.8 - 2018-08-02
5243 - Fix compilation errors with older versions of GCC.
5244
5245v0.2.7 - 2018-07-13
5246 - Bring up to date with minimp3.
5247
5248v0.2.6 - 2018-07-12
5249 - Bring up to date with minimp3.
5250
5251v0.2.5 - 2018-06-22
5252 - Bring up to date with minimp3.
5253
5254v0.2.4 - 2018-05-12
5255 - Bring up to date with minimp3.
5256
5257v0.2.3 - 2018-04-29
5258 - Fix TCC build.
5259
5260v0.2.2 - 2018-04-28
5261 - Fix bug when opening a decoder from memory.
5262
5263v0.2.1 - 2018-04-27
5264 - Efficiency improvements when the decoder reaches the end of the stream.
5265
5266v0.2 - 2018-04-21
5267 - Bring up to date with minimp3.
5268 - Start using major.minor.revision versioning.
5269
5270v0.1d - 2018-03-30
5271 - Bring up to date with minimp3.
5272
5273v0.1c - 2018-03-11
5274 - Fix C++ build error.
5275
5276v0.1b - 2018-03-07
5277 - Bring up to date with minimp3.
5278
5279v0.1a - 2018-02-28
5280 - Fix compilation error on GCC/Clang.
5281 - Fix some warnings.
5282
5283v0.1 - 2018-02-xx
5284 - Initial versioned release.
5285*/
5286
5287/*
5288This software is available as a choice of the following licenses. Choose
5289whichever you prefer.
5290
5291===============================================================================
5292ALTERNATIVE 1 - Public Domain (www.unlicense.org)
5293===============================================================================
5294This is free and unencumbered software released into the public domain.
5295
5296Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
5297software, either in source code form or as a compiled binary, for any purpose,
5298commercial or non-commercial, and by any means.
5299
5300In jurisdictions that recognize copyright laws, the author or authors of this
5301software dedicate any and all copyright interest in the software to the public
5302domain. We make this dedication for the benefit of the public at large and to
5303the detriment of our heirs and successors. We intend this dedication to be an
5304overt act of relinquishment in perpetuity of all present and future rights to
5305this software under copyright law.
5306
5307THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
5308IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
5309FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
5310AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
5311ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
5312WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
5313
5314For more information, please refer to <http://unlicense.org/>
5315
5316===============================================================================
5317ALTERNATIVE 2 - MIT No Attribution
5318===============================================================================
5319Copyright 2023 David Reid
5320
5321Permission is hereby granted, free of charge, to any person obtaining a copy of
5322this software and associated documentation files (the "Software"), to deal in
5323the Software without restriction, including without limitation the rights to
5324use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
5325of the Software, and to permit persons to whom the Software is furnished to do
5326so.
5327
5328THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
5329IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
5330FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
5331AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
5332LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
5333OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
5334SOFTWARE.
5335*/
5336
5337/*
5338 https://github.com/lieff/minimp3
5339 To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain worldwide.
5340 This software is distributed without any warranty.
5341 See <http://creativecommons.org/publicdomain/zero/1.0/>.
5342*/
size_t size_t
#define DRMP3_ALREADY_CONNECTED
Definition dr_mp3.h:198
unsigned char drmp3_uint8
Definition dr_mp3.h:82
#define DRMP3_INVALID_OPERATION
Definition dr_mp3.h:155
drmp3_bool32 drmp3_init_memory(drmp3 *pMP3, const void *pData, size_t dataSize, const drmp3_allocation_callbacks *pAllocationCallbacks)
float * drmp3_open_file_and_read_pcm_frames_f32(const char *filePath, drmp3_config *pConfig, drmp3_uint64 *pTotalFrameCount, const drmp3_allocation_callbacks *pAllocationCallbacks)
#define DRMP3_DOES_NOT_EXIST
Definition dr_mp3.h:159
drmp3_seek_origin
Definition dr_mp3.h:288
@ drmp3_seek_origin_end
Definition dr_mp3.h:291
@ drmp3_seek_origin_start
Definition dr_mp3.h:289
@ drmp3_seek_origin_current
Definition dr_mp3.h:290
drmp3_bool32 drmp3_bind_seek_table(drmp3 *pMP3, drmp3_uint32 seekPointCount, drmp3_seek_point *pSeekPoints)
#define DRMP3_UNAVAILABLE
Definition dr_mp3.h:174
unsigned short drmp3_uint16
Definition dr_mp3.h:84
#define DRMP3_NOT_DIRECTORY
Definition dr_mp3.h:166
#define DRMP3_NOT_UNIQUE
Definition dr_mp3.h:188
#define DRMP3_ALREADY_IN_USE
Definition dr_mp3.h:175
#define DRMP3_IN_PROGRESS
Definition dr_mp3.h:202
drmp3_int16 * drmp3_open_and_read_pcm_frames_s16(drmp3_read_proc onRead, drmp3_seek_proc onSeek, drmp3_tell_proc onTell, void *pUserData, drmp3_config *pConfig, drmp3_uint64 *pTotalFrameCount, const drmp3_allocation_callbacks *pAllocationCallbacks)
float * drmp3_open_and_read_pcm_frames_f32(drmp3_read_proc onRead, drmp3_seek_proc onSeek, drmp3_tell_proc onTell, void *pUserData, drmp3_config *pConfig, drmp3_uint64 *pTotalFrameCount, const drmp3_allocation_callbacks *pAllocationCallbacks)
signed int drmp3_int32
Definition dr_mp3.h:85
#define DRMP3_BAD_MESSAGE
Definition dr_mp3.h:183
void drmp3_uninit(drmp3 *pMP3)
#define DRMP3_PROTOCOL_FAMILY_NOT_SUPPORTED
Definition dr_mp3.h:194
#define DRMP3_SUCCESS
Definition dr_mp3.h:152
#define DRMP3_PATH_TOO_LONG
Definition dr_mp3.h:164
signed char drmp3_int8
Definition dr_mp3.h:81
drmp3_bool32 drmp3_calculate_seek_points(drmp3 *pMP3, drmp3_uint32 *pSeekPointCount, drmp3_seek_point *pSeekPoints)
#define DRMP3_BAD_ADDRESS
Definition dr_mp3.h:176
#define DRMP3_BAD_SEEK
Definition dr_mp3.h:177
drmp3_uint64 drmp3_get_pcm_frame_count(drmp3 *pMP3)
#define DRMP3_PROTOCOL_UNAVAILABLE
Definition dr_mp3.h:192
drmp3_bool32(* drmp3_seek_proc)(void *pUserData, int offset, drmp3_seek_origin origin)
Definition dr_mp3.h:342
#define DRMP3_INVALID_ARGS
Definition dr_mp3.h:154
#define DRMP3_NO_NETWORK
Definition dr_mp3.h:187
void(* drmp3_meta_proc)(void *pUserData, const drmp3_metadata *pMetadata)
Definition dr_mp3.h:360
#define DRMP3_IS_DIRECTORY
Definition dr_mp3.h:167
#define DRMP3_BUSY
Definition dr_mp3.h:171
#define DRMP3_CONNECTION_RESET
Definition dr_mp3.h:197
#define DRMP3_INTERRUPT
Definition dr_mp3.h:173
#define DRMP3_PROTOCOL_NOT_SUPPORTED
Definition dr_mp3.h:193
#define DRMP3_ALREADY_EXISTS
Definition dr_mp3.h:160
void drmp3_free(void *p, const drmp3_allocation_callbacks *pAllocationCallbacks)
#define DRMP3_OUT_OF_MEMORY
Definition dr_mp3.h:156
drmp3_uint64 drmp3_read_pcm_frames_f32(drmp3 *pMP3, drmp3_uint64 framesToRead, float *pBufferOut)
#define DRMP3_NOT_CONNECTED
Definition dr_mp3.h:199
#define DRMP3_TIMEOUT
Definition dr_mp3.h:186
drmp3_int32 drmp3_result
Definition dr_mp3.h:151
drmp3_metadata_type
Definition dr_mp3.h:303
@ DRMP3_METADATA_TYPE_APE
Definition dr_mp3.h:306
@ DRMP3_METADATA_TYPE_ID3V1
Definition dr_mp3.h:304
@ DRMP3_METADATA_TYPE_VBRI
Definition dr_mp3.h:308
@ DRMP3_METADATA_TYPE_ID3V2
Definition dr_mp3.h:305
@ DRMP3_METADATA_TYPE_XING
Definition dr_mp3.h:307
#define DRMP3_INVALID_FILE
Definition dr_mp3.h:162
#define DRMP3_VERSION_MINOR
Definition dr_mp3.h:74
#define DRMP3_ADDRESS_FAMILY_NOT_SUPPORTED
Definition dr_mp3.h:195
#define DRMP3_UINT64_MAX
Definition dr_mp3.h:115
#define DRMP3_MAX_SAMPLES_PER_FRAME
Definition dr_mp3.h:209
drmp3_bool32 drmp3_seek_to_pcm_frame(drmp3 *pMP3, drmp3_uint64 frameIndex)
#define DRMP3_API
Definition dr_mp3.h:144
drmp3_bool32 drmp3_init_file_with_metadata(drmp3 *pMP3, const char *pFilePath, drmp3_meta_proc onMeta, void *pUserDataMeta, const drmp3_allocation_callbacks *pAllocationCallbacks)
drmp3_uint64 drmp3_read_pcm_frames_s16(drmp3 *pMP3, drmp3_uint64 framesToRead, drmp3_int16 *pBufferOut)
size_t(* drmp3_read_proc)(void *pUserData, void *pBufferOut, size_t bytesToRead)
Definition dr_mp3.h:331
#define DRMP3_NO_MESSAGE
Definition dr_mp3.h:182
void drmp3dec_init(drmp3dec *dec)
drmp3_uint64 drmp3_get_mp3_frame_count(drmp3 *pMP3)
#define DRMP3_NO_HOST
Definition dr_mp3.h:201
#define DRMP3_DEADLOCK
Definition dr_mp3.h:179
#define DRMP3_ERROR
Definition dr_mp3.h:153
drmp3_uint8 drmp3_bool8
Definition dr_mp3.h:109
#define DRMP3_CANCELLED
Definition dr_mp3.h:203
void drmp3dec_f32_to_s16(const float *in, drmp3_int16 *out, size_t num_samples)
void * drmp3_malloc(size_t sz, const drmp3_allocation_callbacks *pAllocationCallbacks)
drmp3_bool32 drmp3_init_file(drmp3 *pMP3, const char *pFilePath, const drmp3_allocation_callbacks *pAllocationCallbacks)
unsigned int drmp3_uint32
Definition dr_mp3.h:86
int drmp3dec_decode_frame(drmp3dec *dec, const drmp3_uint8 *mp3, int mp3_bytes, void *pcm, drmp3dec_frame_info *info)
#define DRMP3_VERSION_MAJOR
Definition dr_mp3.h:73
drmp3_uint32 drmp3_uintptr
Definition dr_mp3.h:107
#define DRMP3_INVALID_DATA
Definition dr_mp3.h:185
drmp3_bool32 drmp3_init(drmp3 *pMP3, drmp3_read_proc onRead, drmp3_seek_proc onSeek, drmp3_tell_proc onTell, drmp3_meta_proc onMeta, void *pUserData, const drmp3_allocation_callbacks *pAllocationCallbacks)
#define DRMP3_IO_ERROR
Definition dr_mp3.h:172
drmp3_int16 * drmp3_open_file_and_read_pcm_frames_s16(const char *filePath, drmp3_config *pConfig, drmp3_uint64 *pTotalFrameCount, const drmp3_allocation_callbacks *pAllocationCallbacks)
drmp3_bool32(* drmp3_tell_proc)(void *pUserData, drmp3_int64 *pCursor)
Definition dr_mp3.h:352
#define DRMP3_NOT_SOCKET
Definition dr_mp3.h:189
#define DRMP3_VERSION_REVISION
Definition dr_mp3.h:75
#define DRMP3_CONNECTION_REFUSED
Definition dr_mp3.h:200
const char * drmp3_version_string(void)
#define DRMP3_FALSE
Definition dr_mp3.h:112
drmp3_bool32 drmp3_init_file_w(drmp3 *pMP3, const wchar_t *pFilePath, const drmp3_allocation_callbacks *pAllocationCallbacks)
signed long long drmp3_int64
Definition dr_mp3.h:98
void drmp3_version(drmp3_uint32 *pMajor, drmp3_uint32 *pMinor, drmp3_uint32 *pRevision)
#define DRMP3_NO_DATA_AVAILABLE
Definition dr_mp3.h:184
drmp3_bool32 drmp3_init_memory_with_metadata(drmp3 *pMP3, const void *pData, size_t dataSize, drmp3_meta_proc onMeta, void *pUserDataMeta, const drmp3_allocation_callbacks *pAllocationCallbacks)
#define DRMP3_BAD_PROTOCOL
Definition dr_mp3.h:191
#define DRMP3_NO_ADDRESS
Definition dr_mp3.h:190
#define DRMP3_VERSION_STRING
Definition dr_mp3.h:76
#define DRMP3_BAD_PIPE
Definition dr_mp3.h:178
signed short drmp3_int16
Definition dr_mp3.h:83
#define DRMP3_TOO_MANY_OPEN_FILES
Definition dr_mp3.h:161
drmp3_int16 * drmp3_open_memory_and_read_pcm_frames_s16(const void *pData, size_t dataSize, drmp3_config *pConfig, drmp3_uint64 *pTotalFrameCount, const drmp3_allocation_callbacks *pAllocationCallbacks)
unsigned long long drmp3_uint64
Definition dr_mp3.h:99
float * drmp3_open_memory_and_read_pcm_frames_f32(const void *pData, size_t dataSize, drmp3_config *pConfig, drmp3_uint64 *pTotalFrameCount, const drmp3_allocation_callbacks *pAllocationCallbacks)
#define DRMP3_TRUE
Definition dr_mp3.h:111
#define DRMP3_ACCESS_DENIED
Definition dr_mp3.h:158
#define DRMP3_TOO_MANY_LINKS
Definition dr_mp3.h:180
#define DRMP3_SOCKET_NOT_SUPPORTED
Definition dr_mp3.h:196
#define DRMP3_INLINE
Definition dr_mp3.h:236
#define DRMP3_NO_SPACE
Definition dr_mp3.h:170
#define DRMP3_DIRECTORY_NOT_EMPTY
Definition dr_mp3.h:168
#define DRMP3_OUT_OF_RANGE
Definition dr_mp3.h:157
#define DRMP3_TOO_BIG
Definition dr_mp3.h:163
drmp3_uint32 drmp3_bool32
Definition dr_mp3.h:110
drmp3_bool32 drmp3_get_mp3_and_pcm_frame_count(drmp3 *pMP3, drmp3_uint64 *pMP3FrameCount, drmp3_uint64 *pPCMFrameCount)
#define DRMP3_NOT_IMPLEMENTED
Definition dr_mp3.h:181
drmp3_bool32 drmp3_init_file_with_metadata_w(drmp3 *pMP3, const wchar_t *pFilePath, drmp3_meta_proc onMeta, void *pUserDataMeta, const drmp3_allocation_callbacks *pAllocationCallbacks)
double sign(const double &v)
Invert a symmetric and positive definite matrix using Cholesky decomposition (defined in Math....
Definition math.cpp:657
bool sum(yarp::sig::Image &OutImg, const yarp::sig::Image &InImg, bool colorkey_enable, int colorkey, bool alpha_enable, float alpha, size_t off_x, size_t off_y)
applies an image on the top over another image.
void(* onFree)(void *p, void *pUserData)
Definition dr_mp3.h:251
void *(* onRealloc)(void *p, size_t sz, void *pUserData)
Definition dr_mp3.h:250
void *(* onMalloc)(size_t sz, void *pUserData)
Definition dr_mp3.h:249
drmp3_uint32 sampleRate
Definition dr_mp3.h:366
drmp3_uint32 channels
Definition dr_mp3.h:365
size_t rawDataSize
Definition dr_mp3.h:315
drmp3_metadata_type type
Definition dr_mp3.h:313
const void * pRawData
Definition dr_mp3.h:314
drmp3_uint64 seekPosInBytes
Definition dr_mp3.h:296
drmp3_uint64 pcmFrameIndex
Definition dr_mp3.h:297
drmp3_uint16 mp3FramesToDiscard
Definition dr_mp3.h:298
drmp3_uint16 pcmFramesToDiscard
Definition dr_mp3.h:299
drmp3_uint32 sampleRate
Definition dr_mp3.h:373
drmp3_uint64 totalPCMFrameCount
Definition dr_mp3.h:393
drmp3_bool32 isCBR
Definition dr_mp3.h:395
struct drmp3::@93 memory
size_t dataConsumed
Definition dr_mp3.h:398
drmp3_bool32 isVBR
Definition dr_mp3.h:394
drmp3_uint32 pcmFramesConsumedInMP3Frame
Definition dr_mp3.h:382
drmp3_uint64 streamStartOffset
Definition dr_mp3.h:388
drmp3_uint32 paddingInPCMFrames
Definition dr_mp3.h:392
drmp3_uint64 currentPCMFrame
Definition dr_mp3.h:385
const drmp3_uint8 * pData
Definition dr_mp3.h:403
drmp3_uint64 streamCursor
Definition dr_mp3.h:386
void * pUserDataMeta
Definition dr_mp3.h:378
drmp3_uint64 streamLength
Definition dr_mp3.h:387
drmp3_uint8 * pData
Definition dr_mp3.h:399
drmp3_seek_proc onSeek
Definition dr_mp3.h:375
drmp3_uint8 pcmFrames[sizeof(float) *(1152 *2)]
Definition dr_mp3.h:384
drmp3_read_proc onRead
Definition dr_mp3.h:374
drmp3_allocation_callbacks allocationCallbacks
Definition dr_mp3.h:379
size_t currentReadPos
Definition dr_mp3.h:405
size_t dataCapacity
Definition dr_mp3.h:397
size_t dataSize
Definition dr_mp3.h:396
void * pUserData
Definition dr_mp3.h:377
drmp3_uint32 channels
Definition dr_mp3.h:372
drmp3_uint32 mp3FrameSampleRate
Definition dr_mp3.h:381
drmp3_seek_point * pSeekPoints
Definition dr_mp3.h:389
drmp3_uint32 pcmFramesRemainingInMP3Frame
Definition dr_mp3.h:383
drmp3_uint32 seekPointCount
Definition dr_mp3.h:390
drmp3_bool32 atEnd
Definition dr_mp3.h:400
drmp3_uint32 mp3FrameChannels
Definition dr_mp3.h:380
drmp3_uint32 delayInPCMFrames
Definition dr_mp3.h:391
drmp3_meta_proc onMeta
Definition dr_mp3.h:376
drmp3dec decoder
Definition dr_mp3.h:371
drmp3_uint8 reserv_buf[511]
Definition dr_mp3.h:269
int free_format_bytes
Definition dr_mp3.h:268
int reserv
Definition dr_mp3.h:268
drmp3_uint8 header[4]
Definition dr_mp3.h:269
float mdct_overlap[2][9 *32]
Definition dr_mp3.h:267
float qmf_state[15 *2 *32]
Definition dr_mp3.h:267