FLAC audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
FLAC audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
dr_flac - v0.12.7 - 2020-03-14
dr_flac - v0.12.8 - 2020-04-04
David Reid - mackron@gmail.com
David Reid - mackron@gmail.com
GitHub: https://github.com/mackron/dr_libs
*/
*/
/*
/*
...
@@ -115,16 +117,18 @@ to the old per-sample APIs. You now need to use the "pcm_frame" versions.
...
@@ -115,16 +117,18 @@ to the old per-sample APIs. You now need to use the "pcm_frame" versions.
/*
/*
USAGE
Introduction
=====
============
dr_flac is a single-file library. To use it, do something like the following in one .c file.
dr_flac is a singlefile library. To use it, do something like the following in one .c file.
```c
#define DR_FLAC_IMPLEMENTATION
#define DR_FLAC_IMPLEMENTATION
#include "dr_flac.h"
#include "dr_flac.h"
```
You can then #include this file in other parts of the program as you would with any other header file. To decode audio data,
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:
The drflac object represents the decoder. It is a transparent type so all the information you need, such as the number of
The drflac object represents the decoder. It is a transparent type so all the information you need, such as the number of channels and the bits per sample,
channels and the bits per sample, should be directly accessible - just make sure you don't change their values. Samples are
should be directly accessible - just make sure you don't change their values. Samples are always output as interleaved signed 32-bit PCM. In the example above
always output as interleaved signed 32-bit PCM. In the example above a native FLAC stream was opened, however dr_flac has
a native FLAC stream was opened, however dr_flac has seamless support for Ogg encapsulated FLAC streams as well.
seamless support for Ogg encapsulated FLAC streams as well.
You do not need to decode the entire stream in one go - you just specify how many samples you'd like at any given time and
You do not need to decode the entire stream in one go - you just specify how many samples you'd like at any given time and the decoder will give you as many
the decoder will give you as many samples as it can, up to the amount requested. Later on when you need the next batch of
samples as it can, up to the amount requested. Later on when you need the next batch of samples, just call it again. Example:
samples, just call it again. Example:
```c
while (drflac_read_pcm_frames_s32(pFlac, chunkSizeInPCMFrames, pChunkSamples) > 0) {
while (drflac_read_pcm_frames_s32(pFlac, chunkSizeInPCMFrames, pChunkSamples) > 0) {
do_something();
do_something();
}
}
```
You can seek to a specific sample with drflac_seek_to_sample(). The given sample is based on interleaving. So for example,
You can seek to a specific sample with drflac_seek_to_sample(). The given sample is based on interleaving. So for example, if you were to seek to the sample at
if you were to seek to the sample at index 0 in a stereo stream, you'll be seeking to the first sample of the left channel.
index 0 in a stereo stream, you'll be seeking to the first sample of the left channel. The sample at index 1 will be the first sample of the right channel. The
The sample at index 1 will be the first sample of the right channel. The sample at index 2 will be the second sample of the
sample at index 2 will be the second sample of the left channel, etc.
left channel, etc.
If you just want to quickly decode an entire FLAC file in one go you can do something like this:
If you just want to quickly decode an entire FLAC file in one go you can do something like this:
```c
unsigned int channels;
unsigned int channels;
unsigned int sampleRate;
unsigned int sampleRate;
drflac_uint64 totalPCMFrameCount;
drflac_uint64 totalPCMFrameCount;
...
@@ -165,94 +170,132 @@ If you just want to quickly decode an entire FLAC file in one go you can do some
...
@@ -165,94 +170,132 @@ If you just want to quickly decode an entire FLAC file in one go you can do some
...
...
drflac_free(pSampleData);
drflac_free(pSampleData);
```
You can read samples as signed 16-bit integer and 32-bit floating-point PCM with the *_s16() and *_f32() family of APIs respectively, but note that these
You can read samples as signed 16-bit integer and 32-bit floating-point PCM with the *_s16() and *_f32() family of APIs
should be considered lossy.
respectively, but note that these should be considered lossy.
If you need access to metadata (album art, etc.), use drflac_open_with_metadata(), drflac_open_file_with_metdata() or
If you need access to metadata (album art, etc.), use `drflac_open_with_metadata()`, `drflac_open_file_with_metdata()` or `drflac_open_memory_with_metadata()`.
drflac_open_memory_with_metadata(). The rationale for keeping these APIs separate is that they're slightly slower than the
The rationale for keeping these APIs separate is that they're slightly slower than the normal versions and also just a little bit harder to use. dr_flac
normal versions and also just a little bit harder to use.
reports metadata to the application through the use of a callback, and every metadata block is reported before `drflac_open_with_metdata()` returns.
dr_flac reports metadata to the application through the use of a callback, and every metadata block is reported before
The main opening APIs (`drflac_open()`, etc.) will fail if the header is not present. The presents a problem in certain scenarios such as broadcast style
drflac_open_with_metdata() returns.
streams or internet radio where the header may not be present because the user has started playback mid-stream. To handle this, use the relaxed APIs:
`drflac_open_relaxed()`
`drflac_open_with_metadata_relaxed()`
It is not recommended to use these APIs for file based streams because a missing header would usually indicate a corrupt or perverse file. In addition, these
APIs can take a long time to initialize because they may need to spend a lot of time finding the first frame.
The main opening APIs (drflac_open(), etc.) will fail if the header is not present. The presents a problem in certain
scenarios such as broadcast style streams or internet radio where the header may not be present because the user has
started playback mid-stream. To handle this, use the relaxed APIs: drflac_open_relaxed() and drflac_open_with_metadata_relaxed().
It is not recommended to use these APIs for file based streams because a missing header would usually indicate a
corrupt or perverse file. In addition, these APIs can take a long time to initialize because they may need to spend
a lot of time finding the first frame.
Build Options
=============
OPTIONS
=======
#define these options before including this file.
#define these options before including this file.
#define DR_FLAC_NO_STDIO
#define DR_FLAC_NO_STDIO
Disable drflac_open_file() and family.
Disable `drflac_open_file()` and family.
#define DR_FLAC_NO_OGG
#define DR_FLAC_NO_OGG
Disables support for Ogg/FLAC streams.
Disables support for Ogg/FLAC streams.
#define DR_FLAC_BUFFER_SIZE <number>
#define DR_FLAC_BUFFER_SIZE <number>
Defines the size of the internal buffer to store data from onRead(). This buffer is used to reduce the number of calls
Defines the size of the internal buffer to store data from onRead(). This buffer is used to reduce the number of calls back to the client for more data.
back to the client for more data. Larger values means more memory, but better performance. My tests show diminishing
Larger values means more memory, but better performance. My tests show diminishing returns after about 4KB (which is the default). Consider reducing this if
returns after about 4KB (which is the default). Consider reducing this if you have a very efficient implementation of
you have a very efficient implementation of onRead(), or increase it if it's very inefficient. Must be a multiple of 8.
onRead(), or increase it if it's very inefficient. Must be a multiple of 8.
#define DR_FLAC_NO_CRC
#define DR_FLAC_NO_CRC
Disables CRC checks. This will offer a performance boost when CRC is unnecessary. This will disable binary search seeking.
Disables CRC checks. This will offer a performance boost when CRC is unnecessary. This will disable binary search seeking. When seeking, the seek table will
When seeking, the seek table will be used if available. Otherwise the seek will be performed using brute force.
be used if available. Otherwise the seek will be performed using brute force.
#define DR_FLAC_NO_SIMD
#define DR_FLAC_NO_SIMD
Disables SIMD optimizations (SSE on x86/x64 architectures, NEON on ARM architectures). Use this if you are having
Disables SIMD optimizations (SSE on x86/x64 architectures, NEON on ARM architectures). Use this if you are having compatibility issues with your compiler.
compatibility issues with your compiler.
QUICK NOTES
Notes
===========
=====
- dr_flac does not currently support changing the sample rate nor channel count mid stream.
- dr_flac does not support changing the sample rate nor channel count mid stream.
- This has not been tested on big-endian architectures.
- dr_flac is not thread-safe, but its APIs can be called from any thread so long as you do your own synchronization.
- dr_flac is not thread-safe, but its APIs can be called from any thread so long as you do your own synchronization.
- When using Ogg encapsulation, a corrupted metadata block will result in drflac_open_with_metadata() and drflac_open()
- When using Ogg encapsulation, a corrupted metadata block will result in `drflac_open_with_metadata()` and `drflac_open()` returning inconsistent samples due
returning inconsistent samples.
to differences in corrupted stream recorvery logic between the two APIs.
*/
*/
#ifndef dr_flac_h
#ifndef dr_flac_h
#define dr_flac_h
#define dr_flac_h
#include <stddef.h>
#ifdef __cplusplus
extern"C"{
#if defined(_MSC_VER) && _MSC_VER < 1600
#endif
typedefsignedchardrflac_int8;
typedefunsignedchardrflac_uint8;
#include <stddef.h> /* For size_t. */
typedefsignedshortdrflac_int16;
typedefunsignedshortdrflac_uint16;
/* Sized types. Prefer built-in types. Fall back to stdint. */
As data is read from the client it is placed into an internal buffer for fast access. This controls the
As data is read from the client it is placed into an internal buffer for fast access. This controls the size of that buffer. Larger values means more speed,
size of that buffer. Larger values means more speed, but also more memory. In my testing there is diminishing
but also more memory. In my testing there is diminishing returns after about 4KB, but you can fiddle with this to suit your own needs. Must be a multiple of 8.
returns after about 4KB, but you can fiddle with this to suit your own needs. Must be a multiple of 8.
*/
*/
#ifndef DR_FLAC_BUFFER_SIZE
#ifndef DR_FLAC_BUFFER_SIZE
#define DR_FLAC_BUFFER_SIZE 4096
#define DR_FLAC_BUFFER_SIZE 4096
#endif
#endif
#ifdef __cplusplus
extern"C"{
#endif
/* Check if we can enable 64-bit optimizations. */
/* Check if we can enable 64-bit optimizations. */
Callback for when data needs to be read from the client.
Callback for when data needs to be read from the client.
pUserData [in] The user data that was passed to drflac_open() and family.
pBufferOut [out] The output buffer.
bytesToRead [in] The number of bytes to read.
Returns the number of bytes actually read.
Parameters
----------
pUserData (in)
The user data that was passed to drflac_open() and family.
pBufferOut (out)
The output buffer.
bytesToRead (in)
The number of bytes to read.
A return value of less than bytesToRead indicates the end of the stream. Do _not_ return from this callback until
either the entire bytesToRead is filled or you have reached the end of the stream.
Return Value
------------
The number of bytes actually read.
Remarks
-------
A return value of less than bytesToRead indicates the end of the stream. Do _not_ return from this callback until either the entire bytesToRead is filled or
pUserData [in] The user data that was passed to drflac_open() and family.
offset [in] The number of bytes to move, relative to the origin. Will never be negative.
origin [in] The origin of the seek - the current position or the start of the stream.
Returns whether or not the seek was successful.
Parameters
----------
pUserData (in)
The user data that was passed to drflac_open() and family.
offset (in)
The number of bytes to move, relative to the origin. Will never be negative.
origin (in)
The origin of the seek - the current position or the start of the stream.
The offset will never be negative. Whether or not it is relative to the beginning or current position is determined
by the "origin" parameter which will be either drflac_seek_origin_start or drflac_seek_origin_current.
When seeking to a PCM frame using drflac_seek_to_pcm_frame(), dr_flac may call this with an offset beyond the end of
Return Value
the FLAC stream. This needs to be detected and handled by returning DRFLAC_FALSE.
------------
Whether or not the seek was successful.
Remarks
-------
The offset will never be negative. Whether or not it is relative to the beginning or current position is determined by the "origin" parameter which will be
either drflac_seek_origin_start or drflac_seek_origin_current.
When seeking to a PCM frame using drflac_seek_to_pcm_frame(), dr_flac may call this with an offset beyond the end of the FLAC stream. This needs to be detected
onRead [in] The function to call when data needs to be read from the client.
onSeek [in] The function to call when the read position of the client data needs to move.
pUserData [in, optional] A pointer to application defined data that will be passed to onRead and onSeek.
pAllocationCallbacks [in, optional] A pointer to application defined callbacks for managing memory allocations.
Parameters
----------
onRead (in)
The function to call when data needs to be read from the client.
onSeek (in)
The function to call when the read position of the client data needs to move.
pUserData (in, optional)
A pointer to application defined data that will be passed to onRead and onSeek.
pAllocationCallbacks (in, optional)
A pointer to application defined callbacks for managing memory allocations.
Return Value
------------
Returns a pointer to an object representing the decoder.
Returns a pointer to an object representing the decoder.
Close the decoder with drflac_close().
pAllocationCallbacks can be NULL in which case it will use DRFLAC_MALLOC, DRFLAC_REALLOC and DRFLAC_FREE.
Remarks
-------
Close the decoder with `drflac_close()`.
This function will automatically detect whether or not you are attempting to open a native or Ogg encapsulated
`pAllocationCallbacks` can be NULL in which case it will use `DRFLAC_MALLOC`, `DRFLAC_REALLOC` and `DRFLAC_FREE`.
FLAC, both of which should work seamlessly without any manual intervention. Ogg encapsulation also works with
multiplexed streams which basically means it can play FLAC encoded audio tracks in videos.
This is the lowest level function for opening a FLAC stream. You can also use drflac_open_file() and drflac_open_memory()
This function will automatically detect whether or not you are attempting to open a native or Ogg encapsulated FLAC, both of which should work seamlessly
to open the stream from a file or from a block of memory respectively.
without any manual intervention. Ogg encapsulation also works with multiplexed streams which basically means it can play FLAC encoded audio tracks in videos.
The STREAMINFO block must be present for this to succeed. Use drflac_open_relaxed() to open a FLAC stream where
This is the lowest level function for opening a FLAC stream. You can also use `drflac_open_file()` and `drflac_open_memory()` to open the stream from a file or
the header may not be present.
from a block of memory respectively.
See also: drflac_open_file(), drflac_open_memory(), drflac_open_with_metadata(), drflac_close()
The STREAMINFO block must be present for this to succeed. Use `drflac_open_relaxed()` to open a FLAC stream where the header may not be present.
Opens a FLAC stream with relaxed validation of the header block.
Parameters
----------
onRead (in)
The function to call when data needs to be read from the client.
onSeek (in)
The function to call when the read position of the client data needs to move.
container (in)
Whether or not the FLAC stream is encapsulated using standard FLAC encapsulation or Ogg encapsulation.
pUserData (in, optional)
A pointer to application defined data that will be passed to onRead and onSeek.
pAllocationCallbacks (in, optional)
A pointer to application defined callbacks for managing memory allocations.
Return Value
------------
A pointer to an object representing the decoder.
Remarks
-------
The same as drflac_open(), except attempts to open the stream even when a header block is not present.
The same as drflac_open(), except attempts to open the stream even when a header block is not present.
Because the header is not necessarily available, the caller must explicitly define the container (Native or Ogg). Do
Because the header is not necessarily available, the caller must explicitly define the container (Native or Ogg). Do not set this to `drflac_container_unknown`
not set this to drflac_container_unknown - that is for internal use only.
as that is for internal use only.
Opening in relaxed mode will continue reading data from onRead until it finds a valid frame. If a frame is never
Opening in relaxed mode will continue reading data from onRead until it finds a valid frame. If a frame is never found it will continue forever. To abort,
found it will continue forever. To abort, force your onRead callback to return 0, which dr_flac will use as an
force your `onRead` callback to return 0, which dr_flac will use as an indicator that the end of the stream was found.
Opens a FLAC decoder and notifies the caller of the metadata chunks (album art, etc.).
Opens a FLAC decoder and notifies the caller of the metadata chunks (album art, etc.).
onRead [in] The function to call when data needs to be read from the client.
onSeek [in] The function to call when the read position of the client data needs to move.
onMeta [in] The function to call for every metadata block.
pUserData [in, optional] A pointer to application defined data that will be passed to onRead, onSeek and onMeta.
pAllocationCallbacks [in, optional] A pointer to application defined callbacks for managing memory allocations.
Returns a pointer to an object representing the decoder.
Parameters
----------
onRead (in)
The function to call when data needs to be read from the client.
Close the decoder with drflac_close().
onSeek (in)
The function to call when the read position of the client data needs to move.
onMeta (in)
The function to call for every metadata block.
pUserData (in, optional)
A pointer to application defined data that will be passed to onRead, onSeek and onMeta.
pAllocationCallbacks (in, optional)
A pointer to application defined callbacks for managing memory allocations.
Return Value
------------
A pointer to an object representing the decoder.
pAllocationCallbacks can be NULL in which case it will use DRFLAC_MALLOC, DRFLAC_REALLOC and DRFLAC_FREE.
This is slower than drflac_open(), so avoid this one if you don't need metadata. Internally, this will allocate and free
Remarks
memory on the heap for every metadata block except for STREAMINFO and PADDING blocks.
-------
Close the decoder with `drflac_close()`.
The caller is notified of the metadata via the onMeta callback. All metadata blocks will be handled before the function
`pAllocationCallbacks` can be NULL in which case it will use `DRFLAC_MALLOC`, `DRFLAC_REALLOC` and `DRFLAC_FREE`.
returns.
The STREAMINFO block must be present for this to succeed. Use drflac_open_with_metadata_relaxed() to open a FLAC
This is slower than `drflac_open()`, so avoid this one if you don't need metadata. Internally, this will allocate and free memory on the heap for every
stream where the header may not be present.
metadata block except for STREAMINFO and PADDING blocks.
Note that this will behave inconsistently with drflac_open() if the stream is an Ogg encapsulated stream and a metadata
The caller is notified of the metadata via the `onMeta` callback. All metadata blocks will be handled before the function returns.
block is corrupted. This is due to the way the Ogg stream recovers from corrupted pages. When drflac_open_with_metadata()
is being used, the open routine will try to read the contents of the metadata block, whereas drflac_open() will simply
seek past it (for the sake of efficiency). This inconsistency can result in different samples being returned depending on
whether or not the stream is being opened with metadata.
See also: drflac_open_file_with_metadata(), drflac_open_memory_with_metadata(), drflac_open(), drflac_close()
The STREAMINFO block must be present for this to succeed. Use `drflac_open_with_metadata_relaxed()` to open a FLAC stream where the header may not be present.
Note that this will behave inconsistently with `drflac_open()` if the stream is an Ogg encapsulated stream and a metadata block is corrupted. This is due to
the way the Ogg stream recovers from corrupted pages. When `drflac_open_with_metadata()` is being used, the open routine will try to read the contents of the
metadata block, whereas `drflac_open()` will simply seek past it (for the sake of efficiency). This inconsistency can result in different samples being
returned depending on whether or not the stream is being opened with metadata.
Opens a FLAC decoder from the file at the given path.
Opens a FLAC decoder from the file at the given path.
filename [in] The path of the file to open, either absolute or relative to the current directory.
pAllocationCallbacks [in, optional] A pointer to application defined callbacks for managing memory allocations.
Returns a pointer to an object representing the decoder.
Parameters
----------
pFileName (in)
The path of the file to open, either absolute or relative to the current directory.
pAllocationCallbacks (in, optional)
A pointer to application defined callbacks for managing memory allocations.
Return Value
------------
A pointer to an object representing the decoder.
Remarks
-------
Close the decoder with drflac_close().
Close the decoder with drflac_close().
This will hold a handle to the file until the decoder is closed with drflac_close(). Some platforms will restrict the
number of files a process can have open at any given time, so keep this mind if you have many decoders open at the
same time.
See also: drflac_open(), drflac_open_file_with_metadata(), drflac_close()
Remarks
-------
This will hold a handle to the file until the decoder is closed with drflac_close(). Some platforms will restrict the number of files a process can have open
at any given time, so keep this mind if you have many decoders open at the same time.
Frees memory that was allocated internally by dr_flac.
Frees memory that was allocated internally by dr_flac.
Set pAllocationCallbacks to the same object that was passed to drflac_open_*_and_read_pcm_frames_*(). If you originally passed in NULL, pass in NULL for this.
Set pAllocationCallbacks to the same object that was passed to drflac_open_*_and_read_pcm_frames_*(). If you originally passed in NULL, pass in NULL for this.
#include <wchar.h> /* For wcslen(), wcsrtombs() */
/* drflac_result_from_errno() is only used for fopen() and wfopen() so putting it inside DR_WAV_NO_STDIO for now. If something else needs this later we can move it out. */
MP3 audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
MP3 audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
dr_mp3 - v0.5.6 - 2020-02-12
dr_mp3 - v0.6.0 - 2020-04-04
David Reid - mackron@gmail.com
David Reid - mackron@gmail.com
Based off minimp3 (https://github.com/lieff/minimp3) which is where the real work was done. See the bottom of this file for
GitHub: https://github.com/mackron/dr_libs
differences between minimp3 and dr_mp3.
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.
*/
*/
/*
/*
RELEASE NOTES - v0.5.0
RELEASE NOTES - VERSION 0.6
=======================
===========================
Version 0.5.0 has breaking API changes.
Version 0.6 includes breaking changes with the configuration of decoders. The ability to customize the number of output channels and the sample rate has been
removed. You must now use the channel count and sample rate reported by the MP3 stream itself, and all channel and sample rate conversion must be done
Improved Client-Defined Memory Allocation
yourself.
-----------------------------------------
The main change with this release is the addition of a more flexible way of implementing custom memory allocation routines. The
existing system of DRMP3_MALLOC, DRMP3_REALLOC and DRMP3_FREE are still in place and will be used by default when no custom
allocation callbacks are specified.
To use the new system, you pass in a pointer to a drmp3_allocation_callbacks object to drmp3_init() and family, like this:
The advantage of this new system is that it allows you to specify user data which will be passed in to the allocation routines.
Passing in null for the allocation callbacks object will cause dr_mp3 to use defaults which is the same as DRMP3_MALLOC,
DRMP3_REALLOC and DRMP3_FREE and the equivalent of how it worked in previous versions.
Every API that opens a drmp3 object now takes this extra parameter. These include the following:
Changes to Initialization
-------------------------
Previously, `drmp3_init()`, etc. took a pointer to a `drmp3_config` object that allowed you to customize the output channels and sample rate. This has been
removed. If you need the old behaviour you will need to convert the data yourself or just not upgrade. The following APIs have changed.
drmp3_init()
`drmp3_init()`
drmp3_init_file()
`drmp3_init_memory()`
drmp3_init_memory()
`drmp3_init_file()`
drmp3_open_and_read_pcm_frames_f32()
drmp3_open_and_read_pcm_frames_s16()
drmp3_open_memory_and_read_pcm_frames_f32()
drmp3_open_memory_and_read_pcm_frames_s16()
drmp3_open_file_and_read_pcm_frames_f32()
drmp3_open_file_and_read_pcm_frames_s16()
Renamed APIs
------------
The following APIs have been renamed for consistency with other dr_* libraries and to make it clear that they return PCM frame
dr_mp3 is a single-file library. To use it, do something like the following in one .c file.
dr_mp3 is a single file library. To use it, do something like the following in one .c file.
```c
#define DR_MP3_IMPLEMENTATION
#define DR_MP3_IMPLEMENTATION
#include "dr_mp3.h"
#include "dr_mp3.h"
```
You can then #include this file in other parts of the program as you would with any other header file. To decode audio data,
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:
do something like the following:
```c
drmp3 mp3;
drmp3 mp3;
if (!drmp3_init_file(&mp3, "MySong.mp3", NULL)) {
if (!drmp3_init_file(&mp3, "MySong.mp3", NULL)) {
// Failed to open file
// Failed to open file
...
@@ -91,28 +53,27 @@ do something like the following:
...
@@ -91,28 +53,27 @@ do something like the following:
The drmp3 object is transparent so you can get access to the channel count and sample rate like so:
The drmp3 object is transparent so you can get access to the channel count and sample rate like so:
```
drmp3_uint32 channels = mp3.channels;
drmp3_uint32 channels = mp3.channels;
drmp3_uint32 sampleRate = mp3.sampleRate;
drmp3_uint32 sampleRate = mp3.sampleRate;
```
The third parameter of drmp3_init_file() in the example above allows you to control the output channel count and sample rate. It
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
is a pointer to a drmp3_config object. Setting any of the variables of this object to 0 will cause dr_mp3 to use defaults.
`drmp3_init_memory()` and `drmp3_init()` respectively.
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 drmp3_init_memory() and drmp3_init() respectively.
You do not need to do any annoying memory management when reading PCM frames - this is all managed internally. You can request
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
any number of PCM frames in each call to drmp3_read_pcm_frames_f32() and it will return as many PCM frames as it can, up to the
call to `drmp3_read_pcm_frames_f32()` and it will return as many PCM frames as it can, up to the requested amount.
requested amount.
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
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
drmp3_open_file_and_read_pcm_frames_f32().
`drmp3_open_file_and_read_pcm_frames_f32()`.
OPTIONS
Build Options
=======
=============
#define these options before including this file.
#define these options before including this file.
#define DR_MP3_NO_STDIO
#define DR_MP3_NO_STDIO
...
@@ -129,32 +90,129 @@ OPTIONS
...
@@ -129,32 +90,129 @@ OPTIONS
extern"C"{
extern"C"{
#endif
#endif
#include <stddef.h>
#include <stddef.h> /* For size_t. */
#if defined(_MSC_VER) && _MSC_VER < 1600
/* Sized types. Prefer built-in types. Fall back to stdint. */
typedefdrmp3_uint64(*drmp3_src_read_proc)(drmp3_src*pSRC,drmp3_uint64frameCount,void*pFramesOut,void*pUserData);/* Returns the number of frames that were read. */
drmp3_uint32cacheSizeInFrames;/* The number of frames to read from the client at a time. */
}drmp3_src_config;
structdrmp3_src
{
drmp3_src_configconfig;
drmp3_src_read_proconRead;
void*pUserData;
floatbin[256];
drmp3_src_cachecache;/* <-- For simplifying and optimizing client -> memory reading. */
union
{
struct
{
doublealpha;
drmp3_bool32isPrevFramesLoaded:1;
drmp3_bool32isNextFramesLoaded:1;
}linear;
}algo;
};
typedefenum
typedefenum
{
{
...
@@ -313,8 +327,8 @@ typedef struct
...
@@ -313,8 +327,8 @@ typedef struct
typedefstruct
typedefstruct
{
{
drmp3_uint32outputChannels;
drmp3_uint32channels;
drmp3_uint32outputSampleRate;
drmp3_uint32sampleRate;
}drmp3_config;
}drmp3_config;
typedefstruct
typedefstruct
...
@@ -334,7 +348,6 @@ typedef struct
...
@@ -334,7 +348,6 @@ typedef struct
drmp3_uint8pcmFrames[sizeof(float)*DRMP3_MAX_SAMPLES_PER_FRAME];/* <-- Multipled by sizeof(float) to ensure there's enough room for DR_MP3_FLOAT_OUTPUT. */
drmp3_uint8pcmFrames[sizeof(float)*DRMP3_MAX_SAMPLES_PER_FRAME];/* <-- Multipled by sizeof(float) to ensure there's enough room for DR_MP3_FLOAT_OUTPUT. */
drmp3_uint64currentPCMFrame;/* The current PCM frame, globally, based on the output sample rate. Mainly used for seeking. */
drmp3_uint64currentPCMFrame;/* The current PCM frame, globally, based on the output sample rate. Mainly used for seeking. */
drmp3_uint64streamCursor;/* The current byte the decoder is sitting on in the raw stream. */
drmp3_uint64streamCursor;/* The current byte the decoder is sitting on in the raw stream. */
drmp3_srcsrc;
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. */
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. */
drmp3_uint32seekPointCount;/* The number of items in pSeekPoints. When set to 0 assumes to no seek table. Defaults to zero. */
drmp3_uint32seekPointCount;/* The number of items in pSeekPoints. When set to 0 assumes to no seek table. Defaults to zero. */
size_tdataSize;
size_tdataSize;
...
@@ -362,7 +375,7 @@ Close the loader with drmp3_uninit().
...
@@ -362,7 +375,7 @@ Close the loader with drmp3_uninit().
See also: drmp3_init_file(), drmp3_init_memory(), drmp3_uninit()
See also: drmp3_init_file(), drmp3_init_memory(), drmp3_uninit()
pcmFramesRead=drmp3dec_decode_frame(&pMP3->decoder,pMP3->pData,(int)pMP3->dataSize,pPCMFrames,&info);/* <-- Safe size_t -> int conversion thanks to the check above. */
pcmFramesRead=drmp3dec_decode_frame(&pMP3->decoder,pMP3->pData,(int)pMP3->dataSize,pPCMFrames,&info);/* <-- Safe size_t -> int conversion thanks to the check above. */
drmp3dec_f32_to_s16(tempF32,pBufferOut,(int)(pcmFramesJustRead*pMP3->channels));/* <-- Safe cast since pcmFramesJustRead will be clamped based on the size of tempF32 which is always small. */
Update resampler. This is wrong. Need to instead update it on a per MP3 frame basis. Also broken for cases when
the sample rate is being reduced in my testing. Should work fine when the input and output sample rate is the same
or a clean multiple.
*/
pMP3->src.algo.linear.alpha=(drmp3_int64)pMP3->currentPCMFrame*((double)pMP3->src.config.sampleRateIn/pMP3->src.config.sampleRateOut);/* <-- Cast to int64 is required for VC6. */