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
102
src/audio.cpp
102
src/audio.cpp
|
@ -556,7 +556,14 @@ struct VorbisSource : ALDataSource
|
|||
|
||||
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)
|
||||
|
@ -569,6 +576,8 @@ struct VorbisSource : ALDataSource
|
|||
|
||||
Status retStatus = ALDataSource::NoError;
|
||||
|
||||
bool readAgain = false;
|
||||
|
||||
if (loop.valid)
|
||||
{
|
||||
int tilLoopEnd = loop.end * info.frameSize;
|
||||
|
@ -602,7 +611,22 @@ struct VorbisSource : ALDataSource
|
|||
retStatus = ALDataSource::EndOfStream;
|
||||
}
|
||||
|
||||
/* 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));
|
||||
|
@ -682,6 +706,7 @@ struct ALStream
|
|||
bool threadTermReq;
|
||||
|
||||
bool needsRewind;
|
||||
float startOffset;
|
||||
|
||||
AL::Source::ID alSrc;
|
||||
AL::Buffer::ID alBuf[streamBufs];
|
||||
|
@ -790,7 +815,7 @@ struct ALStream
|
|||
state = Stopped;
|
||||
}
|
||||
|
||||
void play()
|
||||
void play(float offset = 0)
|
||||
{
|
||||
checkStopped();
|
||||
|
||||
|
@ -800,7 +825,7 @@ struct ALStream
|
|||
case Playing:
|
||||
return;
|
||||
case Stopped:
|
||||
startStream();
|
||||
startStream(offset);
|
||||
break;
|
||||
case Paused :
|
||||
resumeStream();
|
||||
|
@ -826,15 +851,6 @@ struct ALStream
|
|||
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)
|
||||
{
|
||||
AL::Source::setVolume(alSrc, value);
|
||||
|
@ -907,16 +923,18 @@ private:
|
|||
procFrames = 0;
|
||||
}
|
||||
|
||||
void startStream()
|
||||
void startStream(float offset)
|
||||
{
|
||||
clearALQueue();
|
||||
|
||||
procFrames = 0;
|
||||
|
||||
preemptPause = false;
|
||||
streamInited = false;
|
||||
sourceExhausted = false;
|
||||
threadTermReq = false;
|
||||
|
||||
startOffset = offset;
|
||||
procFrames = offset * source->sampleRate();
|
||||
|
||||
thread = SDL_CreateThread(streamDataFun, "al_stream", this);
|
||||
}
|
||||
|
||||
|
@ -988,7 +1006,12 @@ private:
|
|||
ALDataSource::Status status;
|
||||
|
||||
if (needsRewind)
|
||||
{
|
||||
if (startOffset > 0)
|
||||
source->seekToOffset(startOffset);
|
||||
else
|
||||
source->reset();
|
||||
}
|
||||
|
||||
for (int i = 0; i < streamBufs; ++i)
|
||||
{
|
||||
|
@ -1177,7 +1200,8 @@ struct AudioStream
|
|||
|
||||
void play(const std::string &filename,
|
||||
int volume,
|
||||
int pitch)
|
||||
int pitch,
|
||||
float offset = 0)
|
||||
{
|
||||
finiFadeInt();
|
||||
|
||||
|
@ -1236,7 +1260,7 @@ struct AudioStream
|
|||
current.pitch = _pitch;
|
||||
|
||||
if (!extPaused)
|
||||
stream.play();
|
||||
stream.play(offset);
|
||||
|
||||
unlockStream();
|
||||
}
|
||||
|
@ -1323,6 +1347,11 @@ struct AudioStream
|
|||
updateVolume();
|
||||
}
|
||||
|
||||
float playingOffset()
|
||||
{
|
||||
return stream.queryOffset();
|
||||
}
|
||||
|
||||
private:
|
||||
void finiFadeInt()
|
||||
{
|
||||
|
@ -1601,9 +1630,17 @@ Audio::Audio()
|
|||
|
||||
void Audio::bgmPlay(const char *filename,
|
||||
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);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Audio::bgmStop()
|
||||
|
@ -1619,9 +1656,17 @@ void Audio::bgmFade(int time)
|
|||
|
||||
void Audio::bgsPlay(const char *filename,
|
||||
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);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Audio::bgsStop()
|
||||
|
@ -1665,4 +1710,23 @@ void Audio::seStop()
|
|||
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; }
|
||||
|
|
40
src/audio.h
40
src/audio.h
|
@ -22,6 +22,16 @@
|
|||
#ifndef 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;
|
||||
|
||||
class Audio
|
||||
|
@ -30,21 +40,43 @@ public:
|
|||
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 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 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 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();
|
||||
|
||||
#ifdef RGSS3
|
||||
void setupMidi();
|
||||
float bgmPos();
|
||||
float bgsPos();
|
||||
#endif
|
||||
|
||||
private:
|
||||
AudioPrivate *p;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue