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

Generated with cgit - Back to sebastiano.tronto.net