mirror of
https://github.com/love2d/love.git
synced 2026-08-17 11:00:31 +02:00
Merged love.audio changes.
This commit is contained in:
@@ -60,7 +60,11 @@ namespace lullaby
|
||||
bool ModPlugDecoder::accepts(const std::string & ext)
|
||||
{
|
||||
static const std::string supported[] = {
|
||||
"it", "xm", "mod", "wav", ""
|
||||
"699", "abc", "amf", "ams", "dbm", "dmf",
|
||||
"dsm", "far", "it", "j2b", "mdl", "med",
|
||||
"mid", "mod", "mt2", "mtm", "okt", "pat",
|
||||
"psm", "s3m", "stm", "ult", "umx", "wav",
|
||||
"xm", ""
|
||||
};
|
||||
|
||||
for(int i = 0; !(supported[i].empty()); i++)
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace lullaby
|
||||
public:
|
||||
|
||||
ModPlugDecoder(Data * data, const std::string & ext, int bufferSize, int sampleRate);
|
||||
~ModPlugDecoder();
|
||||
virtual ~ModPlugDecoder();
|
||||
|
||||
static bool accepts(const std::string & ext);
|
||||
|
||||
|
||||
@@ -34,9 +34,12 @@ namespace lullaby
|
||||
bool Mpg123Decoder::inited = false;
|
||||
|
||||
Mpg123Decoder::Mpg123Decoder(Data * data, const std::string & ext, int bufferSize, int sampleRate)
|
||||
: Decoder(data, ext, bufferSize, sampleRate), handle(0), islooping(false)
|
||||
: Decoder(data, ext, bufferSize, sampleRate), handle(0)
|
||||
{
|
||||
|
||||
data_size = data->getSize();
|
||||
data_offset = 0;
|
||||
|
||||
int ret;
|
||||
|
||||
if(!inited)
|
||||
@@ -57,21 +60,11 @@ namespace lullaby
|
||||
ret = mpg123_format(handle, sampleRate, MPG123_STEREO, MPG123_ENC_SIGNED_16);
|
||||
if (ret != MPG123_OK)
|
||||
throw love::Exception("Could not set output format.");
|
||||
size_t numbytes = 0;
|
||||
ret = mpg123_decode(handle, (unsigned char*)data->getData(), data->getSize(), NULL, 0, &numbytes);
|
||||
|
||||
if(ret == MPG123_NEW_FORMAT)
|
||||
{
|
||||
long rate;
|
||||
int channels;
|
||||
int encoding;
|
||||
mpg123_getformat(handle, &rate, &channels, &encoding);
|
||||
}
|
||||
else if(ret != 0)
|
||||
{
|
||||
throw love::Exception(mpg123_strerror(handle));
|
||||
}
|
||||
|
||||
ret = feed(16384);
|
||||
|
||||
if (ret != MPG123_OK && ret != MPG123_DONE)
|
||||
throw love::Exception("Could not feed!");
|
||||
}
|
||||
|
||||
Mpg123Decoder::~Mpg123Decoder()
|
||||
@@ -108,26 +101,51 @@ namespace lullaby
|
||||
|
||||
int Mpg123Decoder::decode()
|
||||
{
|
||||
size_t numbytes;
|
||||
int r = mpg123_read(handle, (unsigned char*) buffer, bufferSize, &numbytes);
|
||||
|
||||
if (r == MPG123_DONE || r != MPG123_OK)
|
||||
int size = 0;
|
||||
bool done = false;
|
||||
|
||||
while(size < bufferSize && !done && !eof)
|
||||
{
|
||||
if ( r == MPG123_NEED_MORE && islooping )
|
||||
{
|
||||
islooping = false;
|
||||
size_t numbytes = 0;
|
||||
mpg123_decode(handle, (unsigned char*) data->getData(), data->getSize(), (unsigned char*) buffer, bufferSize, &numbytes);
|
||||
}
|
||||
else
|
||||
size_t numbytes = 0;
|
||||
|
||||
int r = mpg123_read(handle, (unsigned char*) buffer + size, bufferSize - size, &numbytes);
|
||||
|
||||
switch(r)
|
||||
{
|
||||
case MPG123_NEW_FORMAT:
|
||||
continue;
|
||||
case MPG123_NEED_MORE:
|
||||
{
|
||||
int v = feed(8192);
|
||||
|
||||
switch(v)
|
||||
{
|
||||
case MPG123_OK:
|
||||
continue;
|
||||
case MPG123_DONE:
|
||||
if(numbytes == 0)
|
||||
eof = true;
|
||||
break;
|
||||
default:
|
||||
done = true;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
case MPG123_OK:
|
||||
size += numbytes;
|
||||
continue;
|
||||
case MPG123_DONE:
|
||||
// Apparently, mpg123_read does not return MPG123_DONE, but
|
||||
// let's keep it here anyway.
|
||||
eof = true;
|
||||
numbytes = 0;
|
||||
default:
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return numbytes;
|
||||
return size;
|
||||
}
|
||||
|
||||
bool Mpg123Decoder::seek(float s)
|
||||
@@ -139,11 +157,16 @@ namespace lullaby
|
||||
|
||||
bool Mpg123Decoder::rewind()
|
||||
{
|
||||
if(mpg123_seek(handle, 0, SEEK_SET) >= 0)
|
||||
return false;
|
||||
islooping = true;
|
||||
eof = false;
|
||||
return true;
|
||||
off_t offset;
|
||||
|
||||
if(mpg123_feedseek(handle, 0, SEEK_SET, &offset) >= 0)
|
||||
{
|
||||
data_offset = offset;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Mpg123Decoder::isSeekable()
|
||||
@@ -160,7 +183,23 @@ namespace lullaby
|
||||
{
|
||||
return 16;
|
||||
}
|
||||
|
||||
int Mpg123Decoder::feed(int bytes)
|
||||
{
|
||||
int remaining = data_size - data_offset;
|
||||
|
||||
if(remaining <= 0)
|
||||
return MPG123_DONE;
|
||||
|
||||
int feed_bytes = remaining < bytes ? remaining : bytes;
|
||||
|
||||
int r = mpg123_feed(handle, (unsigned char*)data->getData() + data_offset, feed_bytes);
|
||||
|
||||
if(r == MPG123_OK || r == MPG123_DONE)
|
||||
data_offset += feed_bytes;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
} // lullaby
|
||||
} // sound
|
||||
|
||||
@@ -43,13 +43,15 @@ namespace lullaby
|
||||
private:
|
||||
|
||||
mpg123_handle * handle;
|
||||
bool islooping;
|
||||
static bool inited;
|
||||
|
||||
int data_offset;
|
||||
int data_size;
|
||||
|
||||
public:
|
||||
|
||||
Mpg123Decoder(Data * data, const std::string & ext, int bufferSize, int sampleRate);
|
||||
~Mpg123Decoder();
|
||||
virtual ~Mpg123Decoder();
|
||||
|
||||
static bool accepts(const std::string & ext);
|
||||
static void quit();
|
||||
@@ -62,6 +64,10 @@ namespace lullaby
|
||||
int getChannels() const;
|
||||
int getBits() const;
|
||||
|
||||
private:
|
||||
|
||||
int feed(int bytes);
|
||||
|
||||
}; // Decoder
|
||||
|
||||
} // lullaby
|
||||
|
||||
@@ -55,9 +55,9 @@ namespace lullaby
|
||||
// Find a suitable decoder here, and return it.
|
||||
if(ModPlugDecoder::accepts(ext))
|
||||
decoder = new ModPlugDecoder(data, ext, bufferSize, sampleRate);
|
||||
else if (Mpg123Decoder::accepts(ext))
|
||||
else if(Mpg123Decoder::accepts(ext))
|
||||
decoder = new Mpg123Decoder(data, ext, bufferSize, sampleRate);
|
||||
else if (VorbisDecoder::accepts(ext))
|
||||
else if(VorbisDecoder::accepts(ext))
|
||||
decoder = new VorbisDecoder(data, ext, bufferSize, sampleRate);
|
||||
/*else if (FLACDecoder::accepts(ext))
|
||||
decoder = new FLACDecoder(data, ext, bufferSize, sampleRate);*/
|
||||
|
||||
@@ -182,42 +182,20 @@ namespace lullaby
|
||||
|
||||
int VorbisDecoder::decode()
|
||||
{
|
||||
int bits = this->getBits();
|
||||
int size = 0;
|
||||
int section;
|
||||
int result;
|
||||
|
||||
if(bits == 16)
|
||||
bits = 2;
|
||||
else
|
||||
bits = 1;
|
||||
|
||||
while(size < bufferSize)
|
||||
{
|
||||
result = ov_read(&handle, (char*) buffer + size, bufferSize - size, endian, bits, 1, §ion);
|
||||
int result = ov_read(&handle, (char*) buffer + size, bufferSize - size, endian, (getBits() == 16 ? 2 : 1), 1, 0);
|
||||
|
||||
if(result > 0)
|
||||
size += result;
|
||||
else if(result < 0)
|
||||
{
|
||||
switch(result)
|
||||
{
|
||||
case OV_EREAD:
|
||||
throw love::Exception("Vorbis read: Read from media");
|
||||
case OV_ENOTVORBIS:
|
||||
throw love::Exception("Vorbis read: Not Vorbis data");
|
||||
case OV_EVERSION:
|
||||
throw love::Exception("Vorbis read: Vorbis version mismatch");
|
||||
case OV_EBADHEADER:
|
||||
throw love::Exception("Vorbis read: Invalid Vorbis header");
|
||||
case OV_EFAULT:
|
||||
throw love::Exception("Vorbis read: Internal logic fault (bug or heap/stack corruption)");
|
||||
default:
|
||||
throw love::Exception("Vorbis read: Unknown error");
|
||||
}
|
||||
}
|
||||
else
|
||||
if(result == OV_HOLE)
|
||||
continue;
|
||||
else if(result <= OV_EREAD)
|
||||
return -1;
|
||||
else if(result == 0)
|
||||
break;
|
||||
else if(result > 0)
|
||||
size += result;
|
||||
}
|
||||
|
||||
if(oggFile.dataSize - oggFile.dataRead == 0)
|
||||
@@ -256,7 +234,8 @@ namespace lullaby
|
||||
bool VorbisDecoder::rewind()
|
||||
{
|
||||
eof = false;
|
||||
return this->seek(0);
|
||||
ov_pcm_seek(&handle, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VorbisDecoder::isSeekable()
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace lullaby
|
||||
public:
|
||||
|
||||
VorbisDecoder(Data * data, const std::string & ext, int bufferSize, int sampleRate);
|
||||
~VorbisDecoder();
|
||||
virtual ~VorbisDecoder();
|
||||
|
||||
static bool accepts(const std::string & ext);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user