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