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
					
				
					 2 changed files with 123 additions and 27 deletions
				
			
		
							
								
								
									
										110
									
								
								src/audio.cpp
									
										
									
									
									
								
							
							
						
						
									
										110
									
								
								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;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				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));
 | 
			
		||||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
			source->reset();
 | 
			
		||||
		{
 | 
			
		||||
			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()
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -1600,10 +1629,18 @@ Audio::Audio()
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
void Audio::bgmPlay(const char *filename,
 | 
			
		||||
					int volume,
 | 
			
		||||
                    int pitch)
 | 
			
		||||
                    int volume,
 | 
			
		||||
                    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()
 | 
			
		||||
| 
						 | 
				
			
			@ -1618,10 +1655,18 @@ void Audio::bgmFade(int time)
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
void Audio::bgsPlay(const char *filename,
 | 
			
		||||
					int volume,
 | 
			
		||||
                    int pitch)
 | 
			
		||||
                    int volume,
 | 
			
		||||
                    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…
	
	Add table
		Add a link
		
	
		Reference in a new issue