mirror of
https://github.com/love2d/love.git
synced 2026-08-19 20:19:42 +02:00
Merged in AuahDark/love/flac-audio (pull request #125)
Enable FLAC audio support.
This commit is contained in:
@@ -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
@@ -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
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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>(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user