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
				
			
		
							
								
								
									
										102
									
								
								src/audio.cpp
									
										
									
									
									
								
							
							
						
						
									
										102
									
								
								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;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									/* 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;
 | 
										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)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if (startOffset > 0)
 | 
				
			||||||
 | 
									source->seekToOffset(startOffset);
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
				source->reset();
 | 
									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()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
| 
						 | 
					@ -1601,9 +1630,17 @@ 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()
 | 
				
			||||||
| 
						 | 
					@ -1619,9 +1656,17 @@ 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…
	
	Add table
		Add a link
		
	
		Reference in a new issue