1 // FLAC audio decoder. Public domain. See "unlicense" statement at the end of this file.
2 // dr_flac - v0.3d - 11/06/2016
3 // commit eebbf6ed17e9200a48c8f83a350a82722295558f
5 // David Reid - mackron@gmail.com
7 // some fixes from v0.4f - 2017-03-10
8 // - Fix a couple of bugs with the bitstreaming code.
10 // fix from 767c3fbda48f54ce1050afa75110ae69cccdf0dd
12 // some fixes from v0.8d - 2017-09-22 (actually, one)
13 // k8 SKIPPED: Add support for decoding streams with ID3 tags. ID3 tags are just skipped.
14 // k8: i am absolutely not interested in such fucked flac files, and won't support that idiocy.
16 // D translation by Ketmar // Invisible Vector
17 module iv
.drflac
/*is aliced*/;
23 // dr_flac is a single-file library.
25 // To decode audio data, do something like the following:
27 // drflac* pFlac = drflac_open_file("MySong.flac");
28 // if (pFlac is null) {
29 // // Failed to open FLAC file
32 // int* pSamples = malloc(pFlac.totalSampleCount * (int)).sizeof;
33 // ulong numberOfInterleavedSamplesActuallyRead = drflac_read_s32(pFlac, pFlac.totalSampleCount, pSamples);
35 // The drflac object represents the decoder. It is a transparent type so all the information you need, such as the number of
36 // channels and the bits per sample, should be directly accessible - just make sure you don't change their values. Samples are
37 // always output as interleaved signed 32-bit PCM. In the example above a native FLAC stream was opened, however dr_flac has
38 // seamless support for Ogg encapsulated FLAC streams as well.
40 // 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
41 // 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
42 // samples, just call it again. Example:
44 // while (drflac_read_s32(pFlac, chunkSize, pChunkSamples) > 0) {
48 // You can seek to a specific sample with drflac_seek_to_sample(). The given sample is based on interleaving. So for example,
49 // 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.
50 // 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
54 // If you just want to quickly decode an entire FLAC file in one go you can do something like this:
58 // ulong totalSampleCount;
59 // int* pSampleData = drflac_open_and_decode_file("MySong.flac", &sampleRate, &channels, &totalSampleCount);
60 // if (pSampleData is null) {
61 // // Failed to open and decode FLAC file.
66 // drflac_free(pSampleData);
69 // If you need access to metadata (album art, etc.), use drflac_open_with_metadata(), drflac_open_file_with_metdata() or
70 // drflac_open_memory_with_metadata(). The rationale for keeping these APIs separate is that they're slightly slower than the
71 // normal versions and also just a little bit harder to use.
73 // dr_flac reports metadata to the application through the use of a callback, and every metadata block is reported before
74 // drflac_open_with_metdata() returns. See https://github.com/mackron/dr_libs_tests/blob/master/dr_flac/dr_flac_test_2.c for
75 // an example on how to read metadata.
80 // #define these options before including this file.
82 // #define DR_FLAC_NO_STDIO
83 // Disable drflac_open_file().
85 // #define DR_FLAC_NO_OGG
86 // Disables support for Ogg/FLAC streams.
88 // #define DR_FLAC_NO_WIN32_IO
89 // In the Win32 build, dr_flac uses the Win32 IO APIs for drflac_open_file() by default. This setting will make it use the
90 // standard FILE APIs instead. Ignored when DR_FLAC_NO_STDIO is #defined. (The rationale for this configuration is that
91 // there's a bug in one compiler's Win32 implementation of the FILE APIs which is not present in the Win32 IO APIs.)
93 // #define DR_FLAC_BUFFER_SIZE <number>
94 // Defines the size of the internal buffer to store data from onRead(). This buffer is used to reduce the number of calls
95 // back to the client for more data. Larger values means more memory, but better performance. My tests show diminishing
96 // returns after about 4KB (which is the default). Consider reducing this if you have a very efficient implementation of
97 // onRead(), or increase it if it's very inefficient. Must be a multiple of 8.
102 // - Based on my tests, the performance of the 32-bit build is at about parity with the reference implementation. The 64-bit build
103 // is slightly faster.
104 // - dr_flac does not currently do any CRC checks.
105 // - dr_flac should work fine with valid native FLAC files, but for broadcast streams it won't work if the header and STREAMINFO
106 // block is unavailable.
107 // - Audio data is output as signed 32-bit PCM, regardless of the bits per sample the FLAC stream is encoded as.
108 // - This has not been tested on big-endian architectures.
109 // - Rice codes in unencoded binary form (see https://xiph.org/flac/format.html#rice_partition) has not been tested. If anybody
110 // knows where I can find some test files for this, let me know.
111 // - Perverse and erroneous files have not been tested. Again, if you know where I can get some test files let me know.
112 // - dr_flac is not thread-safe, but it's APIs can be called from any thread so long as you do your own synchronization.
115 static if (is(typeof((){import iv
.vfs
;}()))) {
116 enum DrFlacHasVFS
= true;
119 enum DrFlacHasVFS
= false;
123 // As data is read from the client it is placed into an internal buffer for fast access. This controls the
124 // size of that buffer. Larger values means more speed, but also more memory. In my testing there is diminishing
125 // returns after about 4KB, but you can fiddle with this to suit your own needs. Must be a multiple of 8.
126 static if (!is(typeof(DR_FLAC_BUFFER_SIZE
))) enum DR_FLAC_BUFFER_SIZE
= 4096;
128 // Check if we can enable 64-bit optimizations.
129 //version = DRFLAC_64BIT;
131 version(DRFLAC_64BIT
) alias drflac_cache_t
= ulong; else alias drflac_cache_t
= uint;
133 // The various metadata block types.
134 enum DRFLAC_METADATA_BLOCK_TYPE_STREAMINFO
= 0;
135 enum DRFLAC_METADATA_BLOCK_TYPE_PADDING
= 1;
136 enum DRFLAC_METADATA_BLOCK_TYPE_APPLICATION
= 2;
137 enum DRFLAC_METADATA_BLOCK_TYPE_SEEKTABLE
= 3;
138 enum DRFLAC_METADATA_BLOCK_TYPE_VORBIS_COMMENT
= 4;
139 enum DRFLAC_METADATA_BLOCK_TYPE_CUESHEET
= 5;
140 enum DRFLAC_METADATA_BLOCK_TYPE_PICTURE
= 6;
141 enum DRFLAC_METADATA_BLOCK_TYPE_INVALID
= 127;
143 // The various picture types specified in the PICTURE block.
144 enum DRFLAC_PICTURE_TYPE_OTHER
= 0;
145 enum DRFLAC_PICTURE_TYPE_FILE_ICON
= 1;
146 enum DRFLAC_PICTURE_TYPE_OTHER_FILE_ICON
= 2;
147 enum DRFLAC_PICTURE_TYPE_COVER_FRONT
= 3;
148 enum DRFLAC_PICTURE_TYPE_COVER_BACK
= 4;
149 enum DRFLAC_PICTURE_TYPE_LEAFLET_PAGE
= 5;
150 enum DRFLAC_PICTURE_TYPE_MEDIA
= 6;
151 enum DRFLAC_PICTURE_TYPE_LEAD_ARTIST
= 7;
152 enum DRFLAC_PICTURE_TYPE_ARTIST
= 8;
153 enum DRFLAC_PICTURE_TYPE_CONDUCTOR
= 9;
154 enum DRFLAC_PICTURE_TYPE_BAND
= 10;
155 enum DRFLAC_PICTURE_TYPE_COMPOSER
= 11;
156 enum DRFLAC_PICTURE_TYPE_LYRICIST
= 12;
157 enum DRFLAC_PICTURE_TYPE_RECORDING_LOCATION
= 13;
158 enum DRFLAC_PICTURE_TYPE_DURING_RECORDING
= 14;
159 enum DRFLAC_PICTURE_TYPE_DURING_PERFORMANCE
= 15;
160 enum DRFLAC_PICTURE_TYPE_SCREEN_CAPTURE
= 16;
161 enum DRFLAC_PICTURE_TYPE_BRIGHT_COLORED_FISH
= 17;
162 enum DRFLAC_PICTURE_TYPE_ILLUSTRATION
= 18;
163 enum DRFLAC_PICTURE_TYPE_BAND_LOGOTYPE
= 19;
164 enum DRFLAC_PICTURE_TYPE_PUBLISHER_LOGOTYPE
= 20;
166 alias drflac_container
= int;
168 drflac_container_native
,
169 drflac_container_ogg
,
172 alias drflac_seek_origin
= int;
174 drflac_seek_origin_start
,
175 drflac_seek_origin_current
,
178 // Packing is important on this structure because we map this directly to the raw data within the SEEKTABLE metadata block.
180 align(2) struct drflac_seekpoint
{
183 ulong frameOffset
; // The offset from the first byte of the header of the first frame.
188 struct drflac_streaminfo
{
196 ulong totalSampleCount
;
200 struct drflac_metadata
{
201 // The metadata type. Use this to know how to interpret the data below.
204 // A pointer to the raw data. This points to a temporary buffer so don't hold on to it. It's best to
205 // not modify the contents of this buffer. Use the structures below for more meaningful and structured
206 // information about the metadata. It's possible for this to be null.
207 const(void)* pRawData
;
209 // The size in bytes of the block and the buffer pointed to by pRawData if it's non-null.
212 static struct Padding
{
216 static struct Application
{
222 static struct SeekTable
{
224 const(drflac_seekpoint
)* pSeekpoints
;
227 static struct VorbisComment
{
231 const(char)* comments
;
234 static struct CueSheet
{
236 ulong leadInSampleCount
;
239 const(ubyte)* pTrackData
;
242 static struct Picture
{
246 uint descriptionLength
;
247 const(char)* description
;
251 uint indexColorCount
;
252 uint pictureDataSize
;
253 const(ubyte)* pPictureData
;
257 drflac_streaminfo streaminfo
;
259 Application application
;
261 VorbisComment vorbis_comment
;
270 // Callback for when data needs to be read from the client.
272 // pUserData [in] The user data that was passed to drflac_open() and family.
273 // pBufferOut [out] The output buffer.
274 // bytesToRead [in] The number of bytes to read.
276 // Returns the number of bytes actually read.
277 alias drflac_read_proc
= usize
delegate (void* pUserData
, void* pBufferOut
, usize bytesToRead
);
279 // Callback for when data needs to be seeked.
281 // pUserData [in] The user data that was passed to drflac_open() and family.
282 // offset [in] The number of bytes to move, relative to the origin. Will never be negative.
283 // origin [in] The origin of the seek - the current position or the start of the stream.
285 // Returns whether or not the seek was successful.
287 // The offset will never be negative. Whether or not it is relative to the beginning or current position is determined
288 // by the "origin" parameter which will be either drflac_seek_origin_start or drflac_seek_origin_current.
289 alias drflac_seek_proc
= bool delegate (void* pUserData
, int offset
, drflac_seek_origin origin
);
291 // Callback for when a metadata block is read.
293 // pUserData [in] The user data that was passed to drflac_open() and family.
294 // pMetadata [in] A pointer to a structure containing the data of the metadata block.
296 // Use pMetadata.type to determine which metadata block is being handled and how to read the data.
297 alias drflac_meta_proc
= void delegate (void* pUserData
, drflac_metadata
* pMetadata
);
300 // Structure for internal use. Only used for decoders opened with drflac_open_memory.
301 struct drflac__memory_stream
{
304 usize currentReadPos
;
307 // Structure for internal use. Used for bit streaming.
309 // The function to call when more data needs to be read.
310 //drflac_read_proc onRead;
312 // The function to call when the current read position needs to be moved.
313 //drflac_seek_proc onSeek;
315 // The user data to pass around to onRead and onSeek.
320 bool stdio
; //k8: it is drflac's stdio shit
322 // The number of unaligned bytes in the L2 cache. This will always be 0 until the end of the stream is hit. At the end of the
323 // stream there will be a number of bytes that don't cleanly fit in an L1 cache line, so we use this variable to know whether
324 // or not the bistreamer needs to run on a slower path to read those last bytes. This will never be more than (drflac_cache_t).sizeof.
325 usize unalignedByteCount
;
327 // The content of the unaligned bytes.
328 drflac_cache_t unalignedCache
;
330 // The index of the next valid cache line in the "L2" cache.
333 // The number of bits that have been consumed by the cache. This is used to determine how many valid bits are remaining.
336 // The cached data which was most recently read from the client. There are two levels of cache. Data flows as such:
337 // Client . L2 . L1. The L2 . L1 movement is aligned and runs on a fast path in just a few instructions.
338 drflac_cache_t
[DR_FLAC_BUFFER_SIZE
/(drflac_cache_t
).sizeof
] cacheL2
;
339 drflac_cache_t cache
;
342 struct drflac_subframe
{
343 // The type of the subframe: SUBFRAME_CONSTANT, SUBFRAME_VERBATIM, SUBFRAME_FIXED or SUBFRAME_LPC.
346 // The number of wasted bits per sample as specified by the sub-frame header.
347 ubyte wastedBitsPerSample
;
349 // The order to use for the prediction stage for SUBFRAME_FIXED and SUBFRAME_LPC.
352 // The number of bits per sample for this subframe. This is not always equal to the current frame's bit per sample because
353 // an extra bit is required for side channels when interchannel decorrelation is being used.
356 // A pointer to the buffer containing the decoded samples in the subframe. This pointer is an offset from drflac::pExtraData, or
357 // null if the heap is not being used. Note that it's a signed 32-bit integer for each value.
358 int* pDecodedSamples
;
361 struct drflac_frame_header
{
362 // If the stream uses variable block sizes, this will be set to the index of the first sample. If fixed block sizes are used, this will
363 // always be set to 0.
366 // If the stream uses fixed block sizes, this will be set to the frame number. If variable block sizes are used, this will always be 0.
369 // The sample rate of this frame.
372 // The number of samples in each sub-frame within this frame.
375 // The channel assignment of this frame. This is not always set to the channel count. If interchannel decorrelation is being used this
376 // will be set to DRFLAC_CHANNEL_ASSIGNMENT_LEFT_SIDE, DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE or DRFLAC_CHANNEL_ASSIGNMENT_MID_SIDE.
377 ubyte channelAssignment
;
379 // The number of bits per sample within this frame.
382 // The frame's CRC. This is set, but unused at the moment.
386 struct drflac_frame
{
388 drflac_frame_header header
;
390 // The number of samples left to be read in this frame. This is initially set to the block size multiplied by the channel count. As samples
391 // are read, this will be decremented. When it reaches 0, the decoder will see this frame as fully consumed and load the next frame.
392 uint samplesRemaining
;
394 // The list of sub-frames within the frame. There is one sub-frame for each channel, and there's a maximum of 8 channels.
395 drflac_subframe
[8] subframes
;
399 // The function to call when a metadata block is read.
400 //drflac_meta_proc onMeta;
402 // The user data posted to the metadata callback function.
406 // The sample rate. Will be set to something like 44100.
409 // The number of channels. This will be set to 1 for monaural streams, 2 for stereo, etc. Maximum 8. This is set based on the
410 // value specified in the STREAMINFO block.
413 // The bits per sample. Will be set to somthing like 16, 24, etc.
416 // The maximum block size, in samples. This number represents the number of samples in each channel (not combined).
419 // The total number of samples making up the stream. This includes every channel. For example, if the stream has 2 channels,
420 // with each channel having a total of 4096, this value will be set to 2*4096 = 8192. Can be 0 in which case it's still a
421 // valid stream, but just means the total sample count is unknown. Likely the case with streams like internet radio.
422 ulong totalSampleCount
;
425 // The container type. This is set based on whether or not the decoder was opened from a native or Ogg stream.
426 drflac_container container
;
429 // The position of the seektable in the file.
432 // The size of the seektable.
436 // Information about the frame the decoder is currently sitting on.
437 drflac_frame currentFrame
;
439 // The position of the first frame in the stream. This is only ever used for seeking.
443 // A hack to avoid a malloc() when opening a decoder with drflac_open_memory().
444 drflac__memory_stream memoryStream
;
447 // A pointer to the decoded sample data. This is an offset of pExtraData.
448 int* pDecodedSamples
;
451 // The bit streamer. The raw FLAC data is fed through this object.
454 // Variable length extra data. We attach this to the end of the object so we avoid unnecessary mallocs.
459 // Opens a FLAC decoder.
461 // onRead [in] The function to call when data needs to be read from the client.
462 // onSeek [in] The function to call when the read position of the client data needs to move.
463 // pUserData [in, optional] A pointer to application defined data that will be passed to onRead and onSeek.
465 // Returns a pointer to an object representing the decoder.
467 // Close the decoder with drflac_close().
469 // This function will automatically detect whether or not you are attempting to open a native or Ogg encapsulated
470 // FLAC, both of which should work seamlessly without any manual intervention. Ogg encapsulation also works with
471 // multiplexed streams which basically means it can play FLAC encoded audio tracks in videos.
473 // This is the lowest level function for opening a FLAC stream. You can also use drflac_open_file() and drflac_open_memory()
474 // to open the stream from a file or from a block of memory respectively.
476 // The STREAMINFO block must be present for this to succeed.
478 // See also: drflac_open_file(), drflac_open_memory(), drflac_open_with_metadata(), drflac_close()
479 //drflac* drflac_open(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData);
481 // Opens a FLAC decoder and notifies the caller of the metadata chunks (album art, etc.).
483 // onRead [in] The function to call when data needs to be read from the client.
484 // onSeek [in] The function to call when the read position of the client data needs to move.
485 // onMeta [in] The function to call for every metadata block.
486 // pUserData [in, optional] A pointer to application defined data that will be passed to onRead, onSeek and onMeta.
488 // Returns a pointer to an object representing the decoder.
490 // Close the decoder with drflac_close().
492 // This is slower that drflac_open(), so avoid this one if you don't need metadata. Internally, this will do a malloc()
493 // and free() for every metadata block except for STREAMINFO and PADDING blocks.
495 // The caller is notified of the metadata via the onMeta callback. All metadata blocks withh be handled before the function
498 // See also: drflac_open_file_with_metadata(), drflac_open_memory_with_metadata(), drflac_open(), drflac_close()
499 //drflac* drflac_open_with_metadata(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData);
501 // Closes the given FLAC decoder.
503 // pFlac [in] The decoder to close.
505 // This will destroy the decoder object.
506 //void drflac_close(drflac* pFlac);
509 // Reads sample data from the given FLAC decoder, output as interleaved signed 32-bit PCM.
511 // pFlac [in] The decoder.
512 // samplesToRead [in] The number of samples to read.
513 // pBufferOut [out, optional] A pointer to the buffer that will receive the decoded samples.
515 // Returns the number of samples actually read.
517 // pBufferOut can be null, in which case the call will act as a seek, and the return value will be the number of samples
519 //ulong drflac_read_s32(drflac* pFlac, ulong samplesToRead, int* pBufferOut);
521 // Seeks to the sample at the given index.
523 // pFlac [in] The decoder.
524 // sampleIndex [in] The index of the sample to seek to. See notes below.
526 // Returns true if successful; false otherwise.
528 // The sample index is based on interleaving. In a stereo stream, for example, the sample at index 0 is the first sample
529 // in the left channel; the sample at index 1 is the first sample on the right channel, and so on.
531 // When seeking, you will likely want to ensure it's rounded to a multiple of the channel count. You can do this with
532 // something like drflac_seek_to_sample(pFlac, (mySampleIndex + (mySampleIndex % pFlac.channels)))
533 //bool drflac_seek_to_sample(drflac* pFlac, ulong sampleIndex);
536 // Opens a FLAC decoder from the file at the given path.
538 // filename [in] The path of the file to open, either absolute or relative to the current directory.
540 // Returns a pointer to an object representing the decoder.
542 // Close the decoder with drflac_close().
544 // This will hold a handle to the file until the decoder is closed with drflac_close(). Some platforms will restrict the
545 // number of files a process can have open at any given time, so keep this mind if you have many decoders open at the
548 // See also: drflac_open(), drflac_open_file_with_metadata(), drflac_close()
549 //drflac* drflac_open_file(const(char)[] filename);
551 // Opens a FLAC decoder from the file at the given path and notifies the caller of the metadata chunks (album art, etc.)
553 // Look at the documentation for drflac_open_with_metadata() for more information on how metadata is handled.
554 //drflac* drflac_open_file_with_metadata(const(char)[] filename, drflac_meta_proc onMeta, void* pUserData);
556 // Opens a FLAC decoder from a pre-allocated block of memory
558 // This does not create a copy of the data. It is up to the application to ensure the buffer remains valid for
559 // the lifetime of the decoder.
560 //drflac* drflac_open_memory(const void* data, usize dataSize);
562 // Opens a FLAC decoder from a pre-allocated block of memory and notifies the caller of the metadata chunks (album art, etc.)
564 // Look at the documentation for drflac_open_with_metadata() for more information on how metadata is handled.
565 //drflac* drflac_open_memory_with_metadata(const void* data, usize dataSize, drflac_meta_proc onMeta, void* pUserData);
569 //// High Level APIs ////
571 // Opens a FLAC stream from the given callbacks and fully decodes it in a single operation. The return value is a
572 // pointer to the sample data as interleaved signed 32-bit PCM. The returned data must be freed with drflac_free().
574 // Sometimes a FLAC file won't keep track of the total sample count. In this situation the function will continuously
575 // read samples into a dynamically sized buffer on the heap until no samples are left.
577 // Do not call this function on a broadcast type of stream (like internet radio streams and whatnot).
578 //int* drflac_open_and_decode(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, uint* sampleRate, uint* channels, ulong* totalSampleCount);
580 //#ifndef DR_FLAC_NO_STDIO
581 // Same as drflac_open_and_decode() except opens the decoder from a file.
582 //int* drflac_open_and_decode_file(const(char)[] filename, uint* sampleRate, uint* channels, ulong* totalSampleCount);
585 // Same as drflac_open_and_decode() except opens the decoder from a block of memory.
586 //int* drflac_open_and_decode_memory(const void* data, usize dataSize, uint* sampleRate, uint* channels, ulong* totalSampleCount);
588 // Frees data returned by drflac_open_and_decode_*().
589 //void drflac_free(void* pSampleDataReturnedByOpenAndDecode);
592 // Structure representing an iterator for vorbis comments in a VORBIS_COMMENT metadata block.
593 struct drflac_vorbis_comment_iterator
{
595 const(char)* pRunningData
;
598 // Initializes a vorbis comment iterator. This can be used for iterating over the vorbis comments in a VORBIS_COMMENT
600 //void drflac_init_vorbis_comment_iterator(drflac_vorbis_comment_iterator* pIter, uint commentCount, const(char)* pComments);
602 // Goes to the next vorbis comment in the given iterator. If null is returned it means there are no more comments. The
603 // returned string is NOT null terminated.
604 //const(char)* drflac_next_vorbis_comment(drflac_vorbis_comment_iterator* pIter, uint* pCommentLengthOut);
607 ///////////////////////////////////////////////////////////////////////////////
611 ///////////////////////////////////////////////////////////////////////////////
613 enum DRFLAC_SUBFRAME_CONSTANT
= 0;
614 enum DRFLAC_SUBFRAME_VERBATIM
= 1;
615 enum DRFLAC_SUBFRAME_FIXED
= 8;
616 enum DRFLAC_SUBFRAME_LPC
= 32;
617 enum DRFLAC_SUBFRAME_RESERVED
= 255;
619 enum DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE
= 0;
620 enum DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE2
= 1;
622 enum DRFLAC_CHANNEL_ASSIGNMENT_INDEPENDENT
= 0;
623 enum DRFLAC_CHANNEL_ASSIGNMENT_LEFT_SIDE
= 8;
624 enum DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE
= 9;
625 enum DRFLAC_CHANNEL_ASSIGNMENT_MID_SIDE
= 10;
628 //// Endian Management ////
629 version(LittleEndian
) enum drflac__is_little_endian
= true; else enum drflac__is_little_endian
= false;
631 ushort drflac__be2host_16 (ushort n
) pure nothrow @safe @nogc {
632 static if (__VERSION__
> 2067) pragma(inline
, true);
633 version(LittleEndian
) {
634 return cast(ushort)((n
>>8)|
((n
&0xff)<<8));
640 uint drflac__be2host_32 (uint n
) pure nothrow @safe @nogc {
641 static if (__VERSION__
> 2067) pragma(inline
, true);
642 version(LittleEndian
) {
643 import core
.bitop
: bswap;
650 ulong drflac__be2host_64 (ulong n
) pure nothrow @safe @nogc {
651 static if (__VERSION__
> 2067) pragma(inline
, true);
652 version(LittleEndian
) {
653 import core
.bitop
: bswap;
655 auto n0
= cast(ulong)bswap(cast(uint)n
);
656 auto n1
= cast(ulong)bswap(cast(uint)(n
>>32));
667 uint drflac__le2host_32 (uint n
) pure nothrow @safe @nogc {
668 static if (__VERSION__
> 2067) pragma(inline
, true);
669 version(LittleEndian
) {
672 import core
.bitop
: bswap;
678 version(DRFLAC_64BIT
) {
679 alias drflac__be2host__cache_line
= drflac__be2host_64
;
681 alias drflac__be2host__cache_line
= drflac__be2host_32
;
684 // BIT READING ATTEMPT #2
686 // This uses a 32- or 64-bit bit-shifted cache - as bits are read, the cache is shifted such that the first valid bit is sitting
687 // on the most significant bit. It uses the notion of an L1 and L2 cache (borrowed from CPU architecture), where the L1 cache
688 // is a 32- or 64-bit unsigned integer (depending on whether or not a 32- or 64-bit build is being compiled) and the L2 is an
689 // array of "cache lines", with each cache line being the same size as the L1. The L2 is a buffer of about 4KB and is where data
690 // from onRead() is read into.
691 enum DRFLAC_CACHE_L1_SIZE_BYTES(string bs
) = "((("~bs
~").cache).sizeof)";
692 enum DRFLAC_CACHE_L1_SIZE_BITS(string bs
) = "((("~bs
~").cache).sizeof*8)";
693 enum DRFLAC_CACHE_L1_BITS_REMAINING(string bs
) = "("~DRFLAC_CACHE_L1_SIZE_BITS
!(bs
)~"-(("~bs
~").consumedBits))";
694 version(DRFLAC_64BIT
) {
695 enum DRFLAC_CACHE_L1_SELECTION_MASK(string _bitCount
) = "(~((cast(ulong)-1L)>>("~_bitCount
~")))";
697 enum DRFLAC_CACHE_L1_SELECTION_MASK(string _bitCount
) = "(~((cast(uint)-1)>>("~_bitCount
~")))";
699 enum DRFLAC_CACHE_L1_SELECTION_SHIFT(string bs
, string _bitCount
) = "("~DRFLAC_CACHE_L1_SIZE_BITS
!bs
~"-("~_bitCount
~"))";
700 enum DRFLAC_CACHE_L1_SELECT(string bs
, string _bitCount
) = "((("~bs
~").cache)&"~DRFLAC_CACHE_L1_SELECTION_MASK
!_bitCount
~")";
701 enum DRFLAC_CACHE_L1_SELECT_AND_SHIFT(string bs
, string _bitCount
) = "("~DRFLAC_CACHE_L1_SELECT
!(bs
, _bitCount
)~">>"~DRFLAC_CACHE_L1_SELECTION_SHIFT
!(bs
, _bitCount
)~")";
702 enum DRFLAC_CACHE_L2_SIZE_BYTES(string bs
) = "((("~bs
~").cacheL2).sizeof)";
703 enum DRFLAC_CACHE_L2_LINE_COUNT(string bs
) = "("~DRFLAC_CACHE_L2_SIZE_BYTES
!bs
~"/(("~bs
~").cacheL2[0]).sizeof)";
704 enum DRFLAC_CACHE_L2_LINES_REMAINING(string bs
) = "("~DRFLAC_CACHE_L2_LINE_COUNT
!bs
~"-("~bs
~").nextL2Line)";
706 bool drflac__reload_l1_cache_from_l2 (drflac_bs
* bs
) {
707 // Fast path. Try loading straight from L2.
708 if (bs
.nextL2Line
< mixin(DRFLAC_CACHE_L2_LINE_COUNT
!"bs")) {
709 bs
.cache
= bs
.cacheL2
.ptr
[bs
.nextL2Line
++];
713 // If we get here it means we've run out of data in the L2 cache. We'll need to fetch more from the client, if there's any left.
714 if (bs
.unalignedByteCount
> 0) return false; // If we have any unaligned bytes it means there's no more aligned bytes left in the client.
716 usize bytesRead
= bs
.rs
.read(bs
.cacheL2
.ptr
, mixin(DRFLAC_CACHE_L2_SIZE_BYTES
!"bs"));
719 if (bytesRead
== mixin(DRFLAC_CACHE_L2_SIZE_BYTES
!"bs")) {
720 bs
.cache
= bs
.cacheL2
.ptr
[bs
.nextL2Line
++];
724 // If we get here it means we were unable to retrieve enough data to fill the entire L2 cache. It probably
725 // means we've just reached the end of the file. We need to move the valid data down to the end of the buffer
726 // and adjust the index of the next line accordingly. Also keep in mind that the L2 cache must be aligned to
727 // the size of the L1 so we'll need to seek backwards by any misaligned bytes.
728 usize alignedL1LineCount
= bytesRead
/mixin(DRFLAC_CACHE_L1_SIZE_BYTES
!"bs");
730 // We need to keep track of any unaligned bytes for later use.
731 bs
.unalignedByteCount
= bytesRead
-(alignedL1LineCount
*mixin(DRFLAC_CACHE_L1_SIZE_BYTES
!"bs"));
732 if (bs
.unalignedByteCount
> 0) {
733 bs
.unalignedCache
= bs
.cacheL2
.ptr
[alignedL1LineCount
];
736 if (alignedL1LineCount
> 0) {
737 usize offset
= mixin(DRFLAC_CACHE_L2_LINE_COUNT
!"bs")-alignedL1LineCount
;
738 for (usize i
= alignedL1LineCount
; i
> 0; --i
) bs
.cacheL2
.ptr
[i
-1+offset
] = bs
.cacheL2
.ptr
[i
-1];
739 bs
.nextL2Line
= offset
;
740 bs
.cache
= bs
.cacheL2
.ptr
[bs
.nextL2Line
++];
743 // If we get into this branch it means we weren't able to load any L1-aligned data.
744 bs
.nextL2Line
= mixin(DRFLAC_CACHE_L2_LINE_COUNT
!"bs");
749 bool drflac__reload_cache (drflac_bs
* bs
) {
750 // Fast path. Try just moving the next value in the L2 cache to the L1 cache.
751 if (drflac__reload_l1_cache_from_l2(bs
)) {
752 bs
.cache
= drflac__be2host__cache_line(bs
.cache
);
759 // If we get here it means we have failed to load the L1 cache from the L2. Likely we've just reached the end of the stream and the last
760 // few bytes did not meet the alignment requirements for the L2 cache. In this case we need to fall back to a slower path and read the
761 // data from the unaligned cache.
762 usize bytesRead
= bs
.unalignedByteCount
;
763 if (bytesRead
== 0) return false;
765 assert(bytesRead
< mixin(DRFLAC_CACHE_L1_SIZE_BYTES
!"bs"));
766 bs
.consumedBits
= (mixin(DRFLAC_CACHE_L1_SIZE_BYTES
!"bs")-bytesRead
)*8;
768 bs
.cache
= drflac__be2host__cache_line(bs
.unalignedCache
);
769 //bs.cache &= DRFLAC_CACHE_L1_SELECTION_MASK(DRFLAC_CACHE_L1_SIZE_BITS(bs)-bs.consumedBits);
770 bs
.cache
&= mixin(DRFLAC_CACHE_L1_SELECTION_MASK
!(DRFLAC_CACHE_L1_SIZE_BITS
!"bs"~"-bs.consumedBits"));
771 // <-- Make sure the consumed bits are always set to zero. Other parts of the library depend on this property.
772 bs
.unalignedByteCount
= 0; // <-- At this point the unaligned bytes have been moved into the cache and we thus have no more unaligned bytes.
776 void drflac__reset_cache (drflac_bs
* bs
) {
777 bs
.nextL2Line
= mixin(DRFLAC_CACHE_L2_LINE_COUNT
!"bs"); // <-- This clears the L2 cache.
778 bs
.consumedBits
= mixin(DRFLAC_CACHE_L1_SIZE_BITS
!"bs"); // <-- This clears the L1 cache.
780 bs
.unalignedByteCount
= 0; // <-- This clears the trailing unaligned bytes.
781 bs
.unalignedCache
= 0;
784 bool drflac__seek_bits (drflac_bs
* bs
, usize bitsToSeek
) {
785 if (bitsToSeek
<= mixin(DRFLAC_CACHE_L1_BITS_REMAINING
!"bs")) {
786 bs
.consumedBits
+= bitsToSeek
;
787 bs
.cache
<<= bitsToSeek
;
790 // It straddles the cached data. This function isn't called too frequently so I'm favouring simplicity here.
791 bitsToSeek
-= mixin(DRFLAC_CACHE_L1_BITS_REMAINING
!"bs");
792 bs
.consumedBits
+= mixin(DRFLAC_CACHE_L1_BITS_REMAINING
!"bs");
795 usize wholeBytesRemainingToSeek
= bitsToSeek
/8;
796 if (wholeBytesRemainingToSeek
> 0) {
797 // The next bytes to seek will be located in the L2 cache. The problem is that the L2 cache is not byte aligned,
798 // but rather DRFLAC_CACHE_L1_SIZE_BYTES aligned (usually 4 or 8). If, for example, the number of bytes to seek is
799 // 3, we'll need to handle it in a special way.
800 usize wholeCacheLinesRemaining
= wholeBytesRemainingToSeek
/mixin(DRFLAC_CACHE_L1_SIZE_BYTES
!"bs");
801 if (wholeCacheLinesRemaining
< mixin(DRFLAC_CACHE_L2_LINES_REMAINING
!"bs")) {
802 wholeBytesRemainingToSeek
-= wholeCacheLinesRemaining
*mixin(DRFLAC_CACHE_L1_SIZE_BYTES
!"bs");
803 bitsToSeek
-= wholeCacheLinesRemaining
*mixin(DRFLAC_CACHE_L1_SIZE_BITS
!"bs");
804 bs
.nextL2Line
+= wholeCacheLinesRemaining
;
806 wholeBytesRemainingToSeek
-= mixin(DRFLAC_CACHE_L2_LINES_REMAINING
!"bs")*mixin(DRFLAC_CACHE_L1_SIZE_BYTES
!"bs");
807 bitsToSeek
-= mixin(DRFLAC_CACHE_L2_LINES_REMAINING
!"bs")*mixin(DRFLAC_CACHE_L1_SIZE_BITS
!"bs");
808 bs
.nextL2Line
+= mixin(DRFLAC_CACHE_L2_LINES_REMAINING
!"bs");
809 // Note that we only seek on the client side if it's got any data left to seek. We can know this by checking
810 // if we have any unaligned data which can be determined with bs->unalignedByteCount.
811 if (wholeBytesRemainingToSeek
> 0 && bs
.unalignedByteCount
== 0) {
812 if (!bs
.rs
.seek(cast(int)wholeBytesRemainingToSeek
, drflac_seek_origin_current
)) return false;
813 bitsToSeek
-= wholeBytesRemainingToSeek
*8;
817 if (bitsToSeek
> 0) {
818 if (!drflac__reload_cache(bs
)) return false;
819 return drflac__seek_bits(bs
, bitsToSeek
);
825 bool drflac__read_uint32 (drflac_bs
* bs
, uint bitCount
, uint* pResultOut
) {
827 assert(pResultOut
!is null);
828 assert(bitCount
> 0);
829 assert(bitCount
<= 32);
831 if (bs
.consumedBits
== mixin(DRFLAC_CACHE_L1_SIZE_BITS
!"bs")) {
832 if (!drflac__reload_cache(bs
)) return false;
835 if (bitCount
<= mixin(DRFLAC_CACHE_L1_BITS_REMAINING
!"bs")) {
836 if (bitCount
< mixin(DRFLAC_CACHE_L1_SIZE_BITS
!"bs")) {
837 *pResultOut
= cast(uint)mixin(DRFLAC_CACHE_L1_SELECT_AND_SHIFT
!("bs", "bitCount")); //k8
838 bs
.consumedBits
+= bitCount
;
839 bs
.cache
<<= bitCount
;
841 *pResultOut
= cast(uint)bs
.cache
;
842 bs
.consumedBits
= mixin(DRFLAC_CACHE_L1_SIZE_BITS
!"bs");
847 // It straddles the cached data. It will never cover more than the next chunk. We just read the number in two parts and combine them.
848 usize bitCountHi
= mixin(DRFLAC_CACHE_L1_BITS_REMAINING
!"bs");
849 usize bitCountLo
= bitCount
-bitCountHi
;
850 uint resultHi
= cast(uint)mixin(DRFLAC_CACHE_L1_SELECT_AND_SHIFT
!("bs", "bitCountHi")); //k8
851 if (!drflac__reload_cache(bs
)) return false;
852 *pResultOut
= cast(uint)((resultHi
<<bitCountLo
)|
mixin(DRFLAC_CACHE_L1_SELECT_AND_SHIFT
!("bs", "bitCountLo"))); //k8
853 bs
.consumedBits
+= bitCountLo
;
854 bs
.cache
<<= bitCountLo
;
859 bool drflac__read_int32 (drflac_bs
* bs
, uint bitCount
, int* pResult
) {
861 assert(pResult
!is null);
862 assert(bitCount
> 0);
863 assert(bitCount
<= 32);
866 if (!drflac__read_uint32(bs
, bitCount
, &result
)) return false;
868 uint signbit
= ((result
>>(bitCount
-1))&0x01);
869 result |
= (~signbit
+1)<<bitCount
;
871 *pResult
= cast(int)result
;
875 bool drflac__read_uint64 (drflac_bs
* bs
, uint bitCount
, ulong* pResultOut
) {
876 assert(bitCount
<= 64);
877 assert(bitCount
> 32);
880 if (!drflac__read_uint32(bs
, bitCount
-32, &resultHi
)) return false;
883 if (!drflac__read_uint32(bs
, 32, &resultLo
)) return false;
885 *pResultOut
= ((cast(ulong)resultHi
)<<32)|
(cast(ulong)resultLo
);
889 bool drflac__read_uint16 (drflac_bs
* bs
, uint bitCount
, ushort* pResult
) {
891 assert(pResult
!is null);
892 assert(bitCount
> 0);
893 assert(bitCount
<= 16);
896 if (!drflac__read_uint32(bs
, bitCount
, &result
)) return false;
898 *pResult
= cast(ushort)result
;
902 bool drflac__read_int16 (drflac_bs
* bs
, uint bitCount
, short* pResult
) {
904 assert(pResult
!is null);
905 assert(bitCount
> 0);
906 assert(bitCount
<= 16);
909 if (!drflac__read_int32(bs
, bitCount
, &result
)) return false;
911 *pResult
= cast(short)result
;
915 bool drflac__read_uint8 (drflac_bs
* bs
, uint bitCount
, ubyte* pResult
) {
917 assert(pResult
!is null);
918 assert(bitCount
> 0);
919 assert(bitCount
<= 8);
922 if (!drflac__read_uint32(bs
, bitCount
, &result
)) return false;
924 *pResult
= cast(ubyte)result
;
928 bool drflac__read_int8 (drflac_bs
* bs
, uint bitCount
, byte* pResult
) {
930 assert(pResult
!is null);
931 assert(bitCount
> 0);
932 assert(bitCount
<= 8);
935 if (!drflac__read_int32(bs
, bitCount
, &result
)) return false;
937 *pResult
= cast(byte)result
;
942 bool drflac__seek_past_next_set_bit (drflac_bs
* bs
, uint* pOffsetOut
) {
943 uint zeroCounter
= 0;
944 while (bs
.cache
== 0) {
945 zeroCounter
+= cast(uint)mixin(DRFLAC_CACHE_L1_BITS_REMAINING
!"bs");
946 if (!drflac__reload_cache(bs
)) return false;
949 // At this point the cache should not be zero, in which case we know the first set bit should be somewhere in here. There is
950 // no need for us to perform any cache reloading logic here which should make things much faster.
951 assert(bs
.cache
!= 0);
953 static immutable uint[16] bitOffsetTable
= [
958 1, 1, 1, 1, 1, 1, 1, 1
961 uint setBitOffsetPlus1
= bitOffsetTable
.ptr
[mixin(DRFLAC_CACHE_L1_SELECT_AND_SHIFT
!("bs", "4"))];
962 if (setBitOffsetPlus1
== 0) {
964 setBitOffsetPlus1
= mixin(DRFLAC_CACHE_L1_SIZE_BITS
!"bs");
966 setBitOffsetPlus1
= 5;
968 if ((bs
.cache
&mixin(DRFLAC_CACHE_L1_SELECT
!("bs", "setBitOffsetPlus1")))) break;
969 setBitOffsetPlus1
+= 1;
974 bs
.consumedBits
+= setBitOffsetPlus1
;
975 bs
.cache
<<= setBitOffsetPlus1
;
977 *pOffsetOut
= zeroCounter
+setBitOffsetPlus1
-1;
982 bool drflac__seek_to_byte (drflac_bs
* bs
, ulong offsetFromStart
) {
984 assert(offsetFromStart
> 0);
986 // Seeking from the start is not quite as trivial as it sounds because the onSeek callback takes a signed 32-bit integer (which
987 // is intentional because it simplifies the implementation of the onSeek callbacks), however offsetFromStart is unsigned 64-bit.
988 // To resolve we just need to do an initial seek from the start, and then a series of offset seeks to make up the remainder.
989 if (offsetFromStart
> 0x7FFFFFFF) {
990 ulong bytesRemaining
= offsetFromStart
;
991 if (!bs
.rs
.seek(0x7FFFFFFF, drflac_seek_origin_start
)) return false;
992 bytesRemaining
-= 0x7FFFFFFF;
993 while (bytesRemaining
> 0x7FFFFFFF) {
994 if (!bs
.rs
.seek(0x7FFFFFFF, drflac_seek_origin_current
)) return false;
995 bytesRemaining
-= 0x7FFFFFFF;
997 if (bytesRemaining
> 0) {
998 if (!bs
.rs
.seek(cast(int)bytesRemaining
, drflac_seek_origin_current
)) return false;
1001 if (!bs
.rs
.seek(cast(int)offsetFromStart
, drflac_seek_origin_start
)) return false;
1003 // The cache should be reset to force a reload of fresh data from the client.
1004 drflac__reset_cache(bs
);
1009 bool drflac__read_utf8_coded_number (drflac_bs
* bs
, ulong* pNumberOut
) {
1010 assert(bs
!is null);
1011 assert(pNumberOut
!is null);
1014 if (!drflac__read_uint8(bs
, 8, utf8
.ptr
)) {
1019 if ((utf8
.ptr
[0]&0x80) == 0) {
1020 *pNumberOut
= utf8
.ptr
[0];
1025 if ((utf8
.ptr
[0]&0xE0) == 0xC0) byteCount
= 2;
1026 else if ((utf8
.ptr
[0]&0xF0) == 0xE0) byteCount
= 3;
1027 else if ((utf8
.ptr
[0]&0xF8) == 0xF0) byteCount
= 4;
1028 else if ((utf8
.ptr
[0]&0xFC) == 0xF8) byteCount
= 5;
1029 else if ((utf8
.ptr
[0]&0xFE) == 0xFC) byteCount
= 6;
1030 else if ((utf8
.ptr
[0]&0xFF) == 0xFE) byteCount
= 7;
1031 else { *pNumberOut
= 0; return false; } // Bad UTF-8 encoding.
1033 // Read extra bytes.
1034 assert(byteCount
> 1);
1036 ulong result
= cast(ulong)(utf8
.ptr
[0]&(0xFF>>(byteCount
+1)));
1037 for (int i
= 1; i
< byteCount
; ++i
) {
1038 if (!drflac__read_uint8(bs
, 8, utf8
.ptr
+i
)) {
1042 result
= (result
<<6)|
(utf8
.ptr
[i
]&0x3F);
1045 *pNumberOut
= result
;
1050 bool drflac__read_and_seek_rice (drflac_bs
* bs
, ubyte m
) {
1052 if (!drflac__seek_past_next_set_bit(bs
, &unused
)) return false;
1054 if (!drflac__seek_bits(bs
, m
)) return false;
1060 // The next two functions are responsible for calculating the prediction.
1062 // When the bits per sample is >16 we need to use 64-bit integer arithmetic because otherwise we'll run out of precision. It's
1063 // safe to assume this will be slower on 32-bit platforms so we use a more optimal solution when the bits per sample is <=16.
1064 int drflac__calculate_prediction_32 (uint order
, int shift
, const(short)* coefficients
, int* pDecodedSamples
) {
1065 assert(order
<= 32);
1068 case 32: prediction
+= coefficients
[31]*pDecodedSamples
[-32]; goto case;
1069 case 31: prediction
+= coefficients
[30]*pDecodedSamples
[-31]; goto case;
1070 case 30: prediction
+= coefficients
[29]*pDecodedSamples
[-30]; goto case;
1071 case 29: prediction
+= coefficients
[28]*pDecodedSamples
[-29]; goto case;
1072 case 28: prediction
+= coefficients
[27]*pDecodedSamples
[-28]; goto case;
1073 case 27: prediction
+= coefficients
[26]*pDecodedSamples
[-27]; goto case;
1074 case 26: prediction
+= coefficients
[25]*pDecodedSamples
[-26]; goto case;
1075 case 25: prediction
+= coefficients
[24]*pDecodedSamples
[-25]; goto case;
1076 case 24: prediction
+= coefficients
[23]*pDecodedSamples
[-24]; goto case;
1077 case 23: prediction
+= coefficients
[22]*pDecodedSamples
[-23]; goto case;
1078 case 22: prediction
+= coefficients
[21]*pDecodedSamples
[-22]; goto case;
1079 case 21: prediction
+= coefficients
[20]*pDecodedSamples
[-21]; goto case;
1080 case 20: prediction
+= coefficients
[19]*pDecodedSamples
[-20]; goto case;
1081 case 19: prediction
+= coefficients
[18]*pDecodedSamples
[-19]; goto case;
1082 case 18: prediction
+= coefficients
[17]*pDecodedSamples
[-18]; goto case;
1083 case 17: prediction
+= coefficients
[16]*pDecodedSamples
[-17]; goto case;
1084 case 16: prediction
+= coefficients
[15]*pDecodedSamples
[-16]; goto case;
1085 case 15: prediction
+= coefficients
[14]*pDecodedSamples
[-15]; goto case;
1086 case 14: prediction
+= coefficients
[13]*pDecodedSamples
[-14]; goto case;
1087 case 13: prediction
+= coefficients
[12]*pDecodedSamples
[-13]; goto case;
1088 case 12: prediction
+= coefficients
[11]*pDecodedSamples
[-12]; goto case;
1089 case 11: prediction
+= coefficients
[10]*pDecodedSamples
[-11]; goto case;
1090 case 10: prediction
+= coefficients
[ 9]*pDecodedSamples
[-10]; goto case;
1091 case 9: prediction
+= coefficients
[ 8]*pDecodedSamples
[- 9]; goto case;
1092 case 8: prediction
+= coefficients
[ 7]*pDecodedSamples
[- 8]; goto case;
1093 case 7: prediction
+= coefficients
[ 6]*pDecodedSamples
[- 7]; goto case;
1094 case 6: prediction
+= coefficients
[ 5]*pDecodedSamples
[- 6]; goto case;
1095 case 5: prediction
+= coefficients
[ 4]*pDecodedSamples
[- 5]; goto case;
1096 case 4: prediction
+= coefficients
[ 3]*pDecodedSamples
[- 4]; goto case;
1097 case 3: prediction
+= coefficients
[ 2]*pDecodedSamples
[- 3]; goto case;
1098 case 2: prediction
+= coefficients
[ 1]*pDecodedSamples
[- 2]; goto case;
1099 case 1: prediction
+= coefficients
[ 0]*pDecodedSamples
[- 1]; goto default;
1102 return cast(int)(prediction
>>shift
);
1105 int drflac__calculate_prediction_64 (uint order
, int shift
, const(short)* coefficients
, int* pDecodedSamples
) {
1106 assert(order
<= 32);
1107 long prediction
= 0;
1109 case 32: prediction
+= coefficients
[31]*cast(long)pDecodedSamples
[-32]; goto case;
1110 case 31: prediction
+= coefficients
[30]*cast(long)pDecodedSamples
[-31]; goto case;
1111 case 30: prediction
+= coefficients
[29]*cast(long)pDecodedSamples
[-30]; goto case;
1112 case 29: prediction
+= coefficients
[28]*cast(long)pDecodedSamples
[-29]; goto case;
1113 case 28: prediction
+= coefficients
[27]*cast(long)pDecodedSamples
[-28]; goto case;
1114 case 27: prediction
+= coefficients
[26]*cast(long)pDecodedSamples
[-27]; goto case;
1115 case 26: prediction
+= coefficients
[25]*cast(long)pDecodedSamples
[-26]; goto case;
1116 case 25: prediction
+= coefficients
[24]*cast(long)pDecodedSamples
[-25]; goto case;
1117 case 24: prediction
+= coefficients
[23]*cast(long)pDecodedSamples
[-24]; goto case;
1118 case 23: prediction
+= coefficients
[22]*cast(long)pDecodedSamples
[-23]; goto case;
1119 case 22: prediction
+= coefficients
[21]*cast(long)pDecodedSamples
[-22]; goto case;
1120 case 21: prediction
+= coefficients
[20]*cast(long)pDecodedSamples
[-21]; goto case;
1121 case 20: prediction
+= coefficients
[19]*cast(long)pDecodedSamples
[-20]; goto case;
1122 case 19: prediction
+= coefficients
[18]*cast(long)pDecodedSamples
[-19]; goto case;
1123 case 18: prediction
+= coefficients
[17]*cast(long)pDecodedSamples
[-18]; goto case;
1124 case 17: prediction
+= coefficients
[16]*cast(long)pDecodedSamples
[-17]; goto case;
1125 case 16: prediction
+= coefficients
[15]*cast(long)pDecodedSamples
[-16]; goto case;
1126 case 15: prediction
+= coefficients
[14]*cast(long)pDecodedSamples
[-15]; goto case;
1127 case 14: prediction
+= coefficients
[13]*cast(long)pDecodedSamples
[-14]; goto case;
1128 case 13: prediction
+= coefficients
[12]*cast(long)pDecodedSamples
[-13]; goto case;
1129 case 12: prediction
+= coefficients
[11]*cast(long)pDecodedSamples
[-12]; goto case;
1130 case 11: prediction
+= coefficients
[10]*cast(long)pDecodedSamples
[-11]; goto case;
1131 case 10: prediction
+= coefficients
[ 9]*cast(long)pDecodedSamples
[-10]; goto case;
1132 case 9: prediction
+= coefficients
[ 8]*cast(long)pDecodedSamples
[- 9]; goto case;
1133 case 8: prediction
+= coefficients
[ 7]*cast(long)pDecodedSamples
[- 8]; goto case;
1134 case 7: prediction
+= coefficients
[ 6]*cast(long)pDecodedSamples
[- 7]; goto case;
1135 case 6: prediction
+= coefficients
[ 5]*cast(long)pDecodedSamples
[- 6]; goto case;
1136 case 5: prediction
+= coefficients
[ 4]*cast(long)pDecodedSamples
[- 5]; goto case;
1137 case 4: prediction
+= coefficients
[ 3]*cast(long)pDecodedSamples
[- 4]; goto case;
1138 case 3: prediction
+= coefficients
[ 2]*cast(long)pDecodedSamples
[- 3]; goto case;
1139 case 2: prediction
+= coefficients
[ 1]*cast(long)pDecodedSamples
[- 2]; goto case;
1140 case 1: prediction
+= coefficients
[ 0]*cast(long)pDecodedSamples
[- 1]; goto default;
1143 return cast(int)(prediction
>>shift
);
1147 // Reads and decodes a string of residual values as Rice codes. The decoder should be sitting on the first bit of the Rice codes.
1149 // This is the most frequently called function in the library. It does both the Rice decoding and the prediction in a single loop
1150 // iteration. The prediction is done at the end, and there's an annoying branch I'd like to avoid so the main function is defined
1151 // as a #define - sue me!
1152 //#define DRFLAC__DECODE_SAMPLES_WITH_RESIDULE__RICE__PROC(funcName, predictionFunc)
1153 enum DRFLAC__DECODE_SAMPLES_WITH_RESIDULE__RICE__PROC(string funcName
, string predictionFunc
) =
1154 "static bool "~funcName
~" (drflac_bs* bs, uint count, ubyte riceParam, uint order, int shift, const(short)* coefficients, int* pSamplesOut) {\n"~
1155 " assert(bs !is null);\n"~
1156 " assert(count > 0);\n"~
1157 " assert(pSamplesOut !is null);\n"~
1159 " static immutable uint[16] bitOffsetTable = [\n"~
1164 " 1, 1, 1, 1, 1, 1, 1, 1\n"~
1167 " drflac_cache_t riceParamMask = cast(drflac_cache_t)("~DRFLAC_CACHE_L1_SELECTION_MASK
!"riceParam"~");\n"~
1168 " drflac_cache_t resultHiShift = cast(drflac_cache_t)("~DRFLAC_CACHE_L1_SIZE_BITS
!"bs"~"-riceParam);\n"~
1170 " for (int i = 0; i < cast(int)count; ++i) {\n"~
1171 " uint zeroCounter = 0;\n"~
1172 " while (bs.cache == 0) {\n"~
1173 " zeroCounter += cast(uint)"~DRFLAC_CACHE_L1_BITS_REMAINING
!"bs"~";\n"~
1174 " if (!drflac__reload_cache(bs)) return false;\n"~
1177 " /* At this point the cache should not be zero, in which case we know the first set bit should be somewhere in here. There is\n"~
1178 " no need for us to perform any cache reloading logic here which should make things much faster. */\n"~
1179 " assert(bs.cache != 0);\n"~
1180 " uint decodedRice;\n"~
1182 " uint setBitOffsetPlus1 = bitOffsetTable.ptr["~DRFLAC_CACHE_L1_SELECT_AND_SHIFT
!("bs", "4")~"];\n"~
1183 " if (setBitOffsetPlus1 > 0) {\n"~
1184 " decodedRice = (zeroCounter+(setBitOffsetPlus1-1))<<riceParam;\n"~
1186 " if (bs.cache == 1) {\n"~
1187 " setBitOffsetPlus1 = cast(uint)("~DRFLAC_CACHE_L1_SIZE_BITS
!"bs"~");\n"~
1188 " decodedRice = cast(uint)((zeroCounter+("~DRFLAC_CACHE_L1_SIZE_BITS
!"bs"~"-1))<<riceParam);\n"~
1190 " setBitOffsetPlus1 = 5;\n"~
1192 " if ((bs.cache&"~DRFLAC_CACHE_L1_SELECT
!("bs", "setBitOffsetPlus1")~")) {\n"~
1193 " decodedRice = (zeroCounter+(setBitOffsetPlus1-1))<<riceParam;\n"~
1196 " setBitOffsetPlus1 += 1;\n"~
1201 " uint bitsLo = 0;\n"~
1202 " uint riceLength = setBitOffsetPlus1+riceParam;\n"~
1203 " if (riceLength < "~DRFLAC_CACHE_L1_BITS_REMAINING
!"bs"~") {\n"~
1204 " bitsLo = cast(uint)((bs.cache&(riceParamMask>>setBitOffsetPlus1))>>("~DRFLAC_CACHE_L1_SIZE_BITS
!"bs"~"-riceLength));\n"~
1205 " bs.consumedBits += riceLength;\n"~
1206 " bs.cache <<= riceLength;\n"~
1208 " bs.consumedBits += riceLength;\n"~
1209 " bs.cache <<= setBitOffsetPlus1;\n"~
1211 " /* It straddles the cached data. It will never cover more than the next chunk. We just read the number in two parts and combine them. */\n"~
1212 " usize bitCountLo = bs.consumedBits-"~DRFLAC_CACHE_L1_SIZE_BITS
!"bs"~";\n"~
1213 " drflac_cache_t resultHi = bs.cache&riceParamMask; /* <-- This mask is OK because all bits after the first bits are always zero. */\n"~
1215 " if (bs.nextL2Line < "~DRFLAC_CACHE_L2_LINE_COUNT
!"bs"~") {\n"~
1216 " bs.cache = drflac__be2host__cache_line(bs.cacheL2.ptr[bs.nextL2Line++]);\n"~
1218 " /* Slow path. We need to fetch more data from the client. */\n"~
1219 " if (!drflac__reload_cache(bs)) return false;\n"~
1222 " bitsLo = cast(uint)((resultHi>>resultHiShift)|"~DRFLAC_CACHE_L1_SELECT_AND_SHIFT
!("bs", "bitCountLo")~");\n"~
1223 " bs.consumedBits = bitCountLo;\n"~
1224 " bs.cache <<= bitCountLo;\n"~
1227 " decodedRice |= bitsLo;\n"~
1228 " decodedRice = (decodedRice>>1)^(~(decodedRice&0x01)+1); /* <-- Ah, much faster! :) */\n"~
1230 " if ((decodedRice&0x01)) {\n"~
1231 " decodedRice = ~(decodedRice>>1);\n"~
1233 " decodedRice = (decodedRice>>1);\n"~
1237 " /* In order to properly calculate the prediction when the bits per sample is >16 we need to do it using 64-bit arithmetic. We can assume this\n"~
1238 " is probably going to be slower on 32-bit systems so we'll do a more optimized 32-bit version when the bits per sample is low enough.*/\n"~
1239 " pSamplesOut[i] = (cast(int)decodedRice+"~predictionFunc
~"(order, shift, coefficients, pSamplesOut+i));\n"~
1245 mixin(DRFLAC__DECODE_SAMPLES_WITH_RESIDULE__RICE__PROC
!("drflac__decode_samples_with_residual__rice_64", "drflac__calculate_prediction_64"));
1246 mixin(DRFLAC__DECODE_SAMPLES_WITH_RESIDULE__RICE__PROC
!("drflac__decode_samples_with_residual__rice_32", "drflac__calculate_prediction_32"));
1249 // Reads and seeks past a string of residual values as Rice codes. The decoder should be sitting on the first bit of the Rice codes.
1250 bool drflac__read_and_seek_residual__rice (drflac_bs
* bs
, uint count
, ubyte riceParam
) {
1251 assert(bs
!is null);
1254 for (uint i
= 0; i
< count
; ++i
) {
1255 if (!drflac__read_and_seek_rice(bs
, riceParam
)) return false;
1261 bool drflac__decode_samples_with_residual__unencoded (drflac_bs
* bs
, uint bitsPerSample
, uint count
, ubyte unencodedBitsPerSample
, uint order
, int shift
, const short* coefficients
, int* pSamplesOut
) {
1262 assert(bs
!is null);
1264 assert(unencodedBitsPerSample
> 0 && unencodedBitsPerSample
<= 32);
1265 assert(pSamplesOut
!is null);
1267 for (uint i
= 0; i
< count
; ++i
) {
1268 if (!drflac__read_int32(bs
, unencodedBitsPerSample
, pSamplesOut
+i
)) return false;
1269 if (bitsPerSample
> 16) {
1270 pSamplesOut
[i
] += drflac__calculate_prediction_64(order
, shift
, coefficients
, pSamplesOut
+i
);
1272 pSamplesOut
[i
] += drflac__calculate_prediction_32(order
, shift
, coefficients
, pSamplesOut
+i
);
1280 // Reads and decodes the residual for the sub-frame the decoder is currently sitting on. This function should be called
1281 // when the decoder is sitting at the very start of the RESIDUAL block. The first <order> residuals will be ignored. The
1282 // <blockSize> and <order> parameters are used to determine how many residual values need to be decoded.
1283 bool drflac__decode_samples_with_residual (drflac_bs
* bs
, uint bitsPerSample
, uint blockSize
, uint order
, int shift
, const short* coefficients
, int* pDecodedSamples
) {
1284 assert(bs
!is null);
1285 assert(blockSize
!= 0);
1286 assert(pDecodedSamples
!is null); // <-- Should we allow null, in which case we just seek past the residual rather than do a full decode?
1288 ubyte residualMethod
;
1289 if (!drflac__read_uint8(bs
, 2, &residualMethod
)) return false;
1291 if (residualMethod
!= DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE
&& residualMethod
!= DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE2
) return false; // Unknown or unsupported residual coding method.
1293 // Ignore the first <order> values.
1294 pDecodedSamples
+= order
;
1296 ubyte partitionOrder
;
1297 if (!drflac__read_uint8(bs
, 4, &partitionOrder
)) return false;
1299 uint samplesInPartition
= (blockSize
/(1<<partitionOrder
))-order
;
1300 uint partitionsRemaining
= (1<<partitionOrder
);
1302 ubyte riceParam
= 0;
1303 if (residualMethod
== DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE
) {
1304 if (!drflac__read_uint8(bs
, 4, &riceParam
)) return false;
1305 if (riceParam
== 16) riceParam
= 0xFF;
1306 } else if (residualMethod
== DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE2
) {
1307 if (!drflac__read_uint8(bs
, 5, &riceParam
)) return false;
1308 if (riceParam
== 32) riceParam
= 0xFF;
1311 if (riceParam
!= 0xFF) {
1312 if (bitsPerSample
> 16) {
1313 if (!drflac__decode_samples_with_residual__rice_64(bs
, samplesInPartition
, riceParam
, order
, shift
, coefficients
, pDecodedSamples
)) return false;
1315 if (!drflac__decode_samples_with_residual__rice_32(bs
, samplesInPartition
, riceParam
, order
, shift
, coefficients
, pDecodedSamples
)) return false;
1318 ubyte unencodedBitsPerSample
= 0;
1319 if (!drflac__read_uint8(bs
, 5, &unencodedBitsPerSample
)) return false;
1320 if (!drflac__decode_samples_with_residual__unencoded(bs
, bitsPerSample
, samplesInPartition
, unencodedBitsPerSample
, order
, shift
, coefficients
, pDecodedSamples
)) return false;
1323 pDecodedSamples
+= samplesInPartition
;
1325 if (partitionsRemaining
== 1) break;
1327 partitionsRemaining
-= 1;
1328 samplesInPartition
= blockSize
/(1<<partitionOrder
);
1334 // Reads and seeks past the residual for the sub-frame the decoder is currently sitting on. This function should be called
1335 // when the decoder is sitting at the very start of the RESIDUAL block. The first <order> residuals will be set to 0. The
1336 // <blockSize> and <order> parameters are used to determine how many residual values need to be decoded.
1337 bool drflac__read_and_seek_residual (drflac_bs
* bs
, uint blockSize
, uint order
) {
1338 assert(bs
!is null);
1339 assert(blockSize
!= 0);
1341 ubyte residualMethod
;
1342 if (!drflac__read_uint8(bs
, 2, &residualMethod
)) return false;
1344 if (residualMethod
!= DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE
&& residualMethod
!= DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE2
) return false; // Unknown or unsupported residual coding method.
1346 ubyte partitionOrder
;
1347 if (!drflac__read_uint8(bs
, 4, &partitionOrder
)) return false;
1349 uint samplesInPartition
= (blockSize
/(1<<partitionOrder
))-order
;
1350 uint partitionsRemaining
= (1<<partitionOrder
);
1352 ubyte riceParam
= 0;
1353 if (residualMethod
== DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE
) {
1354 if (!drflac__read_uint8(bs
, 4, &riceParam
)) return false;
1355 if (riceParam
== 16) riceParam
= 0xFF;
1356 } else if (residualMethod
== DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE2
) {
1357 if (!drflac__read_uint8(bs
, 5, &riceParam
)) return false;
1358 if (riceParam
== 32) riceParam
= 0xFF;
1361 if (riceParam
!= 0xFF) {
1362 if (!drflac__read_and_seek_residual__rice(bs
, samplesInPartition
, riceParam
)) return false;
1364 ubyte unencodedBitsPerSample
= 0;
1365 if (!drflac__read_uint8(bs
, 5, &unencodedBitsPerSample
)) return false;
1366 if (!drflac__seek_bits(bs
, unencodedBitsPerSample
*samplesInPartition
)) return false;
1369 if (partitionsRemaining
== 1) break;
1371 partitionsRemaining
-= 1;
1372 samplesInPartition
= blockSize
/(1<<partitionOrder
);
1379 bool drflac__decode_samples__constant (drflac_bs
* bs
, uint blockSize
, uint bitsPerSample
, int* pDecodedSamples
) {
1380 // Only a single sample needs to be decoded here.
1382 if (!drflac__read_int32(bs
, bitsPerSample
, &sample
)) return false;
1384 // We don't really need to expand this, but it does simplify the process of reading samples. If this becomes a performance issue (unlikely)
1385 // we'll want to look at a more efficient way.
1386 for (uint i
= 0; i
< blockSize
; ++i
) pDecodedSamples
[i
] = sample
;
1391 bool drflac__decode_samples__verbatim (drflac_bs
* bs
, uint blockSize
, uint bitsPerSample
, int* pDecodedSamples
) {
1392 for (uint i
= 0; i
< blockSize
; ++i
) {
1394 if (!drflac__read_int32(bs
, bitsPerSample
, &sample
)) return false;
1395 pDecodedSamples
[i
] = sample
;
1400 bool drflac__decode_samples__fixed (drflac_bs
* bs
, uint blockSize
, uint bitsPerSample
, ubyte lpcOrder
, int* pDecodedSamples
) {
1401 static immutable short[4][5] lpcCoefficientsTable
= [
1409 // Warm up samples and coefficients.
1410 for (uint i
= 0; i
< lpcOrder
; ++i
) {
1412 if (!drflac__read_int32(bs
, bitsPerSample
, &sample
)) return false;
1413 pDecodedSamples
[i
] = sample
;
1416 if (!drflac__decode_samples_with_residual(bs
, bitsPerSample
, blockSize
, lpcOrder
, 0, lpcCoefficientsTable
.ptr
[lpcOrder
].ptr
, pDecodedSamples
)) return false;
1421 bool drflac__decode_samples__lpc (drflac_bs
* bs
, uint blockSize
, uint bitsPerSample
, ubyte lpcOrder
, int* pDecodedSamples
) {
1423 for (ubyte i
= 0; i
< lpcOrder
; ++i
) {
1425 if (!drflac__read_int32(bs
, bitsPerSample
, &sample
)) return false;
1426 pDecodedSamples
[i
] = sample
;
1430 if (!drflac__read_uint8(bs
, 4, &lpcPrecision
)) return false;
1431 if (lpcPrecision
== 15) return false; // Invalid.
1435 if (!drflac__read_int8(bs
, 5, &lpcShift
)) return false;
1437 short[32] coefficients
;
1438 for (ubyte i
= 0; i
< lpcOrder
; ++i
) {
1439 if (!drflac__read_int16(bs
, lpcPrecision
, coefficients
.ptr
+i
)) return false;
1442 if (!drflac__decode_samples_with_residual(bs
, bitsPerSample
, blockSize
, lpcOrder
, lpcShift
, coefficients
.ptr
, pDecodedSamples
)) return false;
1448 bool drflac__read_next_frame_header (drflac_bs
* bs
, ubyte streaminfoBitsPerSample
, drflac_frame_header
* header
) {
1449 assert(bs
!is null);
1450 assert(header
!is null);
1452 // At the moment the sync code is as a form of basic validation. The CRC is stored, but is unused at the moment. This
1453 // should probably be handled better in the future.
1455 static immutable uint[12] sampleRateTable
= [0, 88200, 176400, 192000, 8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000];
1456 static immutable ubyte[8] bitsPerSampleTable
= [0, 8, 12, cast(ubyte)-1, 16, 20, 24, cast(ubyte)-1]; // -1 = reserved.
1458 ushort syncCode
= 0;
1459 if (!drflac__read_uint16(bs
, 14, &syncCode
)) return false;
1461 if (syncCode
!= 0x3FFE) return false; // TODO: Try and recover by attempting to seek to and read the next frame?
1464 if (!drflac__read_uint8(bs
, 1, &reserved
)) return false;
1466 ubyte blockingStrategy
= 0;
1467 if (!drflac__read_uint8(bs
, 1, &blockingStrategy
)) return false;
1469 ubyte blockSize
= 0;
1470 if (!drflac__read_uint8(bs
, 4, &blockSize
)) return false;
1472 ubyte sampleRate
= 0;
1473 if (!drflac__read_uint8(bs
, 4, &sampleRate
)) return false;
1475 ubyte channelAssignment
= 0;
1476 if (!drflac__read_uint8(bs
, 4, &channelAssignment
)) return false;
1478 ubyte bitsPerSample
= 0;
1479 if (!drflac__read_uint8(bs
, 3, &bitsPerSample
)) return false;
1481 if (!drflac__read_uint8(bs
, 1, &reserved
)) return false;
1483 bool isVariableBlockSize
= blockingStrategy
== 1;
1484 if (isVariableBlockSize
) {
1486 if (!drflac__read_utf8_coded_number(bs
, &sampleNumber
)) return false;
1487 header
.frameNumber
= 0;
1488 header
.sampleNumber
= sampleNumber
;
1490 ulong frameNumber
= 0;
1491 if (!drflac__read_utf8_coded_number(bs
, &frameNumber
)) return false;
1492 header
.frameNumber
= cast(uint)frameNumber
; // <-- Safe cast.
1493 header
.sampleNumber
= 0;
1496 if (blockSize
== 1) {
1497 header
.blockSize
= 192;
1498 } else if (blockSize
>= 2 && blockSize
<= 5) {
1499 header
.blockSize
= cast(ushort)(576*(1<<(blockSize
-2))); //k8
1500 } else if (blockSize
== 6) {
1501 if (!drflac__read_uint16(bs
, 8, &header
.blockSize
)) return false;
1502 header
.blockSize
+= 1;
1503 } else if (blockSize
== 7) {
1504 if (!drflac__read_uint16(bs
, 16, &header
.blockSize
)) return false;
1505 header
.blockSize
+= 1;
1507 header
.blockSize
= cast(ushort)(256*(1<<(blockSize
-8))); //k8
1510 if (sampleRate
<= 11) {
1511 header
.sampleRate
= sampleRateTable
.ptr
[sampleRate
];
1512 } else if (sampleRate
== 12) {
1513 if (!drflac__read_uint32(bs
, 8, &header
.sampleRate
)) return false;
1514 header
.sampleRate
*= 1000;
1515 } else if (sampleRate
== 13) {
1516 if (!drflac__read_uint32(bs
, 16, &header
.sampleRate
)) return false;
1517 } else if (sampleRate
== 14) {
1518 if (!drflac__read_uint32(bs
, 16, &header
.sampleRate
)) return false;
1519 header
.sampleRate
*= 10;
1521 return false; // Invalid.
1524 header
.channelAssignment
= channelAssignment
;
1526 header
.bitsPerSample
= bitsPerSampleTable
.ptr
[bitsPerSample
];
1527 if (header
.bitsPerSample
== 0) header
.bitsPerSample
= streaminfoBitsPerSample
;
1529 if (drflac__read_uint8(bs
, 8, &header
.crc8
) != 1) return false;
1534 bool drflac__read_subframe_header (drflac_bs
* bs
, drflac_subframe
* pSubframe
) {
1536 if (!drflac__read_uint8(bs
, 8, &header
)) return false;
1538 // First bit should always be 0.
1539 if ((header
&0x80) != 0) return false;
1541 int type
= (header
&0x7E)>>1;
1543 pSubframe
.subframeType
= DRFLAC_SUBFRAME_CONSTANT
;
1544 } else if (type
== 1) {
1545 pSubframe
.subframeType
= DRFLAC_SUBFRAME_VERBATIM
;
1547 if ((type
&0x20) != 0) {
1548 pSubframe
.subframeType
= DRFLAC_SUBFRAME_LPC
;
1549 pSubframe
.lpcOrder
= (type
&0x1F)+1;
1550 } else if ((type
&0x08) != 0) {
1551 pSubframe
.subframeType
= DRFLAC_SUBFRAME_FIXED
;
1552 pSubframe
.lpcOrder
= (type
&0x07);
1553 if (pSubframe
.lpcOrder
> 4) {
1554 pSubframe
.subframeType
= DRFLAC_SUBFRAME_RESERVED
;
1555 pSubframe
.lpcOrder
= 0;
1558 pSubframe
.subframeType
= DRFLAC_SUBFRAME_RESERVED
;
1562 if (pSubframe
.subframeType
== DRFLAC_SUBFRAME_RESERVED
) return false;
1564 // Wasted bits per sample.
1565 pSubframe
.wastedBitsPerSample
= 0;
1566 if ((header
&0x01) == 1) {
1567 uint wastedBitsPerSample
;
1568 if (!drflac__seek_past_next_set_bit(bs
, &wastedBitsPerSample
)) return false;
1569 pSubframe
.wastedBitsPerSample
= cast(ubyte)(cast(ubyte)wastedBitsPerSample
+1); // k8
1575 bool drflac__decode_subframe (drflac_bs
* bs
, drflac_frame
* frame
, int subframeIndex
, int* pDecodedSamplesOut
) {
1576 assert(bs
!is null);
1577 assert(frame
!is null);
1579 drflac_subframe
* pSubframe
= frame
.subframes
.ptr
+subframeIndex
;
1580 if (!drflac__read_subframe_header(bs
, pSubframe
)) return false;
1582 // Side channels require an extra bit per sample. Took a while to figure that one out...
1583 pSubframe
.bitsPerSample
= frame
.header
.bitsPerSample
;
1584 if ((frame
.header
.channelAssignment
== DRFLAC_CHANNEL_ASSIGNMENT_LEFT_SIDE || frame
.header
.channelAssignment
== DRFLAC_CHANNEL_ASSIGNMENT_MID_SIDE
) && subframeIndex
== 1) {
1585 pSubframe
.bitsPerSample
+= 1;
1586 } else if (frame
.header
.channelAssignment
== DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE
&& subframeIndex
== 0) {
1587 pSubframe
.bitsPerSample
+= 1;
1590 // Need to handle wasted bits per sample.
1591 pSubframe
.bitsPerSample
-= pSubframe
.wastedBitsPerSample
;
1592 pSubframe
.pDecodedSamples
= pDecodedSamplesOut
;
1594 switch (pSubframe
.subframeType
) {
1595 case DRFLAC_SUBFRAME_CONSTANT
: drflac__decode_samples__constant(bs
, frame
.header
.blockSize
, pSubframe
.bitsPerSample
, pSubframe
.pDecodedSamples
); break;
1596 case DRFLAC_SUBFRAME_VERBATIM
: drflac__decode_samples__verbatim(bs
, frame
.header
.blockSize
, pSubframe
.bitsPerSample
, pSubframe
.pDecodedSamples
); break;
1597 case DRFLAC_SUBFRAME_FIXED
: drflac__decode_samples__fixed(bs
, frame
.header
.blockSize
, pSubframe
.bitsPerSample
, pSubframe
.lpcOrder
, pSubframe
.pDecodedSamples
); break;
1598 case DRFLAC_SUBFRAME_LPC
: drflac__decode_samples__lpc(bs
, frame
.header
.blockSize
, pSubframe
.bitsPerSample
, pSubframe
.lpcOrder
, pSubframe
.pDecodedSamples
); break;
1599 default: return false;
1605 bool drflac__seek_subframe (drflac_bs
* bs
, drflac_frame
* frame
, int subframeIndex
) {
1606 assert(bs
!is null);
1607 assert(frame
!is null);
1609 drflac_subframe
* pSubframe
= frame
.subframes
.ptr
+subframeIndex
;
1610 if (!drflac__read_subframe_header(bs
, pSubframe
)) return false;
1612 // Side channels require an extra bit per sample. Took a while to figure that one out...
1613 pSubframe
.bitsPerSample
= frame
.header
.bitsPerSample
;
1614 if ((frame
.header
.channelAssignment
== DRFLAC_CHANNEL_ASSIGNMENT_LEFT_SIDE || frame
.header
.channelAssignment
== DRFLAC_CHANNEL_ASSIGNMENT_MID_SIDE
) && subframeIndex
== 1) {
1615 pSubframe
.bitsPerSample
+= 1;
1616 } else if (frame
.header
.channelAssignment
== DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE
&& subframeIndex
== 0) {
1617 pSubframe
.bitsPerSample
+= 1;
1620 // Need to handle wasted bits per sample.
1621 pSubframe
.bitsPerSample
-= pSubframe
.wastedBitsPerSample
;
1622 pSubframe
.pDecodedSamples
= null;
1623 //pSubframe.pDecodedSamples = pFlac.pDecodedSamples+(pFlac.currentFrame.header.blockSize*subframeIndex);
1625 switch (pSubframe
.subframeType
) {
1626 case DRFLAC_SUBFRAME_CONSTANT
:
1627 if (!drflac__seek_bits(bs
, pSubframe
.bitsPerSample
)) return false;
1630 case DRFLAC_SUBFRAME_VERBATIM
:
1631 uint bitsToSeek
= frame
.header
.blockSize
*pSubframe
.bitsPerSample
;
1632 if (!drflac__seek_bits(bs
, bitsToSeek
)) return false;
1635 case DRFLAC_SUBFRAME_FIXED
:
1636 uint bitsToSeek
= pSubframe
.lpcOrder
*pSubframe
.bitsPerSample
;
1637 if (!drflac__seek_bits(bs
, bitsToSeek
)) return false;
1638 if (!drflac__read_and_seek_residual(bs
, frame
.header
.blockSize
, pSubframe
.lpcOrder
)) return false;
1641 case DRFLAC_SUBFRAME_LPC
:
1642 uint bitsToSeek
= pSubframe
.lpcOrder
*pSubframe
.bitsPerSample
;
1643 if (!drflac__seek_bits(bs
, bitsToSeek
)) return false;
1645 if (!drflac__read_uint8(bs
, 4, &lpcPrecision
)) return false;
1646 if (lpcPrecision
== 15) return false; // Invalid.
1648 bitsToSeek
= (pSubframe
.lpcOrder
*lpcPrecision
)+5; // +5 for shift.
1649 if (!drflac__seek_bits(bs
, bitsToSeek
)) return false;
1650 if (!drflac__read_and_seek_residual(bs
, frame
.header
.blockSize
, pSubframe
.lpcOrder
)) return false;
1653 default: return false;
1660 ubyte drflac__get_channel_count_from_channel_assignment (byte channelAssignment
) {
1661 assert(channelAssignment
<= 10);
1662 static immutable ubyte[11] lookup
= [1, 2, 3, 4, 5, 6, 7, 8, 2, 2, 2];
1663 return lookup
.ptr
[channelAssignment
];
1666 bool drflac__decode_frame (drflac
* pFlac
) {
1667 import core
.stdc
.string
: memset
;
1668 // This function should be called while the stream is sitting on the first byte after the frame header.
1669 memset(pFlac
.currentFrame
.subframes
.ptr
, 0, (pFlac
.currentFrame
.subframes
).sizeof
);
1671 int channelCount
= drflac__get_channel_count_from_channel_assignment(pFlac
.currentFrame
.header
.channelAssignment
);
1672 for (int i
= 0; i
< channelCount
; ++i
) {
1673 if (!drflac__decode_subframe(&pFlac
.bs
, &pFlac
.currentFrame
, i
, pFlac
.pDecodedSamples
+(pFlac
.currentFrame
.header
.blockSize
*i
))) return false;
1676 // At the end of the frame sits the padding and CRC. We don't use these so we can just seek past.
1677 if (!drflac__seek_bits(&pFlac
.bs
, (mixin(DRFLAC_CACHE_L1_BITS_REMAINING
!"(&pFlac.bs)")&7)+16)) return false;
1679 pFlac
.currentFrame
.samplesRemaining
= pFlac
.currentFrame
.header
.blockSize
*channelCount
;
1684 bool drflac__seek_frame (drflac
* pFlac
) {
1685 int channelCount
= drflac__get_channel_count_from_channel_assignment(pFlac
.currentFrame
.header
.channelAssignment
);
1686 for (int i
= 0; i
< channelCount
; ++i
) {
1687 if (!drflac__seek_subframe(&pFlac
.bs
, &pFlac
.currentFrame
, i
)) return false;
1690 return drflac__seek_bits(&pFlac
.bs
, (mixin(DRFLAC_CACHE_L1_BITS_REMAINING
!"(&pFlac.bs)")&7)+16);
1693 bool drflac__read_and_decode_next_frame (drflac
* pFlac
) {
1694 assert(pFlac
!is null);
1696 if (!drflac__read_next_frame_header(&pFlac
.bs
, pFlac
.bitsPerSample
, &pFlac
.currentFrame
.header
)) return false;
1698 return drflac__decode_frame(pFlac
);
1702 void drflac__get_current_frame_sample_range (drflac
* pFlac
, ulong* pFirstSampleInFrameOut
, ulong* pLastSampleInFrameOut
) {
1703 assert(pFlac
!is null);
1705 uint channelCount
= drflac__get_channel_count_from_channel_assignment(pFlac
.currentFrame
.header
.channelAssignment
);
1707 ulong firstSampleInFrame
= pFlac
.currentFrame
.header
.sampleNumber
;
1708 if (firstSampleInFrame
== 0) firstSampleInFrame
= pFlac
.currentFrame
.header
.frameNumber
*pFlac
.maxBlockSize
*channelCount
;
1710 ulong lastSampleInFrame
= firstSampleInFrame
+(pFlac
.currentFrame
.header
.blockSize
*channelCount
);
1711 if (lastSampleInFrame
> 0) lastSampleInFrame
-= 1; // Needs to be zero based.
1713 if (pFirstSampleInFrameOut
) *pFirstSampleInFrameOut
= firstSampleInFrame
;
1714 if (pLastSampleInFrameOut
) *pLastSampleInFrameOut
= lastSampleInFrame
;
1717 bool drflac__seek_to_first_frame (drflac
* pFlac
) {
1718 import core
.stdc
.string
: memset
;
1719 assert(pFlac
!is null);
1721 bool result
= drflac__seek_to_byte(&pFlac
.bs
, pFlac
.firstFramePos
);
1723 memset(&pFlac
.currentFrame
, 0, (pFlac
.currentFrame
).sizeof
);
1727 bool drflac__seek_to_next_frame (drflac
* pFlac
) {
1728 // This function should only ever be called while the decoder is sitting on the first byte past the FRAME_HEADER section.
1729 assert(pFlac
!is null);
1730 return drflac__seek_frame(pFlac
);
1733 bool drflac__seek_to_frame_containing_sample (drflac
* pFlac
, ulong sampleIndex
) {
1734 assert(pFlac
!is null);
1736 if (!drflac__seek_to_first_frame(pFlac
)) return false;
1738 ulong firstSampleInFrame
= 0;
1739 ulong lastSampleInFrame
= 0;
1741 // We need to read the frame's header in order to determine the range of samples it contains.
1742 if (!drflac__read_next_frame_header(&pFlac
.bs
, pFlac
.bitsPerSample
, &pFlac
.currentFrame
.header
)) return false;
1743 drflac__get_current_frame_sample_range(pFlac
, &firstSampleInFrame
, &lastSampleInFrame
);
1744 if (sampleIndex
>= firstSampleInFrame
&& sampleIndex
<= lastSampleInFrame
) break; // The sample is in this frame.
1745 if (!drflac__seek_to_next_frame(pFlac
)) return false;
1748 // If we get here we should be right at the start of the frame containing the sample.
1752 bool drflac__seek_to_sample__brute_force (drflac
* pFlac
, ulong sampleIndex
) {
1753 if (!drflac__seek_to_frame_containing_sample(pFlac
, sampleIndex
)) return false;
1755 // At this point we should be sitting on the first byte of the frame containing the sample. We need to decode every sample up to (but
1756 // not including) the sample we're seeking to.
1757 ulong firstSampleInFrame
= 0;
1758 drflac__get_current_frame_sample_range(pFlac
, &firstSampleInFrame
, null);
1760 assert(firstSampleInFrame
<= sampleIndex
);
1761 usize samplesToDecode
= cast(usize
)(sampleIndex
-firstSampleInFrame
); // <-- Safe cast because the maximum number of samples in a frame is 65535.
1762 if (samplesToDecode
== 0) return true;
1764 // At this point we are just sitting on the byte after the frame header. We need to decode the frame before reading anything from it.
1765 if (!drflac__decode_frame(pFlac
)) return false;
1767 return drflac_read_s32(pFlac
, samplesToDecode
, null) != 0;
1771 bool drflac__seek_to_sample__seek_table (drflac
* pFlac
, ulong sampleIndex
) {
1772 assert(pFlac
!is null);
1774 if (pFlac
.seektablePos
== 0) return false;
1776 if (!drflac__seek_to_byte(&pFlac
.bs
, pFlac
.seektablePos
)) return false;
1778 // The number of seek points is derived from the size of the SEEKTABLE block.
1779 uint seekpointCount
= pFlac
.seektableSize
/18; // 18 = the size of each seek point.
1780 if (seekpointCount
== 0) return false; // Would this ever happen?
1782 drflac_seekpoint closestSeekpoint
= {0};
1784 uint seekpointsRemaining
= seekpointCount
;
1785 while (seekpointsRemaining
> 0) {
1786 drflac_seekpoint seekpoint
;
1787 if (!drflac__read_uint64(&pFlac
.bs
, 64, &seekpoint
.firstSample
)) break;
1788 if (!drflac__read_uint64(&pFlac
.bs
, 64, &seekpoint
.frameOffset
)) break;
1789 if (!drflac__read_uint16(&pFlac
.bs
, 16, &seekpoint
.sampleCount
)) break;
1790 if (seekpoint
.firstSample
*pFlac
.channels
> sampleIndex
) break;
1791 closestSeekpoint
= seekpoint
;
1792 seekpointsRemaining
-= 1;
1795 // At this point we should have found the seekpoint closest to our sample. We need to seek to it using basically the same
1796 // technique as we use with the brute force method.
1797 if (!drflac__seek_to_byte(&pFlac
.bs
, pFlac
.firstFramePos
+closestSeekpoint
.frameOffset
)) return false;
1799 ulong firstSampleInFrame
= 0;
1800 ulong lastSampleInFrame
= 0;
1802 // We need to read the frame's header in order to determine the range of samples it contains.
1803 if (!drflac__read_next_frame_header(&pFlac
.bs
, pFlac
.bitsPerSample
, &pFlac
.currentFrame
.header
)) return false;
1804 drflac__get_current_frame_sample_range(pFlac
, &firstSampleInFrame
, &lastSampleInFrame
);
1805 if (sampleIndex
>= firstSampleInFrame
&& sampleIndex
<= lastSampleInFrame
) break; // The sample is in this frame.
1806 if (!drflac__seek_to_next_frame(pFlac
)) return false;
1809 assert(firstSampleInFrame
<= sampleIndex
);
1811 // At this point we are just sitting on the byte after the frame header. We need to decode the frame before reading anything from it.
1812 if (!drflac__decode_frame(pFlac
)) return false;
1814 usize samplesToDecode
= cast(usize
)(sampleIndex
-firstSampleInFrame
); // <-- Safe cast because the maximum number of samples in a frame is 65535.
1815 return drflac_read_s32(pFlac
, samplesToDecode
, null) == samplesToDecode
;
1819 //#ifndef DR_FLAC_NO_OGG
1820 struct drflac_ogg_page_header
{
1821 ubyte[4] capturePattern
; // Should be "OggS"
1822 ubyte structureVersion
; // Always 0.
1824 ulong granulePosition
;
1826 uint sequenceNumber
;
1829 ubyte[255] segmentTable
;
1833 struct drflac_init_info
{
1834 //drflac_read_proc onRead;
1835 //drflac_seek_proc onSeek;
1838 //drflac_meta_proc onMeta;
1839 //void* pUserDataMD;
1840 drflac_container container
;
1843 ubyte bitsPerSample
;
1844 ulong totalSampleCount
;
1845 ushort maxBlockSize
;
1846 ulong runningFilePos
;
1847 bool hasMetadataBlocks
;
1849 //#ifndef DR_FLAC_NO_OGG
1851 ulong oggFirstBytePos
;
1852 drflac_ogg_page_header oggBosHeader
;
1856 private struct ReadStruct
{
1857 static if (DrFlacHasVFS
) VFile srcfile
;
1858 drflac_read_proc onReadCB
;
1859 drflac_seek_proc onSeekCB
;
1862 usize
read (void* pBufferOut
, usize bytesToRead
) nothrow {
1863 auto b
= cast(ubyte*)pBufferOut
;
1866 while (bytesToRead
> 0) {
1868 if (onReadCB
!is null) {
1869 rd
= onReadCB(pUserData
, b
, bytesToRead
);
1871 static if (DrFlacHasVFS
) {
1872 if (srcfile
.isOpen
) rd
= srcfile
.rawRead(b
[0..bytesToRead
]).length
;
1881 } catch (Exception e
) {
1886 bool seek (int offset
, drflac_seek_origin origin
) nothrow {
1888 if (onSeekCB
!is null) {
1889 return onSeekCB(pUserData
, offset
, origin
);
1891 static if (DrFlacHasVFS
) {
1892 if (srcfile
.isOpen
) {
1894 case drflac_seek_origin_start
: srcfile
.seek(offset
, Seek
.Set
); return true;
1895 case drflac_seek_origin_current
: srcfile
.seek(offset
, Seek
.Cur
); return true;
1896 default: return false;
1902 } catch (Exception e
) {
1909 void drflac__decode_block_header (uint blockHeader
, ubyte* isLastBlock
, ubyte* blockType
, uint* blockSize
) {
1910 blockHeader
= drflac__be2host_32(blockHeader
);
1911 *isLastBlock
= (blockHeader
&(0x01<<31))>>31;
1912 *blockType
= (blockHeader
&(0x7F<<24))>>24;
1913 *blockSize
= (blockHeader
&0xFFFFFF);
1916 bool drflac__read_and_decode_block_header (ref ReadStruct rs
, ubyte* isLastBlock
, ubyte* blockType
, uint* blockSize
) {
1918 if (rs
.read(&blockHeader
, 4) != 4) return false;
1919 drflac__decode_block_header(blockHeader
, isLastBlock
, blockType
, blockSize
);
1923 bool drflac__read_streaminfo (ref ReadStruct rs
, drflac_streaminfo
* pStreamInfo
) {
1924 import core
.stdc
.string
: memcpy
;
1925 // min/max block size.
1927 if (rs
.read(&blockSizes
, 4) != 4) return false;
1928 // min/max frame size.
1929 ulong frameSizes
= 0;
1930 if (rs
.read(&frameSizes
, 6) != 6) return false;
1931 // Sample rate, channels, bits per sample and total sample count.
1932 ulong importantProps
;
1933 if (rs
.read(&importantProps
, 8) != 8) return false;
1936 if (rs
.read(md5
.ptr
, md5
.sizeof
) != md5
.sizeof
) return false;
1938 blockSizes
= drflac__be2host_32(blockSizes
);
1939 frameSizes
= drflac__be2host_64(frameSizes
);
1940 importantProps
= drflac__be2host_64(importantProps
);
1942 pStreamInfo
.minBlockSize
= (blockSizes
&0xFFFF0000)>>16;
1943 pStreamInfo
.maxBlockSize
= blockSizes
&0x0000FFFF;
1944 pStreamInfo
.minFrameSize
= cast(uint)((frameSizes
&0xFFFFFF0000000000UL
)>>40);
1945 pStreamInfo
.maxFrameSize
= cast(uint)((frameSizes
&0x000000FFFFFF0000UL
)>>16);
1946 pStreamInfo
.sampleRate
= cast(uint)((importantProps
&0xFFFFF00000000000UL
)>>44);
1947 pStreamInfo
.channels
= cast(ubyte )((importantProps
&0x00000E0000000000UL
)>>41)+1;
1948 pStreamInfo
.bitsPerSample
= cast(ubyte )((importantProps
&0x000001F000000000UL
)>>36)+1;
1949 pStreamInfo
.totalSampleCount
= (importantProps
&0x0000000FFFFFFFFFUL
)*pStreamInfo
.channels
;
1950 memcpy(pStreamInfo
.md5
.ptr
, md5
.ptr
, md5
.sizeof
);
1955 bool drflac__read_and_decode_metadata (drflac
* pFlac
, scope drflac_meta_proc onMeta
, void* pUserDataMD
) {
1956 import core
.stdc
.stdlib
: malloc
, free
;
1957 assert(pFlac
!is null);
1959 // We want to keep track of the byte position in the stream of the seektable. At the time of calling this function we know that
1960 // we'll be sitting on byte 42.
1961 ulong runningFilePos
= 42;
1962 ulong seektablePos
= 0;
1963 uint seektableSize
= 0;
1966 ubyte isLastBlock
= 0;
1969 if (!drflac__read_and_decode_block_header(pFlac
.bs
.rs
, &isLastBlock
, &blockType
, &blockSize
)) return false;
1970 runningFilePos
+= 4;
1972 drflac_metadata metadata
;
1973 metadata
.type
= blockType
;
1974 metadata
.pRawData
= null;
1975 metadata
.rawDataSize
= 0;
1977 switch (blockType
) {
1978 case DRFLAC_METADATA_BLOCK_TYPE_APPLICATION
:
1980 void* pRawData
= malloc(blockSize
);
1981 if (pRawData
is null) return false;
1982 scope(exit
) free(pRawData
);
1984 if (pFlac
.bs
.rs
.read(pRawData
, blockSize
) != blockSize
) return false;
1986 metadata
.pRawData
= pRawData
;
1987 metadata
.rawDataSize
= blockSize
;
1988 metadata
.data
.application
.id
= drflac__be2host_32(*cast(uint*)pRawData
);
1989 metadata
.data
.application
.pData
= cast(const(void)*)(cast(ubyte*)pRawData
+uint.sizeof
);
1990 metadata
.data
.application
.dataSize
= blockSize
-cast(uint)uint.sizeof
;
1991 try { onMeta(pUserDataMD
, &metadata
); } catch (Exception e
) { return false; }
1995 case DRFLAC_METADATA_BLOCK_TYPE_SEEKTABLE
:
1996 seektablePos
= runningFilePos
;
1997 seektableSize
= blockSize
;
2000 void* pRawData
= malloc(blockSize
);
2001 if (pRawData
is null) return false;
2002 scope(exit
) free(pRawData
);
2004 if (pFlac
.bs
.rs
.read(pRawData
, blockSize
) != blockSize
) return false;
2006 metadata
.pRawData
= pRawData
;
2007 metadata
.rawDataSize
= blockSize
;
2008 metadata
.data
.seektable
.seekpointCount
= blockSize
/(drflac_seekpoint
).sizeof
;
2009 metadata
.data
.seektable
.pSeekpoints
= cast(const(drflac_seekpoint
)*)pRawData
;
2012 for (uint iSeekpoint
= 0; iSeekpoint
< metadata
.data
.seektable
.seekpointCount
; ++iSeekpoint
) {
2013 drflac_seekpoint
* pSeekpoint
= cast(drflac_seekpoint
*)pRawData
+iSeekpoint
;
2014 pSeekpoint
.firstSample
= drflac__be2host_64(pSeekpoint
.firstSample
);
2015 pSeekpoint
.frameOffset
= drflac__be2host_64(pSeekpoint
.frameOffset
);
2016 pSeekpoint
.sampleCount
= drflac__be2host_16(pSeekpoint
.sampleCount
);
2019 try { onMeta(pUserDataMD
, &metadata
); } catch (Exception e
) { return false; }
2023 case DRFLAC_METADATA_BLOCK_TYPE_VORBIS_COMMENT
:
2025 void* pRawData
= malloc(blockSize
);
2026 if (pRawData
is null) return false;
2027 scope(exit
) free(pRawData
);
2029 if (pFlac
.bs
.rs
.read(pRawData
, blockSize
) != blockSize
) return false;
2031 metadata
.pRawData
= pRawData
;
2032 metadata
.rawDataSize
= blockSize
;
2034 const(char)* pRunningData
= cast(const(char)*)pRawData
;
2035 metadata
.data
.vorbis_comment
.vendorLength
= drflac__le2host_32(*cast(uint*)pRunningData
); pRunningData
+= 4;
2036 metadata
.data
.vorbis_comment
.vendor
= pRunningData
; pRunningData
+= metadata
.data
.vorbis_comment
.vendorLength
;
2037 metadata
.data
.vorbis_comment
.commentCount
= drflac__le2host_32(*cast(uint*)pRunningData
); pRunningData
+= 4;
2038 metadata
.data
.vorbis_comment
.comments
= pRunningData
;
2039 try { onMeta(pUserDataMD
, &metadata
); } catch (Exception e
) { return false; }
2043 case DRFLAC_METADATA_BLOCK_TYPE_CUESHEET
:
2045 import core
.stdc
.string
: memcpy
;
2046 void* pRawData
= malloc(blockSize
);
2047 if (pRawData
is null) return false;
2048 scope(exit
) free(pRawData
);
2050 if (pFlac
.bs
.rs
.read(pRawData
, blockSize
) != blockSize
) return false;
2052 metadata
.pRawData
= pRawData
;
2053 metadata
.rawDataSize
= blockSize
;
2055 const(char)* pRunningData
= cast(const(char)*)pRawData
;
2056 memcpy(metadata
.data
.cuesheet
.catalog
.ptr
, pRunningData
, 128); pRunningData
+= 128;
2057 metadata
.data
.cuesheet
.leadInSampleCount
= drflac__be2host_64(*cast(ulong*)pRunningData
);pRunningData
+= 4;
2058 metadata
.data
.cuesheet
.isCD
= ((pRunningData
[0]&0x80)>>7) != 0; pRunningData
+= 259;
2059 metadata
.data
.cuesheet
.trackCount
= pRunningData
[0]; pRunningData
+= 1;
2060 metadata
.data
.cuesheet
.pTrackData
= cast(const(ubyte)*)pRunningData
;
2061 try { onMeta(pUserDataMD
, &metadata
); } catch (Exception e
) { return false; }
2065 case DRFLAC_METADATA_BLOCK_TYPE_PICTURE
:
2067 void* pRawData
= malloc(blockSize
);
2068 if (pRawData
is null) return false;
2069 scope(exit
) free(pRawData
);
2071 if (pFlac
.bs
.rs
.read(pRawData
, blockSize
) != blockSize
) return false;
2073 metadata
.pRawData
= pRawData
;
2074 metadata
.rawDataSize
= blockSize
;
2076 const(char)* pRunningData
= cast(const(char)*)pRawData
;
2077 metadata
.data
.picture
.type
= drflac__be2host_32(*cast(uint*)pRunningData
); pRunningData
+= 4;
2078 metadata
.data
.picture
.mimeLength
= drflac__be2host_32(*cast(uint*)pRunningData
); pRunningData
+= 4;
2079 metadata
.data
.picture
.mime
= pRunningData
; pRunningData
+= metadata
.data
.picture
.mimeLength
;
2080 metadata
.data
.picture
.descriptionLength
= drflac__be2host_32(*cast(uint*)pRunningData
); pRunningData
+= 4;
2081 metadata
.data
.picture
.description
= pRunningData
;
2082 metadata
.data
.picture
.width
= drflac__be2host_32(*cast(uint*)pRunningData
); pRunningData
+= 4;
2083 metadata
.data
.picture
.height
= drflac__be2host_32(*cast(uint*)pRunningData
); pRunningData
+= 4;
2084 metadata
.data
.picture
.colorDepth
= drflac__be2host_32(*cast(uint*)pRunningData
); pRunningData
+= 4;
2085 metadata
.data
.picture
.indexColorCount
= drflac__be2host_32(*cast(uint*)pRunningData
); pRunningData
+= 4;
2086 metadata
.data
.picture
.pictureDataSize
= drflac__be2host_32(*cast(uint*)pRunningData
); pRunningData
+= 4;
2087 metadata
.data
.picture
.pPictureData
= cast(const(ubyte)*)pRunningData
;
2088 try { onMeta(pUserDataMD
, &metadata
); } catch (Exception e
) { return false; }
2092 case DRFLAC_METADATA_BLOCK_TYPE_PADDING
:
2094 metadata
.data
.padding
.unused
= 0;
2095 // Padding doesn't have anything meaningful in it, so just skip over it.
2096 if (!pFlac
.bs
.rs
.seek(blockSize
, drflac_seek_origin_current
)) return false;
2097 //onMeta(pUserDataMD, &metadata);
2101 case DRFLAC_METADATA_BLOCK_TYPE_INVALID
:
2102 // Invalid chunk. Just skip over this one.
2104 if (!pFlac
.bs
.rs
.seek(blockSize
, drflac_seek_origin_current
)) return false;
2109 // It's an unknown chunk, but not necessarily invalid. There's a chance more metadata blocks might be defined later on, so we
2110 // can at the very least report the chunk to the application and let it look at the raw data.
2112 void* pRawData
= malloc(blockSize
);
2113 if (pRawData
is null) return false;
2114 scope(exit
) free(pRawData
);
2116 if (pFlac
.bs
.rs
.read(pRawData
, blockSize
) != blockSize
) return false;
2118 metadata
.pRawData
= pRawData
;
2119 metadata
.rawDataSize
= blockSize
;
2120 try { onMeta(pUserDataMD
, &metadata
); } catch (Exception e
) { return false; }
2125 // If we're not handling metadata, just skip over the block. If we are, it will have been handled earlier in the switch statement above.
2126 if (onMeta
is null) {
2127 if (!pFlac
.bs
.rs
.seek(blockSize
, drflac_seek_origin_current
)) return false;
2130 runningFilePos
+= blockSize
;
2131 if (isLastBlock
) break;
2134 pFlac
.seektablePos
= seektablePos
;
2135 pFlac
.seektableSize
= seektableSize
;
2136 pFlac
.firstFramePos
= runningFilePos
;
2141 bool drflac__init_private__native (drflac_init_info
* pInit
, ref ReadStruct rs
, scope drflac_meta_proc onMeta
, void* pUserDataMD
) {
2142 // Pre: The bit stream should be sitting just past the 4-byte id header.
2144 pInit
.container
= drflac_container_native
;
2146 // The first metadata block should be the STREAMINFO block.
2150 if (!drflac__read_and_decode_block_header(rs
, &isLastBlock
, &blockType
, &blockSize
)) return false;
2152 if (blockType
!= DRFLAC_METADATA_BLOCK_TYPE_STREAMINFO || blockSize
!= 34) return false; // Invalid block type. First block must be the STREAMINFO block.
2154 drflac_streaminfo streaminfo
;
2155 if (!drflac__read_streaminfo(rs
, &streaminfo
)) return false;
2157 pInit
.sampleRate
= streaminfo
.sampleRate
;
2158 pInit
.channels
= streaminfo
.channels
;
2159 pInit
.bitsPerSample
= streaminfo
.bitsPerSample
;
2160 pInit
.totalSampleCount
= streaminfo
.totalSampleCount
;
2161 pInit
.maxBlockSize
= streaminfo
.maxBlockSize
; // Don't care about the min block size - only the max (used for determining the size of the memory allocation).
2163 if (onMeta
!is null) {
2164 drflac_metadata metadata
;
2165 metadata
.type
= DRFLAC_METADATA_BLOCK_TYPE_STREAMINFO
;
2166 metadata
.pRawData
= null;
2167 metadata
.rawDataSize
= 0;
2168 metadata
.data
.streaminfo
= streaminfo
;
2169 try { onMeta(pUserDataMD
, &metadata
); } catch (Exception e
) { return false; }
2172 pInit
.hasMetadataBlocks
= !isLastBlock
;
2176 //#ifndef DR_FLAC_NO_OGG
2177 bool drflac_ogg__is_capture_pattern (const(ubyte)* pattern
/*[4]*/) {
2178 return pattern
[0] == 'O' && pattern
[1] == 'g' && pattern
[2] == 'g' && pattern
[3] == 'S';
2181 uint drflac_ogg__get_page_header_size (drflac_ogg_page_header
* pHeader
) {
2182 return 27+pHeader
.segmentCount
;
2185 uint drflac_ogg__get_page_body_size (drflac_ogg_page_header
* pHeader
) {
2186 uint pageBodySize
= 0;
2187 for (int i
= 0; i
< pHeader
.segmentCount
; ++i
) pageBodySize
+= pHeader
.segmentTable
.ptr
[i
];
2188 return pageBodySize
;
2191 bool drflac_ogg__read_page_header_after_capture_pattern (ref ReadStruct rs
, drflac_ogg_page_header
* pHeader
, uint* pHeaderSize
) {
2192 if (rs
.read(&pHeader
.structureVersion
, 1) != 1 || pHeader
.structureVersion
!= 0) return false; // Unknown structure version. Possibly corrupt stream.
2193 if (rs
.read(&pHeader
.headerType
, 1) != 1) return false;
2194 if (rs
.read(&pHeader
.granulePosition
, 8) != 8) return false;
2195 if (rs
.read(&pHeader
.serialNumber
, 4) != 4) return false;
2196 if (rs
.read(&pHeader
.sequenceNumber
, 4) != 4) return false;
2197 if (rs
.read(&pHeader
.checksum
, 4) != 4) return false;
2198 if (rs
.read(&pHeader
.segmentCount
, 1) != 1 || pHeader
.segmentCount
== 0) return false; // Should not have a segment count of 0.
2199 if (rs
.read(&pHeader
.segmentTable
, pHeader
.segmentCount
) != pHeader
.segmentCount
) return false;
2200 if (pHeaderSize
) *pHeaderSize
= (27+pHeader
.segmentCount
);
2204 bool drflac_ogg__read_page_header (ref ReadStruct rs
, drflac_ogg_page_header
* pHeader
, uint* pHeaderSize
) {
2206 if (rs
.read(id
.ptr
, 4) != 4) return false;
2207 if (id
.ptr
[0] != 'O' || id
.ptr
[1] != 'g' || id
.ptr
[2] != 'g' || id
.ptr
[3] != 'S') return false;
2208 return drflac_ogg__read_page_header_after_capture_pattern(rs
, pHeader
, pHeaderSize
);
2212 // The main part of the Ogg encapsulation is the conversion from the physical Ogg bitstream to the native FLAC bitstream. It works
2213 // in three general stages: Ogg Physical Bitstream . Ogg/FLAC Logical Bitstream . FLAC Native Bitstream. dr_flac is architecured
2214 // in such a way that the core sections assume everything is delivered in native format. Therefore, for each encapsulation type
2215 // dr_flac is supporting there needs to be a layer sitting on top of the onRead and onSeek callbacks that ensures the bits read from
2216 // the physical Ogg bitstream are converted and delivered in native FLAC format.
2217 struct drflac_oggbs
{
2218 //drflac_read_proc onRead; // The original onRead callback from drflac_open() and family.
2219 //drflac_seek_proc onSeek; // The original onSeek callback from drflac_open() and family.
2220 //void* pUserData; // The user data passed on onRead and onSeek. This is the user data that was passed on drflac_open() and family.
2222 ulong currentBytePos
; // The position of the byte we are sitting on in the physical byte stream. Used for efficient seeking.
2223 ulong firstBytePos
; // The position of the first byte in the physical bitstream. Points to the start of the "OggS" identifier of the FLAC bos page.
2224 uint serialNumber
; // The serial number of the FLAC audio pages. This is determined by the initial header page that was read during initialization.
2225 drflac_ogg_page_header bosPageHeader
; // Used for seeking.
2226 drflac_ogg_page_header currentPageHeader
;
2227 uint bytesRemainingInPage
;
2228 bool stdio
; //k8: it is drflac's stdio shit
2229 } // oggbs = Ogg Bitstream
2231 usize
drflac_oggbs__read_physical (drflac_oggbs
* oggbs
, void* bufferOut
, usize bytesToRead
) {
2232 usize bytesActuallyRead
= oggbs
.rs
.read(bufferOut
, bytesToRead
);
2233 oggbs
.currentBytePos
+= bytesActuallyRead
;
2234 return bytesActuallyRead
;
2237 bool drflac_oggbs__seek_physical (drflac_oggbs
* oggbs
, ulong offset
, drflac_seek_origin origin
) {
2238 if (origin
== drflac_seek_origin_start
) {
2239 if (offset
<= 0x7FFFFFFF) {
2240 if (!oggbs
.rs
.seek(cast(int)offset
, drflac_seek_origin_start
)) return false;
2241 oggbs
.currentBytePos
= offset
;
2244 if (!oggbs
.rs
.seek(0x7FFFFFFF, drflac_seek_origin_start
)) return false;
2245 oggbs
.currentBytePos
= offset
;
2246 return drflac_oggbs__seek_physical(oggbs
, offset
-0x7FFFFFFF, drflac_seek_origin_current
);
2249 while (offset
> 0x7FFFFFFF) {
2250 if (!oggbs
.rs
.seek(0x7FFFFFFF, drflac_seek_origin_current
)) return false;
2251 oggbs
.currentBytePos
+= 0x7FFFFFFF;
2252 offset
-= 0x7FFFFFFF;
2254 if (!oggbs
.rs
.seek(cast(int)offset
, drflac_seek_origin_current
)) return false; // <-- Safe cast thanks to the loop above.
2255 oggbs
.currentBytePos
+= offset
;
2260 bool drflac_oggbs__goto_next_page (drflac_oggbs
* oggbs
) {
2261 drflac_ogg_page_header header
;
2264 if (!drflac_ogg__read_page_header(oggbs
.rs
, &header
, &headerSize
)) return false;
2265 oggbs
.currentBytePos
+= headerSize
;
2266 uint pageBodySize
= drflac_ogg__get_page_body_size(&header
);
2267 if (header
.serialNumber
== oggbs
.serialNumber
) {
2268 oggbs
.currentPageHeader
= header
;
2269 oggbs
.bytesRemainingInPage
= pageBodySize
;
2272 // If we get here it means the page is not a FLAC page - skip it.
2273 if (pageBodySize
> 0 && !drflac_oggbs__seek_physical(oggbs
, pageBodySize
, drflac_seek_origin_current
)) return false; // <-- Safe cast - maximum size of a page is way below that of an int.
2277 usize
drflac__on_read_ogg (void* pUserData
, void* bufferOut
, usize bytesToRead
) {
2278 drflac_oggbs
* oggbs
= cast(drflac_oggbs
*)pUserData
;
2279 assert(oggbs
!is null);
2281 ubyte* pRunningBufferOut
= cast(ubyte*)bufferOut
;
2283 // Reading is done page-by-page. If we've run out of bytes in the page we need to move to the next one.
2284 usize bytesRead
= 0;
2285 while (bytesRead
< bytesToRead
) {
2286 usize bytesRemainingToRead
= bytesToRead
-bytesRead
;
2288 if (oggbs
.bytesRemainingInPage
>= bytesRemainingToRead
) {
2289 bytesRead
+= oggbs
.rs
.read(pRunningBufferOut
, bytesRemainingToRead
);
2290 oggbs
.bytesRemainingInPage
-= cast(uint)bytesRemainingToRead
;
2294 // If we get here it means some of the requested data is contained in the next pages.
2295 if (oggbs
.bytesRemainingInPage
> 0) {
2296 usize bytesJustRead
= oggbs
.rs
.read(pRunningBufferOut
, oggbs
.bytesRemainingInPage
);
2297 bytesRead
+= bytesJustRead
;
2298 pRunningBufferOut
+= bytesJustRead
;
2299 if (bytesJustRead
!= oggbs
.bytesRemainingInPage
) break; // Ran out of data.
2302 assert(bytesRemainingToRead
> 0);
2303 if (!drflac_oggbs__goto_next_page(oggbs
)) break; // Failed to go to the next chunk. Might have simply hit the end of the stream.
2306 oggbs
.currentBytePos
+= bytesRead
;
2310 bool drflac__on_seek_ogg (void* pUserData
, int offset
, drflac_seek_origin origin
) {
2311 drflac_oggbs
* oggbs
= cast(drflac_oggbs
*)pUserData
;
2312 assert(oggbs
!is null);
2313 assert(offset
> 0 ||
(offset
== 0 && origin
== drflac_seek_origin_start
));
2315 // Seeking is always forward which makes things a lot simpler.
2316 if (origin
== drflac_seek_origin_start
) {
2317 int startBytePos
= cast(int)oggbs
.firstBytePos
+(79-42); // 79 = size of bos page; 42 = size of FLAC header data. Seek up to the first byte of the native FLAC data.
2318 if (!drflac_oggbs__seek_physical(oggbs
, startBytePos
, drflac_seek_origin_start
)) return false;
2319 oggbs
.currentPageHeader
= oggbs
.bosPageHeader
;
2320 oggbs
.bytesRemainingInPage
= 42; // 42 = size of the native FLAC header data. That's our start point for seeking.
2321 return drflac__on_seek_ogg(pUserData
, offset
, drflac_seek_origin_current
);
2324 assert(origin
== drflac_seek_origin_current
);
2326 int bytesSeeked
= 0;
2327 while (bytesSeeked
< offset
) {
2328 int bytesRemainingToSeek
= offset
-bytesSeeked
;
2329 assert(bytesRemainingToSeek
>= 0);
2331 if (oggbs
.bytesRemainingInPage
>= cast(usize
)bytesRemainingToSeek
) {
2332 if (!drflac_oggbs__seek_physical(oggbs
, bytesRemainingToSeek
, drflac_seek_origin_current
)) return false;
2333 bytesSeeked
+= bytesRemainingToSeek
;
2334 oggbs
.bytesRemainingInPage
-= bytesRemainingToSeek
;
2338 // If we get here it means some of the requested data is contained in the next pages.
2339 if (oggbs
.bytesRemainingInPage
> 0) {
2340 if (!drflac_oggbs__seek_physical(oggbs
, oggbs
.bytesRemainingInPage
, drflac_seek_origin_current
)) return false;
2341 bytesSeeked
+= cast(int)oggbs
.bytesRemainingInPage
;
2344 assert(bytesRemainingToSeek
> 0);
2345 if (!drflac_oggbs__goto_next_page(oggbs
)) break; // Failed to go to the next chunk. Might have simply hit the end of the stream.
2351 bool drflac_ogg__seek_to_sample (drflac
* pFlac
, ulong sample
) {
2352 drflac_oggbs
* oggbs
= cast(drflac_oggbs
*)((cast(int*)pFlac
.pExtraData
)+pFlac
.maxBlockSize
*pFlac
.channels
);
2354 ulong originalBytePos
= oggbs
.currentBytePos
; // For recovery.
2356 // First seek to the first frame.
2357 if (!drflac__seek_to_byte(&pFlac
.bs
, pFlac
.firstFramePos
)) return false;
2358 oggbs
.bytesRemainingInPage
= 0;
2360 ulong runningGranulePosition
= 0;
2361 ulong runningFrameBytePos
= oggbs
.currentBytePos
; // <-- Points to the OggS identifier.
2363 if (!drflac_oggbs__goto_next_page(oggbs
)) {
2364 drflac_oggbs__seek_physical(oggbs
, originalBytePos
, drflac_seek_origin_start
);
2365 return false; // Never did find that sample...
2368 runningFrameBytePos
= oggbs
.currentBytePos
-drflac_ogg__get_page_header_size(&oggbs
.currentPageHeader
);
2369 if (oggbs
.currentPageHeader
.granulePosition
*pFlac
.channels
>= sample
) break; // The sample is somewhere in the previous page.
2371 // At this point we know the sample is not in the previous page. It could possibly be in this page. For simplicity we
2372 // disregard any pages that do not begin a fresh packet.
2373 if ((oggbs
.currentPageHeader
.headerType
&0x01) == 0) { // <-- Is it a fresh page?
2374 if (oggbs
.currentPageHeader
.segmentTable
.ptr
[0] >= 2) {
2375 ubyte[2] firstBytesInPage
;
2376 if (drflac_oggbs__read_physical(oggbs
, firstBytesInPage
.ptr
, 2) != 2) {
2377 drflac_oggbs__seek_physical(oggbs
, originalBytePos
, drflac_seek_origin_start
);
2380 if ((firstBytesInPage
.ptr
[0] == 0xFF) && (firstBytesInPage
.ptr
[1]&0xFC) == 0xF8) { // <-- Does the page begin with a frame's sync code?
2381 runningGranulePosition
= oggbs
.currentPageHeader
.granulePosition
*pFlac
.channels
;
2384 if (!drflac_oggbs__seek_physical(oggbs
, cast(int)oggbs
.bytesRemainingInPage
-2, drflac_seek_origin_current
)) {
2385 drflac_oggbs__seek_physical(oggbs
, originalBytePos
, drflac_seek_origin_start
);
2393 if (!drflac_oggbs__seek_physical(oggbs
, cast(int)oggbs
.bytesRemainingInPage
, drflac_seek_origin_current
)) {
2394 drflac_oggbs__seek_physical(oggbs
, originalBytePos
, drflac_seek_origin_start
);
2399 // We found the page that that is closest to the sample, so now we need to find it. The first thing to do is seek to the
2400 // start of that page. In the loop above we checked that it was a fresh page which means this page is also the start of
2401 // a new frame. This property means that after we've seeked to the page we can immediately start looping over frames until
2402 // we find the one containing the target sample.
2403 if (!drflac_oggbs__seek_physical(oggbs
, runningFrameBytePos
, drflac_seek_origin_start
)) return false;
2404 if (!drflac_oggbs__goto_next_page(oggbs
)) return false;
2406 // At this point we'll be sitting on the first byte of the frame header of the first frame in the page. We just keep
2407 // looping over these frames until we find the one containing the sample we're after.
2408 ulong firstSampleInFrame
= runningGranulePosition
;
2410 // NOTE for later: When using Ogg's page/segment based seeking later on we can't use this function (or any drflac__*
2411 // reading functions) because otherwise it will pull extra data for use in it's own internal caches which will then
2412 // break the positioning of the read pointer for the Ogg bitstream.
2413 if (!drflac__read_next_frame_header(&pFlac
.bs
, pFlac
.bitsPerSample
, &pFlac
.currentFrame
.header
)) return false;
2415 int channels
= drflac__get_channel_count_from_channel_assignment(pFlac
.currentFrame
.header
.channelAssignment
);
2416 ulong lastSampleInFrame
= firstSampleInFrame
+(pFlac
.currentFrame
.header
.blockSize
*channels
);
2417 lastSampleInFrame
-= 1; // <-- Zero based.
2419 if (sample
>= firstSampleInFrame
&& sample
<= lastSampleInFrame
) break; // The sample is in this frame.
2421 // If we get here it means the sample is not in this frame so we need to move to the next one. Now the cool thing
2422 // with Ogg is that we can efficiently seek past the frame by looking at the lacing values of each segment in
2424 firstSampleInFrame
= lastSampleInFrame
+1;
2427 // Slow way. This uses the native FLAC decoder to seek past the frame. This is slow because it needs to do a partial
2428 // decode of the frame. Although this is how the native version works, we can use Ogg's framing system to make it
2429 // more efficient. Leaving this here for reference and to use as a basis for debugging purposes.
2430 if (!drflac__seek_to_next_frame(pFlac
)) return false;
2432 // TODO: This is not yet complete. See note at the top of this loop body.
2434 // Fast(er) way. This uses Ogg's framing system to seek past the frame. This should be much more efficient than the
2435 // native FLAC seeking.
2436 if (!drflac_oggbs__seek_to_next_frame(oggbs
)) return false;
2440 assert(firstSampleInFrame
<= sample
);
2442 if (!drflac__decode_frame(pFlac
)) return false;
2444 usize samplesToDecode
= cast(usize
)(sample
-firstSampleInFrame
); // <-- Safe cast because the maximum number of samples in a frame is 65535.
2445 return drflac_read_s32(pFlac
, samplesToDecode
, null) == samplesToDecode
;
2449 bool drflac__init_private__ogg (drflac_init_info
* pInit
, ref ReadStruct rs
, scope drflac_meta_proc onMeta
, void* pUserDataMD
) {
2450 // Pre: The bit stream should be sitting just past the 4-byte OggS capture pattern.
2452 pInit
.container
= drflac_container_ogg
;
2453 pInit
.oggFirstBytePos
= 0;
2455 // We'll get here if the first 4 bytes of the stream were the OggS capture pattern, however it doesn't necessarily mean the
2456 // stream includes FLAC encoded audio. To check for this we need to scan the beginning-of-stream page markers and check if
2457 // any match the FLAC specification. Important to keep in mind that the stream may be multiplexed.
2458 drflac_ogg_page_header header
;
2460 uint headerSize
= 0;
2461 if (!drflac_ogg__read_page_header_after_capture_pattern(rs
, &header
, &headerSize
)) return false;
2462 pInit
.runningFilePos
+= headerSize
;
2465 // Break if we're past the beginning of stream page.
2466 if ((header
.headerType
&0x02) == 0) return false;
2468 // Check if it's a FLAC header.
2469 int pageBodySize
= drflac_ogg__get_page_body_size(&header
);
2470 if (pageBodySize
== 51) { // 51 = the lacing value of the FLAC header packet.
2471 // It could be a FLAC page...
2472 uint bytesRemainingInPage
= pageBodySize
;
2475 if (rs
.read(&packetType
, 1) != 1) return false;
2477 bytesRemainingInPage
-= 1;
2478 if (packetType
== 0x7F) {
2479 // Increasingly more likely to be a FLAC page...
2481 if (rs
.read(sig
.ptr
, 4) != 4) return false;
2483 bytesRemainingInPage
-= 4;
2484 if (sig
.ptr
[0] == 'F' && sig
.ptr
[1] == 'L' && sig
.ptr
[2] == 'A' && sig
.ptr
[3] == 'C') {
2485 // Almost certainly a FLAC page...
2486 ubyte[2] mappingVersion
;
2487 if (rs
.read(mappingVersion
.ptr
, 2) != 2) return false;
2489 if (mappingVersion
.ptr
[0] != 1) return false; // Only supporting version 1.x of the Ogg mapping.
2491 // The next 2 bytes are the non-audio packets, not including this one. We don't care about this because we're going to
2492 // be handling it in a generic way based on the serial number and packet types.
2493 if (!rs
.seek(2, drflac_seek_origin_current
)) return false;
2495 // Expecting the native FLAC signature "fLaC".
2496 if (rs
.read(sig
.ptr
, 4) != 4) return false;
2498 if (sig
.ptr
[0] == 'f' && sig
.ptr
[1] == 'L' && sig
.ptr
[2] == 'a' && sig
.ptr
[3] == 'C') {
2499 // The remaining data in the page should be the STREAMINFO block.
2503 if (!drflac__read_and_decode_block_header(rs
, &isLastBlock
, &blockType
, &blockSize
)) return false;
2505 if (blockType
!= DRFLAC_METADATA_BLOCK_TYPE_STREAMINFO || blockSize
!= 34) return false; // Invalid block type. First block must be the STREAMINFO block.
2507 drflac_streaminfo streaminfo
;
2508 if (drflac__read_streaminfo(rs
, &streaminfo
)) {
2510 pInit
.sampleRate
= streaminfo
.sampleRate
;
2511 pInit
.channels
= streaminfo
.channels
;
2512 pInit
.bitsPerSample
= streaminfo
.bitsPerSample
;
2513 pInit
.totalSampleCount
= streaminfo
.totalSampleCount
;
2514 pInit
.maxBlockSize
= streaminfo
.maxBlockSize
;
2516 if (onMeta
!is null) {
2517 drflac_metadata metadata
;
2518 metadata
.type
= DRFLAC_METADATA_BLOCK_TYPE_STREAMINFO
;
2519 metadata
.pRawData
= null;
2520 metadata
.rawDataSize
= 0;
2521 metadata
.data
.streaminfo
= streaminfo
;
2522 try { onMeta(pUserDataMD
, &metadata
); } catch (Exception e
) { return false; }
2525 pInit
.runningFilePos
+= pageBodySize
;
2526 pInit
.oggFirstBytePos
= pInit
.runningFilePos
-79; // Subtracting 79 will place us right on top of the "OggS" identifier of the FLAC bos page.
2527 pInit
.oggSerial
= header
.serialNumber
;
2528 pInit
.oggBosHeader
= header
;
2531 // Failed to read STREAMINFO block. Aww, so close...
2539 // Not a FLAC header. Skip it.
2540 if (!rs
.seek(bytesRemainingInPage
, drflac_seek_origin_current
)) return false;
2543 // Not a FLAC header. Seek past the entire page and move on to the next.
2544 if (!rs
.seek(bytesRemainingInPage
, drflac_seek_origin_current
)) return false;
2547 if (!rs
.seek(pageBodySize
, drflac_seek_origin_current
)) return false;
2550 pInit
.runningFilePos
+= pageBodySize
;
2552 // Read the header of the next page.
2553 if (!drflac_ogg__read_page_header(rs
, &header
, &headerSize
)) return false;
2554 pInit
.runningFilePos
+= headerSize
;
2558 // If we get here it means we found a FLAC audio stream. We should be sitting on the first byte of the header of the next page. The next
2559 // packets in the FLAC logical stream contain the metadata. The only thing left to do in the initialiation phase for Ogg is to create the
2560 // Ogg bistream object.
2561 pInit
.hasMetadataBlocks
= true; // <-- Always have at least VORBIS_COMMENT metadata block.
2566 bool drflac__check_init_private (drflac_init_info
* pInit
, scope drflac_meta_proc onMeta
, void* pUserDataMD
) {
2568 if (pInit
.rs
.read(id
.ptr
, 4) != 4) return false;
2569 if (id
.ptr
[0] == 'f' && id
.ptr
[1] == 'L' && id
.ptr
[2] == 'a' && id
.ptr
[3] == 'C') return drflac__init_private__native(pInit
, pInit
.rs
, onMeta
, pUserDataMD
);
2570 //#ifndef DR_FLAC_NO_OGG
2571 if (id
.ptr
[0] == 'O' && id
.ptr
[1] == 'g' && id
.ptr
[2] == 'g' && id
.ptr
[3] == 'S') return drflac__init_private__ogg(pInit
, pInit
.rs
, onMeta
, pUserDataMD
);
2573 // unsupported container
2577 bool drflac__init_private (drflac_init_info
* pInit
, drflac_read_proc onRead
, drflac_seek_proc onSeek
, scope drflac_meta_proc onMeta
, void* pUserData
, void* pUserDataMD
) {
2578 if (pInit
is null || onRead
is null || onSeek
is null) return false;
2580 pInit
.rs
.onReadCB
= onRead
;
2581 pInit
.rs
.onSeekCB
= onSeek
;
2582 pInit
.rs
.pUserData
= pUserData
;
2583 //pInit.onMeta = onMeta;
2584 //pInit.pUserDataMD = pUserDataMD;
2586 return drflac__check_init_private(pInit
, onMeta
, pUserDataMD
);
2591 static if (DrFlacHasVFS
)
2592 bool drflac__init_private (drflac_init_info
* pInit
, VFile fl
, scope drflac_meta_proc onMeta
, void* pUserDataMD
) {
2593 //import core.stdc.string : memset;
2594 //memset(&pInit.rs.srcfile, 0, pInit.rs.srcfile.sizeof); // just in case
2596 pInit
.rs
.srcfile
= fl
;
2597 pInit
.rs
.onReadCB
= null;
2598 pInit
.rs
.onSeekCB
= null;
2599 pInit
.rs
.pUserData
= null;
2600 //pInit.onMeta = onMeta;
2601 //pInit.pUserDataMD = pUserDataMD;
2603 return drflac__check_init_private(pInit
, onMeta
, pUserDataMD
);
2607 void drflac__init_from_info (drflac
* pFlac
, drflac_init_info
* pInit
) {
2608 import core
.stdc
.string
: memcpy
, memset
;
2609 assert(pFlac
!is null);
2610 assert(pInit
!is null);
2612 memset(pFlac
, 0, (*pFlac
).sizeof
);
2613 pFlac
.bs
.rs
= pInit
.rs
;
2614 pFlac
.bs
.nextL2Line
= (pFlac
.bs
.cacheL2
).sizeof
/(pFlac
.bs
.cacheL2
.ptr
[0]).sizeof
; // <-- Initialize to this to force a client-side data retrieval right from the start.
2615 pFlac
.bs
.consumedBits
= (pFlac
.bs
.cache
).sizeof
*8;
2617 //pFlac.onMeta = pInit.onMeta;
2618 //pFlac.pUserDataMD = pInit.pUserDataMD;
2619 pFlac
.maxBlockSize
= pInit
.maxBlockSize
;
2620 pFlac
.sampleRate
= pInit
.sampleRate
;
2621 pFlac
.channels
= cast(ubyte)pInit
.channels
;
2622 pFlac
.bitsPerSample
= cast(ubyte)pInit
.bitsPerSample
;
2623 pFlac
.totalSampleCount
= pInit
.totalSampleCount
;
2624 pFlac
.container
= pInit
.container
;
2627 drflac
* drflac_open_with_metadata_private_xx (drflac_init_info
* init
, scope drflac_meta_proc onMeta
, void* pUserDataMD
, bool stdio
) {
2628 import core
.stdc
.stdlib
: malloc
, free
;
2629 import core
.stdc
.string
: memset
;
2630 import std
.functional
: toDelegate
;
2632 usize allocationSize
= (drflac
).sizeof
;
2633 allocationSize
+= init
.maxBlockSize
*init
.channels
*(int).sizeof
;
2634 //allocationSize += init.seektableSize;
2636 //#ifndef DR_FLAC_NO_OGG
2637 // There's additional data required for Ogg streams.
2638 if (init
.container
== drflac_container_ogg
) allocationSize
+= (drflac_oggbs
).sizeof
;
2641 drflac
* pFlac
= cast(drflac
*)malloc(allocationSize
);
2642 memset(pFlac
, 0, (*pFlac
).sizeof
);
2643 drflac__init_from_info(pFlac
, init
);
2644 pFlac
.pDecodedSamples
= cast(int*)pFlac
.pExtraData
;
2646 //#ifndef DR_FLAC_NO_OGG
2647 if (init
.container
== drflac_container_ogg
) {
2648 drflac_oggbs
* oggbs
= cast(drflac_oggbs
*)((cast(int*)pFlac
.pExtraData
)+init
.maxBlockSize
*init
.channels
);
2649 oggbs
.stdio
= stdio
;
2651 oggbs
.currentBytePos
= init
.oggFirstBytePos
;
2652 oggbs
.firstBytePos
= init
.oggFirstBytePos
;
2653 oggbs
.serialNumber
= init
.oggSerial
;
2654 oggbs
.bosPageHeader
= init
.oggBosHeader
;
2655 oggbs
.bytesRemainingInPage
= 0;
2657 // The Ogg bistream needs to be layered on top of the original bitstream.
2658 pFlac
.bs
.rs
.onReadCB
= toDelegate(&drflac__on_read_ogg
);
2659 pFlac
.bs
.rs
.onSeekCB
= toDelegate(&drflac__on_seek_ogg
);
2660 pFlac
.bs
.rs
.pUserData
= cast(void*)oggbs
;
2664 // Decode metadata before returning.
2665 if (init
.hasMetadataBlocks
) {
2666 if (!drflac__read_and_decode_metadata(pFlac
, onMeta
, pUserDataMD
)) {
2676 drflac
* drflac_open_with_metadata_private (drflac_read_proc onRead
, drflac_seek_proc onSeek
, scope drflac_meta_proc onMeta
, void* pUserData
, void* pUserDataMD
, bool stdio
) {
2677 drflac_init_info init
;
2678 if (!drflac__init_private(&init
, onRead
, onSeek
, onMeta
, pUserData
, pUserDataMD
)) return null;
2679 return drflac_open_with_metadata_private_xx(&init
, onMeta
, pUserDataMD
, stdio
);
2684 static if (DrFlacHasVFS
)
2685 drflac
* drflac_open_with_metadata_private (VFile fl
, scope drflac_meta_proc onMeta
, void* pUserDataMD
, bool stdio
) {
2686 drflac_init_info init
;
2687 if (!drflac__init_private(&init
, fl
, onMeta
, pUserDataMD
)) return null;
2688 return drflac_open_with_metadata_private_xx(&init
, onMeta
, pUserDataMD
, stdio
);
2693 alias drflac_file
= void*;
2695 usize
drflac__on_read_stdio (void* pUserData
, void* bufferOut
, usize bytesToRead
) {
2696 import core
.stdc
.stdio
;
2697 return fread(bufferOut
, 1, bytesToRead
, cast(FILE
*)pUserData
);
2700 bool drflac__on_seek_stdio (void* pUserData
, int offset
, drflac_seek_origin origin
) {
2701 import core
.stdc
.stdio
;
2702 assert(offset
> 0 ||
(offset
== 0 && origin
== drflac_seek_origin_start
));
2703 return fseek(cast(FILE
*)pUserData
, offset
, (origin
== drflac_seek_origin_current
) ? SEEK_CUR
: SEEK_SET
) == 0;
2706 drflac_file
drflac__open_file_handle (const(char)[] filename
) {
2707 import std
.internal
.cstring
: tempCString
;
2708 import core
.stdc
.stdio
;
2709 FILE
* pFile
= fopen(filename
.tempCString
, "rb");
2710 if (pFile
is null) return null;
2711 return cast(drflac_file
)pFile
;
2714 void drflac__close_file_handle (drflac_file file
) {
2715 import core
.stdc
.stdio
;
2716 fclose(cast(FILE
*)file
);
2719 public drflac
* drflac_open_file (const(char)[] filename
) {
2720 import std
.functional
: toDelegate
;
2722 drflac_file file
= drflac__open_file_handle(filename
);
2723 if (file
is null) return null;
2725 drflac
* pFlac
= drflac_open(toDelegate(&drflac__on_read_stdio
), toDelegate(&drflac__on_seek_stdio
), cast(void*)file
);
2726 if (pFlac
is null) {
2727 drflac__close_file_handle(file
);
2730 pFlac
.bs
.stdio
= true;
2735 public drflac
* drflac_open_file_with_metadata (const(char)[] filename
, scope drflac_meta_proc onMeta
, void* pUserData
=null) {
2736 import std
.functional
: toDelegate
;
2738 drflac_file file
= drflac__open_file_handle(filename
);
2739 if (file
is null) return null;
2741 drflac
* pFlac
= drflac_open_with_metadata_private(toDelegate(&drflac__on_read_stdio
), toDelegate(&drflac__on_seek_stdio
), onMeta
, cast(void*)file
, pUserData
, true);
2742 if (pFlac
is null) {
2743 drflac__close_file_handle(file
);
2746 pFlac
.bs
.stdio
= true;
2753 static if (DrFlacHasVFS
) {
2754 public drflac
* drflac_open_file (VFile fl
, scope drflac_meta_proc onMeta
=null) {
2755 import std
.functional
: toDelegate
;
2758 if (onMeta
!is null) {
2759 pFlac
= drflac_open_with_metadata_private(fl
, onMeta
, null, true);
2761 pFlac
= drflac_open(fl
);
2763 if (pFlac
is null) return null;
2764 pFlac
.bs
.stdio
= false;
2772 usize
drflac__on_read_memory (void* pUserData
, void* bufferOut
, usize bytesToRead
) {
2773 drflac__memory_stream
* memoryStream
= cast(drflac__memory_stream
*)pUserData
;
2774 assert(memoryStream
!is null);
2775 assert(memoryStream
.dataSize
>= memoryStream
.currentReadPos
);
2777 usize bytesRemaining
= memoryStream
.dataSize
-memoryStream
.currentReadPos
;
2778 if (bytesToRead
> bytesRemaining
) bytesToRead
= bytesRemaining
;
2780 if (bytesToRead
> 0) {
2781 import core
.stdc
.string
: memcpy
;
2782 memcpy(bufferOut
, memoryStream
.data
+memoryStream
.currentReadPos
, bytesToRead
);
2783 memoryStream
.currentReadPos
+= bytesToRead
;
2789 bool drflac__on_seek_memory (void* pUserData
, int offset
, drflac_seek_origin origin
) {
2790 drflac__memory_stream
* memoryStream
= cast(drflac__memory_stream
*)pUserData
;
2791 assert(memoryStream
!is null);
2792 assert(offset
> 0 ||
(offset
== 0 && origin
== drflac_seek_origin_start
));
2794 if (origin
== drflac_seek_origin_current
) {
2795 if (memoryStream
.currentReadPos
+offset
<= memoryStream
.dataSize
) {
2796 memoryStream
.currentReadPos
+= offset
;
2798 memoryStream
.currentReadPos
= memoryStream
.dataSize
; // Trying to seek too far forward.
2801 if (cast(uint)offset
<= memoryStream
.dataSize
) {
2802 memoryStream
.currentReadPos
= offset
;
2804 memoryStream
.currentReadPos
= memoryStream
.dataSize
; // Trying to seek too far forward.
2811 public drflac
* drflac_open_memory (const(void)* data
, usize dataSize
) {
2812 import std
.functional
: toDelegate
;
2814 drflac__memory_stream memoryStream
;
2815 memoryStream
.data
= cast(const(ubyte)*)data
;
2816 memoryStream
.dataSize
= dataSize
;
2817 memoryStream
.currentReadPos
= 0;
2819 drflac
* pFlac
= drflac_open(toDelegate(&drflac__on_read_memory
), toDelegate(&drflac__on_seek_memory
), &memoryStream
);
2820 if (pFlac
is null) return null;
2822 pFlac
.memoryStream
= memoryStream
;
2824 // This is an awful hack...
2825 //#ifndef DR_FLAC_NO_OGG
2826 if (pFlac
.container
== drflac_container_ogg
) {
2827 drflac_oggbs
* oggbs
= cast(drflac_oggbs
*)((cast(int*)pFlac
.pExtraData
)+pFlac
.maxBlockSize
*pFlac
.channels
);
2828 oggbs
.rs
.pUserData
= &pFlac
.memoryStream
;
2833 pFlac
.bs
.rs
.pUserData
= &pFlac
.memoryStream
;
2839 public drflac
* drflac_open_memory_with_metadata (const(void)* data
, usize dataSize
, scope drflac_meta_proc onMeta
, void* pUserData
) {
2840 import std
.functional
: toDelegate
;
2842 drflac__memory_stream memoryStream
;
2843 memoryStream
.data
= cast(const(ubyte)*)data
;
2844 memoryStream
.dataSize
= dataSize
;
2845 memoryStream
.currentReadPos
= 0;
2847 drflac
* pFlac
= drflac_open_with_metadata_private(toDelegate(&drflac__on_read_memory
), toDelegate(&drflac__on_seek_memory
), onMeta
, &memoryStream
, pUserData
, false);
2848 if (pFlac
is null) return null;
2850 pFlac
.memoryStream
= memoryStream
;
2852 // This is an awful hack...
2853 //#ifndef DR_FLAC_NO_OGG
2854 if (pFlac
.container
== drflac_container_ogg
) {
2855 drflac_oggbs
* oggbs
= cast(drflac_oggbs
*)((cast(int*)pFlac
.pExtraData
)+pFlac
.maxBlockSize
*pFlac
.channels
);
2856 oggbs
.rs
.pUserData
= &pFlac
.memoryStream
;
2860 pFlac
.bs
.rs
.pUserData
= &pFlac
.memoryStream
;
2866 public drflac
* drflac_open (drflac_read_proc onRead
, drflac_seek_proc onSeek
, void* pUserData
) {
2867 return drflac_open_with_metadata_private(onRead
, onSeek
, null, pUserData
, pUserData
, false);
2872 static if (DrFlacHasVFS
)
2873 public drflac
* drflac_open (VFile fl
) {
2874 return drflac_open_with_metadata_private(fl
, null, null, false);
2879 public drflac
* drflac_open_with_metadata (drflac_read_proc onRead
, drflac_seek_proc onSeek
, scope drflac_meta_proc onMeta
, void* pUserData
) {
2880 return drflac_open_with_metadata_private(onRead
, onSeek
, onMeta
, pUserData
, pUserData
, false);
2883 public void drflac_close (drflac
* pFlac
) {
2884 import core
.stdc
.stdlib
: free
;
2885 if (pFlac
is null) return;
2887 // If we opened the file with drflac_open_file() we will want to close the file handle. We can know whether or not drflac_open_file()
2888 // was used by looking at the callbacks.
2889 //if (pFlac.bs.onRead == drflac__on_read_stdio) drflac__close_file_handle(cast(drflac_file)pFlac.bs.pUserData);
2890 if (pFlac
.bs
.stdio
) drflac__close_file_handle(cast(drflac_file
)pFlac
.bs
.rs
.pUserData
);
2892 //#ifndef DR_FLAC_NO_OGG
2893 // Need to clean up Ogg streams a bit differently due to the way the bit streaming is chained.
2894 if (pFlac
.container
== drflac_container_ogg
) {
2895 //assert(pFlac.bs.onRead == drflac__on_read_ogg);
2896 drflac_oggbs
* oggbs
= cast(drflac_oggbs
*)(cast(int*)pFlac
.pExtraData
+pFlac
.maxBlockSize
*pFlac
.channels
);
2897 //if (oggbs.onRead == drflac__on_read_stdio) drflac__close_file_handle(cast(drflac_file)oggbs.pUserData);
2898 if (oggbs
.stdio
) drflac__close_file_handle(cast(drflac_file
)oggbs
.rs
.pUserData
);
2905 ulong drflac__read_s32__misaligned (drflac
* pFlac
, ulong samplesToRead
, int* bufferOut
) {
2906 uint channelCount
= drflac__get_channel_count_from_channel_assignment(pFlac
.currentFrame
.header
.channelAssignment
);
2908 // We should never be calling this when the number of samples to read is >= the sample count.
2909 assert(samplesToRead
< channelCount
);
2910 assert(pFlac
.currentFrame
.samplesRemaining
> 0 && samplesToRead
<= pFlac
.currentFrame
.samplesRemaining
);
2912 ulong samplesRead
= 0;
2913 while (samplesToRead
> 0) {
2914 ulong totalSamplesInFrame
= pFlac
.currentFrame
.header
.blockSize
*channelCount
;
2915 ulong samplesReadFromFrameSoFar
= totalSamplesInFrame
-pFlac
.currentFrame
.samplesRemaining
;
2916 uint channelIndex
= samplesReadFromFrameSoFar
%channelCount
;
2918 ulong nextSampleInFrame
= samplesReadFromFrameSoFar
/channelCount
;
2920 int decodedSample
= 0;
2921 switch (pFlac
.currentFrame
.header
.channelAssignment
) {
2922 case DRFLAC_CHANNEL_ASSIGNMENT_LEFT_SIDE
:
2923 if (channelIndex
== 0) {
2924 decodedSample
= pFlac
.currentFrame
.subframes
.ptr
[channelIndex
].pDecodedSamples
[cast(uint)nextSampleInFrame
];
2926 int side
= pFlac
.currentFrame
.subframes
.ptr
[channelIndex
+0].pDecodedSamples
[cast(uint)nextSampleInFrame
];
2927 int left
= pFlac
.currentFrame
.subframes
.ptr
[channelIndex
-1].pDecodedSamples
[cast(uint)nextSampleInFrame
];
2928 decodedSample
= left
-side
;
2932 case DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE
:
2933 if (channelIndex
== 0) {
2934 int side
= pFlac
.currentFrame
.subframes
.ptr
[channelIndex
+0].pDecodedSamples
[cast(uint)nextSampleInFrame
];
2935 int right
= pFlac
.currentFrame
.subframes
.ptr
[channelIndex
+1].pDecodedSamples
[cast(uint)nextSampleInFrame
];
2936 decodedSample
= side
+right
;
2938 decodedSample
= pFlac
.currentFrame
.subframes
.ptr
[channelIndex
].pDecodedSamples
[cast(uint)nextSampleInFrame
];
2942 case DRFLAC_CHANNEL_ASSIGNMENT_MID_SIDE
:
2945 if (channelIndex
== 0) {
2946 mid
= pFlac
.currentFrame
.subframes
.ptr
[channelIndex
+0].pDecodedSamples
[cast(uint)nextSampleInFrame
];
2947 side
= pFlac
.currentFrame
.subframes
.ptr
[channelIndex
+1].pDecodedSamples
[cast(uint)nextSampleInFrame
];
2948 mid
= ((cast(uint)mid
)<<1)|
(side
&0x01);
2949 decodedSample
= (mid
+side
)>>1;
2951 mid
= pFlac
.currentFrame
.subframes
.ptr
[channelIndex
-1].pDecodedSamples
[cast(uint)nextSampleInFrame
];
2952 side
= pFlac
.currentFrame
.subframes
.ptr
[channelIndex
+0].pDecodedSamples
[cast(uint)nextSampleInFrame
];
2953 mid
= ((cast(uint)mid
)<<1)|
(side
&0x01);
2954 decodedSample
= (mid
-side
)>>1;
2958 case DRFLAC_CHANNEL_ASSIGNMENT_INDEPENDENT
: goto default;
2960 decodedSample
= pFlac
.currentFrame
.subframes
.ptr
[channelIndex
].pDecodedSamples
[cast(uint)nextSampleInFrame
];
2964 decodedSample
<<= ((32-pFlac
.bitsPerSample
)+pFlac
.currentFrame
.subframes
.ptr
[channelIndex
].wastedBitsPerSample
);
2966 if (bufferOut
) *bufferOut
++ = decodedSample
;
2969 pFlac
.currentFrame
.samplesRemaining
-= 1;
2976 ulong drflac__seek_forward_by_samples (drflac
* pFlac
, ulong samplesToRead
) {
2977 ulong samplesRead
= 0;
2978 while (samplesToRead
> 0) {
2979 if (pFlac
.currentFrame
.samplesRemaining
== 0) {
2980 if (!drflac__read_and_decode_next_frame(pFlac
)) break; // Couldn't read the next frame, so just break from the loop and return.
2983 pFlac
.currentFrame
.samplesRemaining
-= 1;
2990 public ulong drflac_read_s32 (drflac
* pFlac
, ulong samplesToRead
, int* bufferOut
) {
2991 // Note that <bufferOut> is allowed to be null, in which case this will be treated as something like a seek.
2992 if (pFlac
is null || samplesToRead
== 0) return 0;
2994 if (bufferOut
is null) return drflac__seek_forward_by_samples(pFlac
, samplesToRead
);
2996 ulong samplesRead
= 0;
2997 while (samplesToRead
> 0) {
2998 // If we've run out of samples in this frame, go to the next.
2999 if (pFlac
.currentFrame
.samplesRemaining
== 0) {
3000 if (!drflac__read_and_decode_next_frame(pFlac
)) break; // Couldn't read the next frame, so just break from the loop and return.
3002 // Here is where we grab the samples and interleave them.
3004 uint channelCount
= drflac__get_channel_count_from_channel_assignment(pFlac
.currentFrame
.header
.channelAssignment
);
3005 ulong totalSamplesInFrame
= pFlac
.currentFrame
.header
.blockSize
*channelCount
;
3006 ulong samplesReadFromFrameSoFar
= totalSamplesInFrame
-pFlac
.currentFrame
.samplesRemaining
;
3008 int misalignedSampleCount
= cast(int)(samplesReadFromFrameSoFar
%channelCount
);
3009 if (misalignedSampleCount
> 0) {
3010 ulong misalignedSamplesRead
= drflac__read_s32__misaligned(pFlac
, misalignedSampleCount
, bufferOut
);
3011 samplesRead
+= misalignedSamplesRead
;
3012 samplesReadFromFrameSoFar
+= misalignedSamplesRead
;
3013 bufferOut
+= misalignedSamplesRead
;
3014 samplesToRead
-= misalignedSamplesRead
;
3017 ulong alignedSampleCountPerChannel
= samplesToRead
/channelCount
;
3018 if (alignedSampleCountPerChannel
> pFlac
.currentFrame
.samplesRemaining
/channelCount
) {
3019 alignedSampleCountPerChannel
= pFlac
.currentFrame
.samplesRemaining
/channelCount
;
3022 ulong firstAlignedSampleInFrame
= samplesReadFromFrameSoFar
/channelCount
;
3023 uint unusedBitsPerSample
= 32-pFlac
.bitsPerSample
;
3025 switch (pFlac
.currentFrame
.header
.channelAssignment
) {
3026 case DRFLAC_CHANNEL_ASSIGNMENT_LEFT_SIDE
:
3027 const int* pDecodedSamples0
= pFlac
.currentFrame
.subframes
.ptr
[0].pDecodedSamples
+firstAlignedSampleInFrame
;
3028 const int* pDecodedSamples1
= pFlac
.currentFrame
.subframes
.ptr
[1].pDecodedSamples
+firstAlignedSampleInFrame
;
3030 for (/*ulong*/uint i
= 0; i
< alignedSampleCountPerChannel
; ++i
) {
3031 int left
= pDecodedSamples0
[i
];
3032 int side
= pDecodedSamples1
[i
];
3033 int right
= left
-side
;
3034 bufferOut
[i
*2+0] = left
<<(unusedBitsPerSample
+pFlac
.currentFrame
.subframes
.ptr
[0].wastedBitsPerSample
);
3035 bufferOut
[i
*2+1] = right
<<(unusedBitsPerSample
+pFlac
.currentFrame
.subframes
.ptr
[1].wastedBitsPerSample
);
3039 case DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE
:
3040 const int* pDecodedSamples0
= pFlac
.currentFrame
.subframes
.ptr
[0].pDecodedSamples
+firstAlignedSampleInFrame
;
3041 const int* pDecodedSamples1
= pFlac
.currentFrame
.subframes
.ptr
[1].pDecodedSamples
+firstAlignedSampleInFrame
;
3042 for (/*ulong*/uint i
= 0; i
< alignedSampleCountPerChannel
; ++i
) {
3043 int side
= pDecodedSamples0
[i
];
3044 int right
= pDecodedSamples1
[i
];
3045 int left
= right
+side
;
3046 bufferOut
[i
*2+0] = left
<<(unusedBitsPerSample
+pFlac
.currentFrame
.subframes
.ptr
[0].wastedBitsPerSample
);
3047 bufferOut
[i
*2+1] = right
<<(unusedBitsPerSample
+pFlac
.currentFrame
.subframes
.ptr
[1].wastedBitsPerSample
);
3051 case DRFLAC_CHANNEL_ASSIGNMENT_MID_SIDE
:
3052 const int* pDecodedSamples0
= pFlac
.currentFrame
.subframes
.ptr
[0].pDecodedSamples
+firstAlignedSampleInFrame
;
3053 const int* pDecodedSamples1
= pFlac
.currentFrame
.subframes
.ptr
[1].pDecodedSamples
+firstAlignedSampleInFrame
;
3054 for (/*ulong*/uint i
= 0; i
< alignedSampleCountPerChannel
; ++i
) {
3055 int side
= pDecodedSamples1
[i
];
3056 int mid
= ((cast(uint)pDecodedSamples0
[i
])<<1)|
(side
&0x01);
3057 bufferOut
[i
*2+0] = ((mid
+side
)>>1)<<(unusedBitsPerSample
+pFlac
.currentFrame
.subframes
.ptr
[0].wastedBitsPerSample
);
3058 bufferOut
[i
*2+1] = ((mid
-side
)>>1)<<(unusedBitsPerSample
+pFlac
.currentFrame
.subframes
.ptr
[1].wastedBitsPerSample
);
3062 case DRFLAC_CHANNEL_ASSIGNMENT_INDEPENDENT
: goto default;
3064 if (pFlac
.currentFrame
.header
.channelAssignment
== 1) { // 1 = Stereo
3065 // Stereo optimized inner loop unroll.
3066 const int* pDecodedSamples0
= pFlac
.currentFrame
.subframes
.ptr
[0].pDecodedSamples
+firstAlignedSampleInFrame
;
3067 const int* pDecodedSamples1
= pFlac
.currentFrame
.subframes
.ptr
[1].pDecodedSamples
+firstAlignedSampleInFrame
;
3068 for (/*ulong*/uint i
= 0; i
< alignedSampleCountPerChannel
; ++i
) {
3069 bufferOut
[i
*2+0] = pDecodedSamples0
[i
]<<(unusedBitsPerSample
+pFlac
.currentFrame
.subframes
.ptr
[0].wastedBitsPerSample
);
3070 bufferOut
[i
*2+1] = pDecodedSamples1
[i
]<<(unusedBitsPerSample
+pFlac
.currentFrame
.subframes
.ptr
[1].wastedBitsPerSample
);
3073 // Generic interleaving.
3074 for (/*ulong*/uint i
= 0; i
< alignedSampleCountPerChannel
; ++i
) {
3075 for (uint j
= 0; j
< channelCount
; ++j
) {
3076 bufferOut
[(i
*channelCount
)+j
] = (pFlac
.currentFrame
.subframes
.ptr
[j
].pDecodedSamples
[cast(uint)firstAlignedSampleInFrame
+i
])<<(unusedBitsPerSample
+pFlac
.currentFrame
.subframes
.ptr
[j
].wastedBitsPerSample
);
3083 ulong alignedSamplesRead
= alignedSampleCountPerChannel
*channelCount
;
3084 samplesRead
+= alignedSamplesRead
;
3085 samplesReadFromFrameSoFar
+= alignedSamplesRead
;
3086 bufferOut
+= alignedSamplesRead
;
3087 samplesToRead
-= alignedSamplesRead
;
3088 pFlac
.currentFrame
.samplesRemaining
-= cast(uint)alignedSamplesRead
;
3090 // At this point we may still have some excess samples left to read.
3091 if (samplesToRead
> 0 && pFlac
.currentFrame
.samplesRemaining
> 0) {
3092 ulong excessSamplesRead
= 0;
3093 if (samplesToRead
< pFlac
.currentFrame
.samplesRemaining
) {
3094 excessSamplesRead
= drflac__read_s32__misaligned(pFlac
, samplesToRead
, bufferOut
);
3096 excessSamplesRead
= drflac__read_s32__misaligned(pFlac
, pFlac
.currentFrame
.samplesRemaining
, bufferOut
);
3099 samplesRead
+= excessSamplesRead
;
3100 samplesReadFromFrameSoFar
+= excessSamplesRead
;
3101 bufferOut
+= excessSamplesRead
;
3102 samplesToRead
-= excessSamplesRead
;
3110 public bool drflac_seek_to_sample (drflac
* pFlac
, ulong sampleIndex
) {
3111 if (pFlac
is null) return false;
3113 // If we don't know where the first frame begins then we can't seek. This will happen when the STREAMINFO block was not present
3114 // when the decoder was opened.
3115 if (pFlac
.firstFramePos
== 0) return false;
3117 if (sampleIndex
== 0) return drflac__seek_to_first_frame(pFlac
);
3119 // Clamp the sample to the end.
3120 if (sampleIndex
>= pFlac
.totalSampleCount
) sampleIndex
= pFlac
.totalSampleCount
-1;
3122 // Different techniques depending on encapsulation. Using the native FLAC seektable with Ogg encapsulation is a bit awkward so
3123 // we'll instead use Ogg's natural seeking facility.
3124 //#ifndef DR_FLAC_NO_OGG
3125 if (pFlac
.container
== drflac_container_ogg
) {
3126 return drflac_ogg__seek_to_sample(pFlac
, sampleIndex
);
3131 // First try seeking via the seek table. If this fails, fall back to a brute force seek which is much slower.
3132 if (!drflac__seek_to_sample__seek_table(pFlac
, sampleIndex
)) return drflac__seek_to_sample__brute_force(pFlac
, sampleIndex
);
3140 //// High Level APIs ////
3141 int* drflac__full_decode_and_close (drflac
* pFlac
, uint* sampleRateOut
, uint* channelsOut
, ulong* totalSampleCountOut
) {
3142 import core
.stdc
.stdlib
: malloc
, realloc
, free
;
3143 import core
.stdc
.string
: memset
, memcpy
;
3144 assert(pFlac
!is null);
3146 int* pSampleData
= null;
3147 ulong totalSampleCount
= pFlac
.totalSampleCount
;
3149 if (totalSampleCount
== 0) {
3152 usize sampleDataBufferSize
= (buffer
).sizeof
;
3153 pSampleData
= cast(int*)malloc(sampleDataBufferSize
);
3154 if (pSampleData
is null) goto on_error
;
3157 while ((samplesRead
= cast(ulong)drflac_read_s32(pFlac
, (buffer
).sizeof
/(buffer
[0]).sizeof
, buffer
.ptr
)) > 0) {
3158 if (((totalSampleCount
+samplesRead
)*(int).sizeof
) > sampleDataBufferSize
) {
3159 sampleDataBufferSize
*= 2;
3160 int* pNewSampleData
= cast(int*)realloc(pSampleData
, sampleDataBufferSize
);
3161 if (pNewSampleData
is null) {
3165 pSampleData
= pNewSampleData
;
3167 memcpy(pSampleData
+totalSampleCount
, buffer
.ptr
, cast(usize
)(samplesRead
*(int).sizeof
));
3168 totalSampleCount
+= samplesRead
;
3170 // At this point everything should be decoded, but we just want to fill the unused part buffer with silence - need to
3171 // protect those ears from random noise!
3172 memset(pSampleData
+totalSampleCount
, 0, cast(usize
)(sampleDataBufferSize
-totalSampleCount
*(int).sizeof
));
3174 ulong dataSize
= totalSampleCount
*(int).sizeof
;
3175 if (dataSize
> uint.max
) goto on_error
; // The decoded data is too big.
3177 pSampleData
= cast(int*)malloc(cast(usize
)dataSize
); // <-- Safe cast as per the check above.
3178 if (pSampleData
is null) goto on_error
;
3180 ulong samplesDecoded
= drflac_read_s32(pFlac
, pFlac
.totalSampleCount
, pSampleData
);
3181 if (samplesDecoded
!= pFlac
.totalSampleCount
) {
3183 goto on_error
; // Something went wrong when decoding the FLAC stream.
3187 if (sampleRateOut
) *sampleRateOut
= pFlac
.sampleRate
;
3188 if (channelsOut
) *channelsOut
= pFlac
.channels
;
3189 if (totalSampleCountOut
) *totalSampleCountOut
= totalSampleCount
;
3191 drflac_close(pFlac
);
3195 drflac_close(pFlac
);
3199 public int* drflac_open_and_decode (drflac_read_proc onRead
, drflac_seek_proc onSeek
, void* pUserData
, uint* sampleRate
, uint* channels
, ulong* totalSampleCount
) {
3201 if (sampleRate
) *sampleRate
= 0;
3202 if (channels
) *channels
= 0;
3203 if (totalSampleCount
) *totalSampleCount
= 0;
3205 drflac
* pFlac
= drflac_open(onRead
, onSeek
, pUserData
);
3206 if (pFlac
is null) return null;
3208 return drflac__full_decode_and_close(pFlac
, sampleRate
, channels
, totalSampleCount
);
3211 public int* drflac_open_and_decode_file (const(char)[] filename
, uint* sampleRate
, uint* channels
, ulong* totalSampleCount
) {
3212 if (sampleRate
) *sampleRate
= 0;
3213 if (channels
) *channels
= 0;
3214 if (totalSampleCount
) *totalSampleCount
= 0;
3216 drflac
* pFlac
= drflac_open_file(filename
);
3217 if (pFlac
is null) return null;
3219 return drflac__full_decode_and_close(pFlac
, sampleRate
, channels
, totalSampleCount
);
3222 public int* drflac_open_and_decode_memory (const void* data
, usize dataSize
, uint* sampleRate
, uint* channels
, ulong* totalSampleCount
) {
3223 if (sampleRate
) *sampleRate
= 0;
3224 if (channels
) *channels
= 0;
3225 if (totalSampleCount
) *totalSampleCount
= 0;
3227 drflac
* pFlac
= drflac_open_memory(data
, dataSize
);
3228 if (pFlac
is null) return null;
3230 return drflac__full_decode_and_close(pFlac
, sampleRate
, channels
, totalSampleCount
);
3233 public void drflac_free (void* pSampleDataReturnedByOpenAndDecode
) {
3234 import core
.stdc
.stdlib
: free
;
3235 free(pSampleDataReturnedByOpenAndDecode
);
3239 public void drflac_init_vorbis_comment_iterator (drflac_vorbis_comment_iterator
* pIter
, uint commentCount
, const(char)* pComments
) {
3240 if (pIter
is null) return;
3241 pIter
.countRemaining
= commentCount
;
3242 pIter
.pRunningData
= pComments
;
3245 public const(char)* drflac_next_vorbis_comment (drflac_vorbis_comment_iterator
* pIter
, uint* pCommentLengthOut
) {
3247 if (pCommentLengthOut
) *pCommentLengthOut
= 0;
3249 if (pIter
is null || pIter
.countRemaining
== 0 || pIter
.pRunningData
is null) return null;
3251 uint length
= drflac__le2host_32(*cast(uint*)pIter
.pRunningData
);
3252 pIter
.pRunningData
+= 4;
3254 const(char)* pComment
= pIter
.pRunningData
;
3255 pIter
.pRunningData
+= length
;
3256 pIter
.countRemaining
-= 1;
3258 if (pCommentLengthOut
) *pCommentLengthOut
= length
;
3263 public long drflac_vorbis_comment_size (uint commentCount
, const(char)* pComments
) {
3265 while (commentCount
-- > 0) {
3266 uint length
= drflac__le2host_32(*cast(uint*)pComments
);
3268 pComments
+= length
;
3278 // v0.3d - 11/06/2016
3279 // - Minor clean up.
3281 // v0.3c - 28/05/2016
3282 // - Fixed compilation error.
3284 // v0.3b - 16/05/2016
3285 // - Fixed Linux/GCC build.
3286 // - Updated documentation.
3288 // v0.3a - 15/05/2016
3289 // - Minor fixes to documentation.
3291 // v0.3 - 11/05/2016
3292 // - Optimizations. Now at about parity with the reference implementation on 32-bit builds.
3293 // - Lots of clean up.
3295 // v0.2b - 10/05/2016
3298 // v0.2a - 10/05/2016
3299 // - Made drflac_open_and_decode() more robust.
3300 // - Removed an unused debugging variable
3302 // v0.2 - 09/05/2016
3303 // - Added support for Ogg encapsulation.
3304 // - API CHANGE. Have the onSeek callback take a third argument which specifies whether or not the seek
3305 // should be relative to the start or the current position. Also changes the seeking rules such that
3306 // seeking offsets will never be negative.
3307 // - Have drflac_open_and_decode() fail gracefully if the stream has an unknown total sample count.
3309 // v0.1b - 07/05/2016
3310 // - Properly close the file handle in drflac_open_file() and family when the decoder fails to initialize.
3311 // - Removed a stale comment.
3313 // v0.1a - 05/05/2016
3314 // - Minor formatting changes.
3315 // - Fixed a warning on the GCC build.
3317 // v0.1 - 03/05/2016
3318 // - Initial versioned release.
3321 // - Add support for initializing the decoder without a header STREAMINFO block.
3322 // - Test CUESHEET metadata blocks.
3326 This is free and unencumbered software released into the public domain.
3328 Anyone is free to copy, modify, publish, use, compile, sell, or
3329 distribute this software, either in source code form or as a compiled
3330 binary, for any purpose, commercial or non-commercial, and by any
3333 In jurisdictions that recognize copyright laws, the author or authors
3334 of this software dedicate any and all copyright interest in the
3335 software to the public domain. We make this dedication for the benefit
3336 of the public at large and to the detriment of our heirs and
3337 successors. We intend this dedication to be an overt act of
3338 relinquishment in perpetuity of all present and future rights to this
3339 software under copyright law.
3341 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
3342 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
3343 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
3344 IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
3345 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
3346 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
3347 OTHER DEALINGS IN THE SOFTWARE.
3349 For more information, please refer to <http://unlicense.org/>