Audio: Implement RGSS2 ogg looping
With this we now link to libvorbis/ogg directly. When this is enabled, one can theoretically also build SDL_sound without ogg support, although I doubt it makes much of a difference. Adittionally, count frames instead of samples for playback offset calculation.
This commit is contained in:
		
							parent
							
								
									226e860c38
								
							
						
					
					
						commit
						04526987e4
					
				
					 3 changed files with 302 additions and 31 deletions
				
			
		
							
								
								
									
										11
									
								
								mkxp.pro
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								mkxp.pro
									
										
									
									
									
								
							| 
						 | 
					@ -13,10 +13,19 @@ isEmpty(BINDING) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CONFIG += $$BINDING
 | 
					CONFIG += $$BINDING
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RGSS2 {
 | 
				
			||||||
 | 
						DEFINES += RGSS2
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
unix {
 | 
					unix {
 | 
				
			||||||
	CONFIG += link_pkgconfig
 | 
						CONFIG += link_pkgconfig
 | 
				
			||||||
	PKGCONFIG += QtCore sigc++-2.0 glew pixman-1 zlib \
 | 
						PKGCONFIG += QtCore sigc++-2.0 glew pixman-1 zlib \
 | 
				
			||||||
	             physfs sdl2 SDL2_image SDL2_ttf SDL_sound openal
 | 
						             physfs sdl2 SDL2_image SDL2_ttf SDL_sound \
 | 
				
			||||||
 | 
						             openal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						RGSS2 {
 | 
				
			||||||
 | 
							PKGCONFIG += vorbisfile
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# 'slots' keyword fucks with libsigc++
 | 
					# 'slots' keyword fucks with libsigc++
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -85,6 +85,11 @@ namespace Buffer
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		return getInteger(id, AL_BITS);
 | 
							return getInteger(id, AL_BITS);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						inline ALint getChannels(Buffer::ID id)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return getInteger(id, AL_CHANNELS);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Source
 | 
					namespace Source
 | 
				
			||||||
| 
						 | 
					@ -145,9 +150,12 @@ namespace Source
 | 
				
			||||||
		return getInteger(id, AL_SOURCE_STATE);
 | 
							return getInteger(id, AL_SOURCE_STATE);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inline ALint getSampleOffset(Source::ID id)
 | 
						inline ALfloat getSecOffset(Source::ID id)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		return getInteger(id, AL_SAMPLE_OFFSET);
 | 
							ALfloat value;
 | 
				
			||||||
 | 
							alGetSourcef(id.al, AL_SEC_OFFSET, &value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return value;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inline void setVolume(Source::ID id, float value)
 | 
						inline void setVolume(Source::ID id, float value)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										310
									
								
								src/audio.cpp
									
										
									
									
									
								
							
							
						
						
									
										310
									
								
								src/audio.cpp
									
										
									
									
									
								
							| 
						 | 
					@ -40,6 +40,10 @@
 | 
				
			||||||
#include <SDL_timer.h>
 | 
					#include <SDL_timer.h>
 | 
				
			||||||
#include <SDL_sound.h>
 | 
					#include <SDL_sound.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef RGSS2
 | 
				
			||||||
 | 
					#include <vorbis/vorbisfile.h>
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <alc.h>
 | 
					#include <alc.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <QDebug>
 | 
					#include <QDebug>
 | 
				
			||||||
| 
						 | 
					@ -316,36 +320,35 @@ struct ALDataSource
 | 
				
			||||||
	 * to provided AL buffer */
 | 
						 * to provided AL buffer */
 | 
				
			||||||
	virtual Status fillBuffer(AL::Buffer::ID alBuffer) = 0;
 | 
						virtual Status fillBuffer(AL::Buffer::ID alBuffer) = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	virtual float samplesToOffset(uint32_t samples) = 0;
 | 
						virtual int sampleRate() = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	virtual void seekToOffset(float offset) = 0;
 | 
						virtual void seekToOffset(float seconds) = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Seek back to start */
 | 
						/* Seek back to start */
 | 
				
			||||||
	virtual void reset() = 0;
 | 
						virtual void reset() = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* The frame count right after wrap around */
 | 
				
			||||||
 | 
						virtual uint32_t loopStartFrames() = 0;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct SDLSoundSource : ALDataSource
 | 
					struct SDLSoundSource : ALDataSource
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	Sound_Sample *sample;
 | 
						Sound_Sample *sample;
 | 
				
			||||||
	SDL_RWops ops;
 | 
						SDL_RWops &srcOps;
 | 
				
			||||||
	uint8_t sampleSize;
 | 
						uint8_t sampleSize;
 | 
				
			||||||
	bool looped;
 | 
						bool looped;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ALenum alFormat;
 | 
						ALenum alFormat;
 | 
				
			||||||
	ALsizei alFreq;
 | 
						ALsizei alFreq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	SDLSoundSource(const std::string &filename,
 | 
						SDLSoundSource(SDL_RWops &ops,
 | 
				
			||||||
 | 
						               const char *extension,
 | 
				
			||||||
	               uint32_t maxBufSize,
 | 
						               uint32_t maxBufSize,
 | 
				
			||||||
	               bool looped)
 | 
						               bool looped)
 | 
				
			||||||
	    : looped(looped)
 | 
						    : srcOps(ops),
 | 
				
			||||||
 | 
						      looped(looped)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		const char *extension;
 | 
							sample = Sound_NewSample(&srcOps, extension, 0, maxBufSize);
 | 
				
			||||||
		shState->fileSystem().openRead(ops,
 | 
					 | 
				
			||||||
		                               filename.c_str(),
 | 
					 | 
				
			||||||
		                               FileSystem::Audio,
 | 
					 | 
				
			||||||
		                               false, &extension);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		sample = Sound_NewSample(&ops, extension, 0, maxBufSize);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!sample)
 | 
							if (!sample)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
| 
						 | 
					@ -399,24 +402,256 @@ struct SDLSoundSource : ALDataSource
 | 
				
			||||||
		return ALDataSource::NoError;
 | 
							return ALDataSource::NoError;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	float samplesToOffset(uint32_t samples)
 | 
						int sampleRate()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		uint32_t frames = samples / sample->actual.channels;
 | 
							return sample->actual.rate;
 | 
				
			||||||
 | 
					 | 
				
			||||||
		return static_cast<float>(frames) / sample->actual.rate;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void seekToOffset(float offset)
 | 
						void seekToOffset(float seconds)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		Sound_Seek(sample, static_cast<uint32_t>(offset * 1000));
 | 
							Sound_Seek(sample, static_cast<uint32_t>(seconds * 1000));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void reset()
 | 
						void reset()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		Sound_Rewind(sample);
 | 
							Sound_Rewind(sample);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						uint32_t loopStartFrames()
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							/* Loops from the beginning of the file */
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef RGSS2
 | 
				
			||||||
 | 
					static size_t vfRead(void *ptr, size_t size, size_t nmemb, void *ops)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return SDL_RWread(static_cast<SDL_RWops*>(ops), ptr, size, nmemb);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int vfSeek(void *ops, ogg_int64_t offset, int whence)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return SDL_RWseek(static_cast<SDL_RWops*>(ops), offset, whence);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static long vfTell(void *ops)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return SDL_RWtell(static_cast<SDL_RWops*>(ops));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static ov_callbacks OvCallbacks =
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    vfRead,
 | 
				
			||||||
 | 
					    vfSeek,
 | 
				
			||||||
 | 
					    0,
 | 
				
			||||||
 | 
					    vfTell
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct VorbisSource : ALDataSource
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						SDL_RWops &src;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						OggVorbis_File vf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						uint32_t currentFrame;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							uint32_t start;
 | 
				
			||||||
 | 
							uint32_t length;
 | 
				
			||||||
 | 
							uint32_t end;
 | 
				
			||||||
 | 
							bool valid;
 | 
				
			||||||
 | 
							bool requested;
 | 
				
			||||||
 | 
						} loop;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							int channels;
 | 
				
			||||||
 | 
							int rate;
 | 
				
			||||||
 | 
							int frameSize;
 | 
				
			||||||
 | 
							ALenum alFormat;
 | 
				
			||||||
 | 
						} info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						std::vector<int16_t> sampleBuf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						VorbisSource(SDL_RWops &ops,
 | 
				
			||||||
 | 
						             bool looped)
 | 
				
			||||||
 | 
						    : src(ops),
 | 
				
			||||||
 | 
						      currentFrame(0)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							int error = ov_open_callbacks(&src, &vf, 0, 0, OvCallbacks);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (error)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								SDL_RWclose(&src);
 | 
				
			||||||
 | 
								throw Exception(Exception::MKXPError,
 | 
				
			||||||
 | 
								                "Vorbisfile: Cannot read ogg file");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Extract bitstream info */
 | 
				
			||||||
 | 
							info.channels = vf.vi->channels;
 | 
				
			||||||
 | 
							info.rate = vf.vi->rate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (info.channels > 2)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								ov_clear(&vf);
 | 
				
			||||||
 | 
								SDL_RWclose(&src);
 | 
				
			||||||
 | 
								throw Exception(Exception::MKXPError,
 | 
				
			||||||
 | 
								                "Cannot handle audio with more than 2 channels");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							info.alFormat = chooseALFormat(sizeof(int16_t), info.channels);
 | 
				
			||||||
 | 
							info.frameSize = sizeof(int16_t) * info.channels;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sampleBuf.resize(streamBufSize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							loop.requested = looped;
 | 
				
			||||||
 | 
							loop.valid = false;
 | 
				
			||||||
 | 
							loop.start = loop.length = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!loop.requested)
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Try to extract loop info */
 | 
				
			||||||
 | 
							for (int i = 0; i < vf.vc->comments; ++i)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								char *comment = vf.vc->user_comments[i];
 | 
				
			||||||
 | 
								char *sep = strstr(comment, "=");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* No '=' found */
 | 
				
			||||||
 | 
								if (!sep)
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* Empty value */
 | 
				
			||||||
 | 
								if (!*(sep+1))
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								*sep = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!strcmp(comment, "LOOPSTART"))
 | 
				
			||||||
 | 
									loop.start = strtol(sep+1, 0, 10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!strcmp(comment, "LOOPLENGTH"))
 | 
				
			||||||
 | 
									loop.length = strtol(sep+1, 0, 10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								*sep = '=';
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							loop.end = loop.start + loop.length;
 | 
				
			||||||
 | 
							loop.valid = (loop.start && loop.length);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						~VorbisSource()
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							ov_clear(&vf);
 | 
				
			||||||
 | 
							SDL_RWclose(&src);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int sampleRate()
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return info.rate;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void seekToOffset(float seconds)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							ov_time_seek(&vf, seconds);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Status fillBuffer(AL::Buffer::ID alBuffer)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							void *bufPtr = sampleBuf.data();
 | 
				
			||||||
 | 
							int availBuf = sampleBuf.size();
 | 
				
			||||||
 | 
							int bufUsed  = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							int canRead = availBuf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Status retStatus = ALDataSource::NoError;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (loop.valid)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								int tilLoopEnd = loop.end * info.frameSize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								canRead = std::min(availBuf, tilLoopEnd);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							while (canRead > 16)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								long res = ov_read(&vf, static_cast<char*>(bufPtr),
 | 
				
			||||||
 | 
								                   canRead, 0, sizeof(int16_t), 1, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (res < 0)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									/* Read error */
 | 
				
			||||||
 | 
									retStatus = ALDataSource::Error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (res == 0)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									/* EOF */
 | 
				
			||||||
 | 
									if (loop.requested)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										retStatus = ALDataSource::WrapAround;
 | 
				
			||||||
 | 
										reset();
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									else
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										retStatus = ALDataSource::EndOfStream;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								bufUsed += (res / sizeof(int16_t));
 | 
				
			||||||
 | 
								bufPtr = &sampleBuf[bufUsed];
 | 
				
			||||||
 | 
								currentFrame += (res / info.frameSize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (loop.valid && currentFrame >= loop.end)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									/* Determine how many frames we're
 | 
				
			||||||
 | 
									 * over the loop end */
 | 
				
			||||||
 | 
									int discardFrames = currentFrame - loop.end;
 | 
				
			||||||
 | 
									bufUsed -= discardFrames * info.channels;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									retStatus = ALDataSource::WrapAround;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									/* Seek to loop start */
 | 
				
			||||||
 | 
									currentFrame = loop.start;
 | 
				
			||||||
 | 
									if (ov_pcm_seek(&vf, currentFrame) != 0)
 | 
				
			||||||
 | 
										retStatus = ALDataSource::Error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								canRead -= res;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (retStatus != ALDataSource::Error)
 | 
				
			||||||
 | 
								AL::Buffer::uploadData(alBuffer, info.alFormat, sampleBuf.data(),
 | 
				
			||||||
 | 
								                       bufUsed*sizeof(int16_t), info.rate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return retStatus;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void reset()
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							ov_raw_seek(&vf, 0);
 | 
				
			||||||
 | 
							currentFrame = 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						uint32_t loopStartFrames()
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (loop.valid)
 | 
				
			||||||
 | 
								return loop.start;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* State-machine like audio playback stream.
 | 
					/* State-machine like audio playback stream.
 | 
				
			||||||
 * This class is NOT thread safe */
 | 
					 * This class is NOT thread safe */
 | 
				
			||||||
struct ALStream
 | 
					struct ALStream
 | 
				
			||||||
| 
						 | 
					@ -451,9 +686,11 @@ struct ALStream
 | 
				
			||||||
	AL::Source::ID alSrc;
 | 
						AL::Source::ID alSrc;
 | 
				
			||||||
	AL::Buffer::ID alBuf[streamBufs];
 | 
						AL::Buffer::ID alBuf[streamBufs];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uint64_t procSamples;
 | 
						uint64_t procFrames;
 | 
				
			||||||
	AL::Buffer::ID lastBuf;
 | 
						AL::Buffer::ID lastBuf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						SDL_RWops srcOps;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct
 | 
						struct
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		ALenum format;
 | 
							ALenum format;
 | 
				
			||||||
| 
						 | 
					@ -620,10 +857,9 @@ struct ALStream
 | 
				
			||||||
		if (state == Closed)
 | 
							if (state == Closed)
 | 
				
			||||||
			return 0;
 | 
								return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		uint32_t sampleSum =
 | 
							float procOffset = static_cast<float>(procFrames) / source->sampleRate();
 | 
				
			||||||
			procSamples + AL::Source::getSampleOffset(alSrc);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return source->samplesToOffset(sampleSum);
 | 
							return procOffset + AL::Source::getSecOffset(alSrc);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
| 
						 | 
					@ -634,7 +870,24 @@ private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void openSource(const std::string &filename)
 | 
						void openSource(const std::string &filename)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		source = new SDLSoundSource(filename, streamBufSize, looped);
 | 
							const char *ext;
 | 
				
			||||||
 | 
							shState->fileSystem().openRead(srcOps, filename.c_str(), FileSystem::Audio, false, &ext);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef RGSS2
 | 
				
			||||||
 | 
							/* Try to read ogg file signature */
 | 
				
			||||||
 | 
							char sig[5];
 | 
				
			||||||
 | 
							memset(sig, '\0', sizeof(sig));
 | 
				
			||||||
 | 
							SDL_RWread(&srcOps, sig, 1, 4);
 | 
				
			||||||
 | 
							SDL_RWseek(&srcOps, 0, RW_SEEK_SET);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!strcmp(sig, "OggS"))
 | 
				
			||||||
 | 
								source = new VorbisSource(srcOps, looped);
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								source = new SDLSoundSource(srcOps, ext, streamBufSize, looped);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
							source = new SDLSoundSource(srcOps, ext, streamBufSize, looped);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		needsRewind = false;
 | 
							needsRewind = false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -651,14 +904,14 @@ private:
 | 
				
			||||||
			needsRewind = true;
 | 
								needsRewind = true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		procSamples = 0;
 | 
							procFrames = 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void startStream()
 | 
						void startStream()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		clearALQueue();
 | 
							clearALQueue();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		procSamples = 0;
 | 
							procFrames = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		preemptPause = false;
 | 
							preemptPause = false;
 | 
				
			||||||
		streamInited = false;
 | 
							streamInited = false;
 | 
				
			||||||
| 
						 | 
					@ -783,17 +1036,18 @@ private:
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					/* Reset the processed sample count so
 | 
										/* Reset the processed sample count so
 | 
				
			||||||
					 * querying the playback offset returns 0.0 again */
 | 
										 * querying the playback offset returns 0.0 again */
 | 
				
			||||||
					procSamples = 0;
 | 
										procFrames = source->loopStartFrames();
 | 
				
			||||||
					lastBuf = AL::Buffer::ID(0);
 | 
										lastBuf = AL::Buffer::ID(0);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				else
 | 
									else
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					/* Add the sample count contained in this
 | 
										/* Add the frame count contained in this
 | 
				
			||||||
					 * buffer to the total count */
 | 
										 * buffer to the total count */
 | 
				
			||||||
					ALint bits = AL::Buffer::getBits(buf);
 | 
										ALint bits = AL::Buffer::getBits(buf);
 | 
				
			||||||
					ALint size = AL::Buffer::getSize(buf);
 | 
										ALint size = AL::Buffer::getSize(buf);
 | 
				
			||||||
 | 
										ALint chan = AL::Buffer::getChannels(buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					procSamples += (size / (bits / 8));
 | 
										procFrames += ((size / (bits / 8)) / chan);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if (sourceExhausted)
 | 
									if (sourceExhausted)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue