Logo

index : raylib-jai

Bindings from https://solarium.technology

  • summary
  • about
  • tree
  • log
  • branches
<< path: root/public/raylib-jai.git/html/Raylib/raylib/src/external/dr_mp3.h blob: cc033ce871125fef9c9e0941cd1108b810d06461 [raw] [clear marker]

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