Audio: Remove all traces of rubberband
We will not be using librubberband for in place pitch shifting. RMXP "shifts" PCM based audio by just playing it back slower/faster, which OpenAL takes care of for us. A native midi backend will be able to effortlessly pitch shift by multiplying note pitches, should we ever get one. I have been chasing this ghost for way too long.
This commit is contained in:
parent
e26d0366f1
commit
a817b31e7c
187
src/audio.cpp
187
src/audio.cpp
|
@ -48,81 +48,6 @@
|
||||||
#define SE_SOURCES 6
|
#define SE_SOURCES 6
|
||||||
#define SE_CACHE_MEM (10*1024*1024) // 10 MB
|
#define SE_CACHE_MEM (10*1024*1024) // 10 MB
|
||||||
|
|
||||||
static void genFloatSamples(int sampleCount, int sdlFormat, const void *in, float *out)
|
|
||||||
{
|
|
||||||
(void) genFloatSamples;
|
|
||||||
|
|
||||||
int i = sampleCount;
|
|
||||||
|
|
||||||
/* Convert from the possible fixed point
|
|
||||||
* formats to [-1;1] floats */
|
|
||||||
switch (sdlFormat)
|
|
||||||
{
|
|
||||||
case AUDIO_U8 :
|
|
||||||
{
|
|
||||||
const uint8_t *_in = static_cast<const uint8_t*>(in);
|
|
||||||
|
|
||||||
while (i--)
|
|
||||||
out[i] = (((float) _in[i] / 255.f) - 0.5) * 2;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case AUDIO_S8 :
|
|
||||||
{
|
|
||||||
const int8_t *_in = static_cast<const int8_t*>(in);
|
|
||||||
|
|
||||||
while (i--)
|
|
||||||
out[i] = (float) _in[i] / 128.f; // ???
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case AUDIO_U16LSB :
|
|
||||||
{
|
|
||||||
const uint16_t *_in = static_cast<const uint16_t*>(in);
|
|
||||||
|
|
||||||
while (i--)
|
|
||||||
out[i] = (((float) _in[i] / 65536.f) - 0.5) * 2;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case AUDIO_U16MSB :
|
|
||||||
{
|
|
||||||
const int16_t *_in = static_cast<const int16_t*>(in);
|
|
||||||
|
|
||||||
while (i--)
|
|
||||||
{
|
|
||||||
int16_t swp = SDL_Swap16(_in[i]);
|
|
||||||
out[i] = (((float) swp / 65536.f) - 0.5) * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case AUDIO_S16LSB :
|
|
||||||
{
|
|
||||||
const int16_t *_in = static_cast<const int16_t*>(in);
|
|
||||||
|
|
||||||
while (i--)
|
|
||||||
out[i] = (float) _in[i] / 32768.f; // ???
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case AUDIO_S16MSB :
|
|
||||||
{
|
|
||||||
const int16_t *_in = static_cast<const int16_t*>(in);
|
|
||||||
|
|
||||||
while (i--)
|
|
||||||
{
|
|
||||||
int16_t swp = SDL_Swap16(_in[i]);
|
|
||||||
out[i] = (float) swp / 32768.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
qDebug() << "Unhandled sample format";
|
|
||||||
default: Q_ASSERT(0); // XXX
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t formatSampleSize(int sdlFormat)
|
static uint8_t formatSampleSize(int sdlFormat)
|
||||||
{
|
{
|
||||||
switch (sdlFormat)
|
switch (sdlFormat)
|
||||||
|
@ -183,10 +108,8 @@ static const int streamBufSize = 32768;
|
||||||
|
|
||||||
struct SoundBuffer
|
struct SoundBuffer
|
||||||
{
|
{
|
||||||
/* Filename, pitch.
|
/* Uniquely identifies this or equal buffer */
|
||||||
* Uniquely identifies this or equal buffer */
|
QByteArray key;
|
||||||
typedef QPair<QByteArray, int> Key;
|
|
||||||
Key key;
|
|
||||||
|
|
||||||
AL::Buffer::ID alBuffer;
|
AL::Buffer::ID alBuffer;
|
||||||
|
|
||||||
|
@ -229,7 +152,7 @@ struct SoundBuffer
|
||||||
struct SoundEmitter
|
struct SoundEmitter
|
||||||
{
|
{
|
||||||
IntruList<SoundBuffer> buffers;
|
IntruList<SoundBuffer> buffers;
|
||||||
QHash<SoundBuffer::Key, SoundBuffer*> bufferHash;
|
QHash<QByteArray, SoundBuffer*> bufferHash;
|
||||||
|
|
||||||
/* Byte count sum of all cached / playing buffers */
|
/* Byte count sum of all cached / playing buffers */
|
||||||
uint32_t bufferBytes;
|
uint32_t bufferBytes;
|
||||||
|
@ -239,10 +162,6 @@ struct SoundEmitter
|
||||||
/* Index of next source to be used */
|
/* Index of next source to be used */
|
||||||
int srcIndex;
|
int srcIndex;
|
||||||
|
|
||||||
#ifdef RUBBERBAND
|
|
||||||
std::vector<float> floatBuf;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SoundEmitter()
|
SoundEmitter()
|
||||||
: bufferBytes(0),
|
: bufferBytes(0),
|
||||||
srcIndex(0)
|
srcIndex(0)
|
||||||
|
@ -252,9 +171,6 @@ struct SoundEmitter
|
||||||
alSrcs[i] = AL::Source::gen();
|
alSrcs[i] = AL::Source::gen();
|
||||||
atchBufs[i] = 0;
|
atchBufs[i] = 0;
|
||||||
}
|
}
|
||||||
#ifdef RUBBERBAND
|
|
||||||
floatBuf.resize(streamBufSize/4);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~SoundEmitter()
|
~SoundEmitter()
|
||||||
|
@ -268,7 +184,7 @@ struct SoundEmitter
|
||||||
SoundBuffer::deref(atchBufs[i]);
|
SoundBuffer::deref(atchBufs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
QHash<SoundBuffer::Key, SoundBuffer*>::iterator iter;
|
QHash<QByteArray, SoundBuffer*>::iterator iter;
|
||||||
for (iter = bufferHash.begin(); iter != bufferHash.end(); ++iter)
|
for (iter = bufferHash.begin(); iter != bufferHash.end(); ++iter)
|
||||||
delete iter.value();
|
delete iter.value();
|
||||||
}
|
}
|
||||||
|
@ -278,8 +194,9 @@ struct SoundEmitter
|
||||||
int pitch)
|
int pitch)
|
||||||
{
|
{
|
||||||
float _volume = clamp<int>(volume, 0, 100) / 100.f;
|
float _volume = clamp<int>(volume, 0, 100) / 100.f;
|
||||||
|
float _pitch = clamp<int>(pitch, 50, 150) / 100.f;
|
||||||
|
|
||||||
SoundBuffer *buffer = allocateBuffer(filename, pitch);
|
SoundBuffer *buffer = allocateBuffer(filename);
|
||||||
|
|
||||||
int soundIndex = srcIndex++;
|
int soundIndex = srcIndex++;
|
||||||
if (srcIndex > SE_SOURCES-1)
|
if (srcIndex > SE_SOURCES-1)
|
||||||
|
@ -297,11 +214,9 @@ struct SoundEmitter
|
||||||
atchBufs[soundIndex] = SoundBuffer::ref(buffer);
|
atchBufs[soundIndex] = SoundBuffer::ref(buffer);
|
||||||
|
|
||||||
AL::Source::attachBuffer(src, buffer->alBuffer);
|
AL::Source::attachBuffer(src, buffer->alBuffer);
|
||||||
AL::Source::setVolume(src, _volume);
|
|
||||||
|
|
||||||
#ifndef RUBBERBAND
|
AL::Source::setVolume(src, _volume);
|
||||||
AL::Source::setPitch(src, clamp<int>(pitch, 50, 150) / 100.f);
|
AL::Source::setPitch(src, _pitch);
|
||||||
#endif
|
|
||||||
|
|
||||||
AL::Source::play(src);
|
AL::Source::play(src);
|
||||||
}
|
}
|
||||||
|
@ -313,26 +228,9 @@ struct SoundEmitter
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#ifdef RUBBERBAND
|
SoundBuffer *allocateBuffer(const QByteArray &filename)
|
||||||
void ensureFloatBufSize(uint32_t size)
|
|
||||||
{
|
{
|
||||||
if (size <= floatBuf.size())
|
SoundBuffer *buffer = bufferHash.value(filename, 0);
|
||||||
return;
|
|
||||||
|
|
||||||
floatBuf.resize(size);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SoundBuffer *allocateBuffer(const QByteArray &filename,
|
|
||||||
int pitch)
|
|
||||||
{
|
|
||||||
#ifndef RUBBERBAND
|
|
||||||
pitch = 100;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SoundBuffer::Key soundKey(filename, pitch);
|
|
||||||
|
|
||||||
SoundBuffer *buffer = bufferHash.value(soundKey, 0);
|
|
||||||
|
|
||||||
if (buffer)
|
if (buffer)
|
||||||
{
|
{
|
||||||
|
@ -364,34 +262,15 @@ private:
|
||||||
uint8_t sampleSize = formatSampleSize(sampleHandle->actual.format);
|
uint8_t sampleSize = formatSampleSize(sampleHandle->actual.format);
|
||||||
uint32_t sampleCount = decBytes / sampleSize;
|
uint32_t sampleCount = decBytes / sampleSize;
|
||||||
|
|
||||||
uint32_t actSampleSize;
|
|
||||||
#ifdef RUBBERBAND
|
|
||||||
actSampleSize = sizeof(float);
|
|
||||||
#else
|
|
||||||
actSampleSize = sampleSize;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
buffer = new SoundBuffer;
|
buffer = new SoundBuffer;
|
||||||
buffer->key = soundKey;
|
buffer->key = filename;
|
||||||
buffer->bytes = actSampleSize * sampleCount;
|
buffer->bytes = sampleSize * sampleCount;
|
||||||
|
|
||||||
ALenum alFormat = chooseALFormat(actSampleSize, sampleHandle->actual.channels);
|
ALenum alFormat = chooseALFormat(sampleSize, sampleHandle->actual.channels);
|
||||||
|
|
||||||
#ifdef RUBBERBAND
|
|
||||||
/* Fill float buffer */
|
|
||||||
ensureFloatBufSize(sampleCount);
|
|
||||||
genFloatSamples(sampleCount, sampleHandle->actual.format,
|
|
||||||
sampleHandle->buffer, floatBuf.data());
|
|
||||||
|
|
||||||
// XXX apply stretcher
|
|
||||||
|
|
||||||
/* Upload data to AL */
|
|
||||||
AL::Buffer::uploadData(buffer->alBuffer, alFormat, floatBuf.data(),
|
|
||||||
buffer->bytes, sampleHandle->actual.rate);
|
|
||||||
#else
|
|
||||||
AL::Buffer::uploadData(buffer->alBuffer, alFormat, sampleHandle->buffer,
|
AL::Buffer::uploadData(buffer->alBuffer, alFormat, sampleHandle->buffer,
|
||||||
buffer->bytes, sampleHandle->actual.rate);
|
buffer->bytes, sampleHandle->actual.rate);
|
||||||
#endif
|
|
||||||
Sound_FreeSample(sampleHandle);
|
Sound_FreeSample(sampleHandle);
|
||||||
|
|
||||||
uint32_t wouldBeBytes = bufferBytes + buffer->bytes;
|
uint32_t wouldBeBytes = bufferBytes + buffer->bytes;
|
||||||
|
@ -409,7 +288,7 @@ private:
|
||||||
SoundBuffer::deref(last);
|
SoundBuffer::deref(last);
|
||||||
}
|
}
|
||||||
|
|
||||||
bufferHash.insert(soundKey, buffer);
|
bufferHash.insert(filename, buffer);
|
||||||
buffers.prepend(buffer->link);
|
buffers.prepend(buffer->link);
|
||||||
|
|
||||||
bufferBytes = wouldBeBytes;
|
bufferBytes = wouldBeBytes;
|
||||||
|
@ -457,12 +336,9 @@ struct SDLSoundSource : ALDataSource
|
||||||
|
|
||||||
SDLSoundSource(const std::string &filename,
|
SDLSoundSource(const std::string &filename,
|
||||||
uint32_t maxBufSize,
|
uint32_t maxBufSize,
|
||||||
bool looped,
|
bool looped)
|
||||||
float pitch)
|
|
||||||
: looped(looped)
|
: looped(looped)
|
||||||
{
|
{
|
||||||
(void) pitch;
|
|
||||||
|
|
||||||
const char *extension;
|
const char *extension;
|
||||||
shState->fileSystem().openRead(ops,
|
shState->fileSystem().openRead(ops,
|
||||||
filename.c_str(),
|
filename.c_str(),
|
||||||
|
@ -505,8 +381,6 @@ struct SDLSoundSource : ALDataSource
|
||||||
if (sample->flags & SOUND_SAMPLEFLAG_ERROR)
|
if (sample->flags & SOUND_SAMPLEFLAG_ERROR)
|
||||||
return ALDataSource::Error;
|
return ALDataSource::Error;
|
||||||
|
|
||||||
// XXX apply stretcher here
|
|
||||||
|
|
||||||
AL::Buffer::uploadData(alBuffer, alFormat, sample->buffer, decoded, alFreq);
|
AL::Buffer::uploadData(alBuffer, alFormat, sample->buffer, decoded, alFreq);
|
||||||
|
|
||||||
if (sample->flags & SOUND_SAMPLEFLAG_EOF)
|
if (sample->flags & SOUND_SAMPLEFLAG_EOF)
|
||||||
|
@ -644,8 +518,7 @@ struct ALStream
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void open(const std::string &filename,
|
void open(const std::string &filename)
|
||||||
float pitch)
|
|
||||||
{
|
{
|
||||||
checkStopped();
|
checkStopped();
|
||||||
|
|
||||||
|
@ -657,7 +530,7 @@ struct ALStream
|
||||||
case Stopped:
|
case Stopped:
|
||||||
closeSource();
|
closeSource();
|
||||||
case Closed:
|
case Closed:
|
||||||
openSource(filename, pitch);
|
openSource(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
state = Stopped;
|
state = Stopped;
|
||||||
|
@ -730,6 +603,11 @@ struct ALStream
|
||||||
AL::Source::setVolume(alSrc, value);
|
AL::Source::setVolume(alSrc, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setPitch(float value)
|
||||||
|
{
|
||||||
|
AL::Source::setPitch(alSrc, value);
|
||||||
|
}
|
||||||
|
|
||||||
State queryState()
|
State queryState()
|
||||||
{
|
{
|
||||||
checkStopped();
|
checkStopped();
|
||||||
|
@ -754,15 +632,10 @@ private:
|
||||||
delete source;
|
delete source;
|
||||||
}
|
}
|
||||||
|
|
||||||
void openSource(const std::string &filename,
|
void openSource(const std::string &filename)
|
||||||
float pitch)
|
|
||||||
{
|
{
|
||||||
source = new SDLSoundSource(filename, streamBufSize, looped, pitch);
|
source = new SDLSoundSource(filename, streamBufSize, looped);
|
||||||
needsRewind = false;
|
needsRewind = false;
|
||||||
|
|
||||||
#ifndef RUBBERBAND
|
|
||||||
AL::Source::setPitch(alSrc, pitch);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void stopStream()
|
void stopStream()
|
||||||
|
@ -1084,19 +957,25 @@ struct AudioStream
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Requested audio file is different from current one */
|
||||||
|
bool diffFile = (filename != current.filename);
|
||||||
|
|
||||||
switch (sState)
|
switch (sState)
|
||||||
{
|
{
|
||||||
case ALStream::Paused :
|
case ALStream::Paused :
|
||||||
case ALStream::Playing :
|
case ALStream::Playing :
|
||||||
stream.stop();
|
stream.stop();
|
||||||
case ALStream::Stopped :
|
case ALStream::Stopped :
|
||||||
stream.close();
|
if (diffFile)
|
||||||
|
stream.close();
|
||||||
case ALStream::Closed :
|
case ALStream::Closed :
|
||||||
|
if (diffFile)
|
||||||
|
stream.open(filename);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
stream.open(filename, _pitch);
|
|
||||||
setBaseVolume(_volume);
|
setBaseVolume(_volume);
|
||||||
|
stream.setPitch(_pitch);
|
||||||
|
|
||||||
current.filename = filename;
|
current.filename = filename;
|
||||||
current.volume = _volume;
|
current.volume = _volume;
|
||||||
|
|
Loading…
Reference in New Issue