Merged in AuahDark/love/flac-audio (pull request #125)

Enable FLAC audio support.
This commit is contained in:
Alex Szpakowski
2019-06-25 23:02:44 +00:00
5 changed files with 8973 additions and 113 deletions
+6
View File
@@ -74,6 +74,12 @@ This distribution contains code from the following projects (full license text b
You can contact the author at : You can contact the author at :
- xxHash source repository : https://github.com/Cyan4973/xxHash - xxHash source repository : https://github.com/Cyan4973/xxHash
- dr_flac
Website: https://github.com/mackron/dr_libs
Source download: https://github.com/mackron/dr_libs/blob/41bc0e8/dr_flac.h
License: MIT/Expat
Copyright 2018 David Reid
- libmpg123 - libmpg123
Website: http://www.mpg123.de/ Website: http://www.mpg123.de/
Source download: http://sourceforge.net/projects/mpg123/files/latest/download Source download: http://sourceforge.net/projects/mpg123/files/latest/download
File diff suppressed because it is too large Load Diff
+32 -94
View File
@@ -18,8 +18,7 @@
* 3. This notice may not be removed or altered from any source distribution. * 3. This notice may not be removed or altered from any source distribution.
**/ **/
#if 0 #define DR_FLAC_IMPLEMENTATION
#include "FLACDecoder.h" #include "FLACDecoder.h"
#include <set> #include <set>
@@ -33,29 +32,27 @@ namespace lullaby
{ {
FLACDecoder::FLACDecoder(Data *data, int nbufferSize) FLACDecoder::FLACDecoder(Data *data, int nbufferSize)
: Decoder(data, nbufferSize) : Decoder(data, nbufferSize)
, pos(0)
{ {
init(); flac = drflac_open_memory(data->getData(), data->getSize());
init_ogg(); if (flac == nullptr)
process_until_end_of_metadata(); throw love::Exception("Could not load FLAC file");
process_single();
seek(0);
bufferSize = 256 * getBitDepth() * getChannelCount() * 2;
delete[](char *) buffer;
buffer = new char[bufferSize];
} }
FLACDecoder::~FLACDecoder() FLACDecoder::~FLACDecoder()
{ {
finish(); drflac_close(flac);
} }
bool FLACDecoder::accepts(const std::string &ext) bool FLACDecoder::accepts(const std::string &ext)
{ {
// dr_flac supports FLAC encapsulated in Ogg, but unfortunately
// LOVE detects .ogg extension as Vorbis. It would be a good idea
// to always probe in the future (see #1487 and commit ccf9e63).
// Please remove once it's no longer the case.
static const std::string supported[] = static const std::string supported[] =
{ {
"flac", "" "flac", "ogg"
}; };
for (int i = 0; !(supported[i].empty()); i++) for (int i = 0; !(supported[i].empty()); i++)
@@ -74,18 +71,31 @@ love::sound::Decoder *FLACDecoder::clone()
int FLACDecoder::decode() int FLACDecoder::decode()
{ {
process_single(); // `bufferSize` is in bytes, so divide by 2.
return bufferSize; drflac_uint64 readed = drflac_read_pcm_frames_s16(flac, bufferSize / 2 / flac->channels, (drflac_int16 *) buffer);
readed = readed * 2 * flac->channels;
if (readed < bufferSize)
eof = true;
return (int) readed;
} }
bool FLACDecoder::seek(double s) bool FLACDecoder::seek(double s)
{ {
return seek_absolute((int)(s*1000.0)); double duration = getDuration();
drflac_uint64 seekPosition = (drflac_uint64) (s * ((double) flac->totalPCMFrameCount) / duration);
drflac_bool32 result = drflac_seek_to_pcm_frame(flac, seekPosition);
if (result)
eof = false;
return result;
} }
bool FLACDecoder::rewind() bool FLACDecoder::rewind()
{ {
return seek_absolute(0); return seek(0);
} }
bool FLACDecoder::isSeekable() bool FLACDecoder::isSeekable()
@@ -95,97 +105,25 @@ bool FLACDecoder::isSeekable()
int FLACDecoder::getChannelCount() const int FLACDecoder::getChannelCount() const
{ {
return get_channels(); return flac->channels;
} }
int FLACDecoder::getBitDepth() const int FLACDecoder::getBitDepth() const
{ {
return get_bits_per_sample(); return 16;
} }
int FLACDecoder::getSampleRate() const int FLACDecoder::getSampleRate() const
{ {
return get_sample_rate(); return flac->sampleRate;
} }
double FLACDecoder::getDuration() double FLACDecoder::getDuration()
{ {
return -1; return ((double) flac->totalPCMFrameCount) / ((double) flac->sampleRate);
} }
FLAC__StreamDecoderReadStatus FLACDecoder::read_callback(FLAC__byte buffer[], size_t *bytes)
{
int size = data->getSize();
char *d = (char *) data->getData() + pos;
if (pos >= size)
{
eof = true;
return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
}
if (pos+*bytes <= (unsigned int)size)
{
memcpy(buffer, d, *bytes);
pos = pos+*bytes;
}
else
{
memcpy(buffer, d, size-pos);
*bytes = size-pos;
pos = size;
}
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
}
FLAC__StreamDecoderSeekStatus FLACDecoder::seek_callback(FLAC__uint64 offset)
{
pos = (int)offset;
return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
}
FLAC__StreamDecoderTellStatus FLACDecoder::tell_callback(FLAC__uint64 *offset)
{
*offset = pos;
return FLAC__STREAM_DECODER_TELL_STATUS_OK;
}
FLAC__StreamDecoderLengthStatus FLACDecoder::length_callback(FLAC__uint64 *length)
{
*length = data->getSize();
return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
}
bool FLACDecoder::eof_callback()
{
eof = (pos >= data->getSize());
return eof;
}
FLAC__StreamDecoderWriteStatus FLACDecoder::write_callback(const FLAC__Frame *frame, const FLAC__int32 *const fbuffer[])
{
int i, j;
for (i = 0, j = 0; i < bufferSize; i += 4, j++)
{
((char *)buffer)[i] = fbuffer[0][j];
((char *)buffer)[i+1] = fbuffer[0][j] >> 8;
((char *)buffer)[i+2] = fbuffer[1][j];
((char *)buffer)[i+3] = fbuffer[1][j] >> 8;
}
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
}
void FLACDecoder::metadata_callback(const FLAC__StreamMetadata *metadata)
{
//we do nothing with metadata...
return;
}
void FLACDecoder::error_callback(FLAC__StreamDecoderErrorStatus status)
{
//wow.. error, let's throw one (please clean this part up sometime)
throw love::Exception("FLAC error: %s!", FLAC__StreamDecoderErrorStatusString[status]);
}
} // lullaby } // lullaby
} // sound } // sound
} // love } // love
#endif // 0
+3 -17
View File
@@ -21,13 +21,11 @@
#ifndef LOVE_SOUND_LULLABY_FLAC_DECODER_H #ifndef LOVE_SOUND_LULLABY_FLAC_DECODER_H
#define LOVE_SOUND_LULLABY_FLAC_DECODER_H #define LOVE_SOUND_LULLABY_FLAC_DECODER_H
#if 0
// LOVE // LOVE
#include "common/Data.h" #include "common/Data.h"
#include "sound/Decoder.h" #include "sound/Decoder.h"
#include <FLAC++/decoder.h> #include "dr_flac/dr_flac.h"
#include <string.h> #include <string.h>
namespace love namespace love
@@ -37,7 +35,7 @@ namespace sound
namespace lullaby namespace lullaby
{ {
class FLACDecoder : public Decoder, public FLAC::Decoder::Stream class FLACDecoder : public Decoder
{ {
public: public:
FLACDecoder(Data *data, int bufferSize); FLACDecoder(Data *data, int bufferSize);
@@ -54,24 +52,12 @@ public:
int getSampleRate() const; int getSampleRate() const;
double getDuration(); double getDuration();
//needed for FLAC
FLAC__StreamDecoderReadStatus read_callback(FLAC__byte buffer[], size_t *bytes);
FLAC__StreamDecoderSeekStatus seek_callback(FLAC__uint64 offset);
FLAC__StreamDecoderTellStatus tell_callback(FLAC__uint64 *offset);
FLAC__StreamDecoderLengthStatus length_callback(FLAC__uint64 *length);
bool eof_callback();
FLAC__StreamDecoderWriteStatus write_callback(const FLAC__Frame *frame, const FLAC__int32 *const buffer[]);
void metadata_callback(const FLAC__StreamMetadata *metadata);
void error_callback(FLAC__StreamDecoderErrorStatus status);
private: private:
int pos; drflac *flac;
}; // Decoder }; // Decoder
} // lullaby } // lullaby
} // sound } // sound
} // love } // love
#endif // 0
#endif // LOVE_SOUND_LULLABY_FLAC_DECODER_H #endif // LOVE_SOUND_LULLABY_FLAC_DECODER_H
+2 -2
View File
@@ -29,7 +29,7 @@
#include "VorbisDecoder.h" #include "VorbisDecoder.h"
#include "GmeDecoder.h" #include "GmeDecoder.h"
#include "WaveDecoder.h" #include "WaveDecoder.h"
//#include "FLACDecoder.h" #include "FLACDecoder.h"
#ifndef LOVE_NOMPG123 #ifndef LOVE_NOMPG123
# include "Mpg123Decoder.h" # include "Mpg123Decoder.h"
@@ -103,7 +103,7 @@ sound::Decoder *Sound::newDecoder(love::filesystem::FileData *data, int bufferSi
DecoderImplFor<CoreAudioDecoder>(), DecoderImplFor<CoreAudioDecoder>(),
#endif #endif
DecoderImplFor<WaveDecoder>(), DecoderImplFor<WaveDecoder>(),
// DecoderImplFor<FLACDecoder>(), DecoderImplFor<FLACDecoder>(),
// DecoderImplFor<OtherDecoder>(), // DecoderImplFor<OtherDecoder>(),
}; };