Audio: Implement RGSS3 functionality
'Pos' and 'Play' functions take a float for their 'pos' parameter, which is in seconds of playback. 'setupMidi' is a noop at this point.
This commit is contained in:
parent
ef2430e0c3
commit
5fca94616c
110
src/audio.cpp
110
src/audio.cpp
|
@ -556,7 +556,14 @@ struct VorbisSource : ALDataSource
|
||||||
|
|
||||||
void seekToOffset(float seconds)
|
void seekToOffset(float seconds)
|
||||||
{
|
{
|
||||||
ov_time_seek(&vf, seconds);
|
currentFrame = seconds * info.rate;
|
||||||
|
|
||||||
|
if (loop.valid && currentFrame > loop.end)
|
||||||
|
currentFrame = loop.start;
|
||||||
|
|
||||||
|
/* If seeking fails, just seek back to start */
|
||||||
|
if (ov_pcm_seek(&vf, currentFrame) != 0)
|
||||||
|
ov_raw_seek(&vf, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Status fillBuffer(AL::Buffer::ID alBuffer)
|
Status fillBuffer(AL::Buffer::ID alBuffer)
|
||||||
|
@ -569,6 +576,8 @@ struct VorbisSource : ALDataSource
|
||||||
|
|
||||||
Status retStatus = ALDataSource::NoError;
|
Status retStatus = ALDataSource::NoError;
|
||||||
|
|
||||||
|
bool readAgain = false;
|
||||||
|
|
||||||
if (loop.valid)
|
if (loop.valid)
|
||||||
{
|
{
|
||||||
int tilLoopEnd = loop.end * info.frameSize;
|
int tilLoopEnd = loop.end * info.frameSize;
|
||||||
|
@ -602,7 +611,22 @@ struct VorbisSource : ALDataSource
|
||||||
retStatus = ALDataSource::EndOfStream;
|
retStatus = ALDataSource::EndOfStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
/* If we sought right to the end of the file,
|
||||||
|
* we might be EOF without actually having read
|
||||||
|
* any data at all yet (which mustn't happen),
|
||||||
|
* so we try to continue reading some data. */
|
||||||
|
if (bufUsed > 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (readAgain)
|
||||||
|
{
|
||||||
|
/* We're still not getting data though.
|
||||||
|
* Just error out to prevent an endless loop */
|
||||||
|
retStatus = ALDataSource::Error;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
readAgain = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bufUsed += (res / sizeof(int16_t));
|
bufUsed += (res / sizeof(int16_t));
|
||||||
|
@ -682,6 +706,7 @@ struct ALStream
|
||||||
bool threadTermReq;
|
bool threadTermReq;
|
||||||
|
|
||||||
bool needsRewind;
|
bool needsRewind;
|
||||||
|
float startOffset;
|
||||||
|
|
||||||
AL::Source::ID alSrc;
|
AL::Source::ID alSrc;
|
||||||
AL::Buffer::ID alBuf[streamBufs];
|
AL::Buffer::ID alBuf[streamBufs];
|
||||||
|
@ -790,7 +815,7 @@ struct ALStream
|
||||||
state = Stopped;
|
state = Stopped;
|
||||||
}
|
}
|
||||||
|
|
||||||
void play()
|
void play(float offset = 0)
|
||||||
{
|
{
|
||||||
checkStopped();
|
checkStopped();
|
||||||
|
|
||||||
|
@ -800,7 +825,7 @@ struct ALStream
|
||||||
case Playing:
|
case Playing:
|
||||||
return;
|
return;
|
||||||
case Stopped:
|
case Stopped:
|
||||||
startStream();
|
startStream(offset);
|
||||||
break;
|
break;
|
||||||
case Paused :
|
case Paused :
|
||||||
resumeStream();
|
resumeStream();
|
||||||
|
@ -826,15 +851,6 @@ struct ALStream
|
||||||
state = Paused;
|
state = Paused;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setOffset(float value)
|
|
||||||
{
|
|
||||||
if (state == Closed)
|
|
||||||
return;
|
|
||||||
// XXX needs more work. protect source with mutex
|
|
||||||
source->seekToOffset(value);
|
|
||||||
needsRewind = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setVolume(float value)
|
void setVolume(float value)
|
||||||
{
|
{
|
||||||
AL::Source::setVolume(alSrc, value);
|
AL::Source::setVolume(alSrc, value);
|
||||||
|
@ -907,16 +923,18 @@ private:
|
||||||
procFrames = 0;
|
procFrames = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void startStream()
|
void startStream(float offset)
|
||||||
{
|
{
|
||||||
clearALQueue();
|
clearALQueue();
|
||||||
|
|
||||||
procFrames = 0;
|
|
||||||
|
|
||||||
preemptPause = false;
|
preemptPause = false;
|
||||||
streamInited = false;
|
streamInited = false;
|
||||||
sourceExhausted = false;
|
sourceExhausted = false;
|
||||||
threadTermReq = false;
|
threadTermReq = false;
|
||||||
|
|
||||||
|
startOffset = offset;
|
||||||
|
procFrames = offset * source->sampleRate();
|
||||||
|
|
||||||
thread = SDL_CreateThread(streamDataFun, "al_stream", this);
|
thread = SDL_CreateThread(streamDataFun, "al_stream", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -988,7 +1006,12 @@ private:
|
||||||
ALDataSource::Status status;
|
ALDataSource::Status status;
|
||||||
|
|
||||||
if (needsRewind)
|
if (needsRewind)
|
||||||
source->reset();
|
{
|
||||||
|
if (startOffset > 0)
|
||||||
|
source->seekToOffset(startOffset);
|
||||||
|
else
|
||||||
|
source->reset();
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < streamBufs; ++i)
|
for (int i = 0; i < streamBufs; ++i)
|
||||||
{
|
{
|
||||||
|
@ -1177,7 +1200,8 @@ struct AudioStream
|
||||||
|
|
||||||
void play(const std::string &filename,
|
void play(const std::string &filename,
|
||||||
int volume,
|
int volume,
|
||||||
int pitch)
|
int pitch,
|
||||||
|
float offset = 0)
|
||||||
{
|
{
|
||||||
finiFadeInt();
|
finiFadeInt();
|
||||||
|
|
||||||
|
@ -1236,7 +1260,7 @@ struct AudioStream
|
||||||
current.pitch = _pitch;
|
current.pitch = _pitch;
|
||||||
|
|
||||||
if (!extPaused)
|
if (!extPaused)
|
||||||
stream.play();
|
stream.play(offset);
|
||||||
|
|
||||||
unlockStream();
|
unlockStream();
|
||||||
}
|
}
|
||||||
|
@ -1323,6 +1347,11 @@ struct AudioStream
|
||||||
updateVolume();
|
updateVolume();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float playingOffset()
|
||||||
|
{
|
||||||
|
return stream.queryOffset();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void finiFadeInt()
|
void finiFadeInt()
|
||||||
{
|
{
|
||||||
|
@ -1600,10 +1629,18 @@ Audio::Audio()
|
||||||
|
|
||||||
|
|
||||||
void Audio::bgmPlay(const char *filename,
|
void Audio::bgmPlay(const char *filename,
|
||||||
int volume,
|
int volume,
|
||||||
int pitch)
|
int pitch
|
||||||
|
#ifdef RGSS3
|
||||||
|
,float pos
|
||||||
|
#endif
|
||||||
|
)
|
||||||
{
|
{
|
||||||
|
#ifdef RGSS3
|
||||||
|
p->bgm.play(filename, volume, pitch, pos);
|
||||||
|
#else
|
||||||
p->bgm.play(filename, volume, pitch);
|
p->bgm.play(filename, volume, pitch);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Audio::bgmStop()
|
void Audio::bgmStop()
|
||||||
|
@ -1618,10 +1655,18 @@ void Audio::bgmFade(int time)
|
||||||
|
|
||||||
|
|
||||||
void Audio::bgsPlay(const char *filename,
|
void Audio::bgsPlay(const char *filename,
|
||||||
int volume,
|
int volume,
|
||||||
int pitch)
|
int pitch
|
||||||
|
#ifdef RGSS3
|
||||||
|
,float pos
|
||||||
|
#endif
|
||||||
|
)
|
||||||
{
|
{
|
||||||
|
#ifdef RGSS3
|
||||||
|
p->bgs.play(filename, volume, pitch, pos);
|
||||||
|
#else
|
||||||
p->bgs.play(filename, volume, pitch);
|
p->bgs.play(filename, volume, pitch);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Audio::bgsStop()
|
void Audio::bgsStop()
|
||||||
|
@ -1665,4 +1710,23 @@ void Audio::seStop()
|
||||||
p->se.stop();
|
p->se.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef RGSS3
|
||||||
|
|
||||||
|
void Audio::setupMidi()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
float Audio::bgmPos()
|
||||||
|
{
|
||||||
|
return p->bgm.playingOffset();
|
||||||
|
}
|
||||||
|
|
||||||
|
float Audio::bgsPos()
|
||||||
|
{
|
||||||
|
return p->bgs.playingOffset();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
Audio::~Audio() { delete p; }
|
Audio::~Audio() { delete p; }
|
||||||
|
|
40
src/audio.h
40
src/audio.h
|
@ -22,6 +22,16 @@
|
||||||
#ifndef AUDIO_H
|
#ifndef AUDIO_H
|
||||||
#define AUDIO_H
|
#define AUDIO_H
|
||||||
|
|
||||||
|
/* Concerning the 'pos' parameter:
|
||||||
|
* RGSS3 actually doesn't specify a format for this,
|
||||||
|
* it's only implied that it is a numerical value
|
||||||
|
* (must be 0 on invalid cases), and it's not used for
|
||||||
|
* anything outside passing it back into bgm/bgs_play.
|
||||||
|
* We use this freedom to define pos to be a float,
|
||||||
|
* in seconds of playback. (RGSS3 seems to use large
|
||||||
|
* integers that _look_ like sample offsets but I can't
|
||||||
|
* quite make out their meaning yet) */
|
||||||
|
|
||||||
struct AudioPrivate;
|
struct AudioPrivate;
|
||||||
|
|
||||||
class Audio
|
class Audio
|
||||||
|
@ -30,21 +40,43 @@ public:
|
||||||
Audio();
|
Audio();
|
||||||
~Audio();
|
~Audio();
|
||||||
|
|
||||||
void bgmPlay(const char *filename, int volume = 100, int pitch = 100);
|
void bgmPlay(const char *filename,
|
||||||
|
int volume = 100,
|
||||||
|
int pitch = 100
|
||||||
|
#ifdef RGSS3
|
||||||
|
,float pos = 0
|
||||||
|
#endif
|
||||||
|
);
|
||||||
void bgmStop();
|
void bgmStop();
|
||||||
void bgmFade(int time);
|
void bgmFade(int time);
|
||||||
|
|
||||||
void bgsPlay(const char *filename, int volume = 100, int pitch = 100);
|
void bgsPlay(const char *filename,
|
||||||
|
int volume = 100,
|
||||||
|
int pitch = 100
|
||||||
|
#ifdef RGSS3
|
||||||
|
,float pos = 0
|
||||||
|
#endif
|
||||||
|
);
|
||||||
void bgsStop();
|
void bgsStop();
|
||||||
void bgsFade(int time);
|
void bgsFade(int time);
|
||||||
|
|
||||||
void mePlay(const char *filename, int volume = 100, int pitch = 100);
|
void mePlay(const char *filename,
|
||||||
|
int volume = 100,
|
||||||
|
int pitch = 100);
|
||||||
void meStop();
|
void meStop();
|
||||||
void meFade(int time);
|
void meFade(int time);
|
||||||
|
|
||||||
void sePlay(const char *filename, int volume = 100, int pitch = 100);
|
void sePlay(const char *filename,
|
||||||
|
int volume = 100,
|
||||||
|
int pitch = 100);
|
||||||
void seStop();
|
void seStop();
|
||||||
|
|
||||||
|
#ifdef RGSS3
|
||||||
|
void setupMidi();
|
||||||
|
float bgmPos();
|
||||||
|
float bgsPos();
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AudioPrivate *p;
|
AudioPrivate *p;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue