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