Преглед изворни кода

Merge pull request #102 from mcclure/sound

Sound() should support procedurally generated data
Ivan Safrin пре 13 година
родитељ
комит
f681b674b2
2 измењених фајлова са 67 додато и 19 уклоњено
  1. 21 0
      Core/Contents/Include/PolySound.h
  2. 46 19
      Core/Contents/Source/PolySound.cpp

+ 21 - 0
Core/Contents/Include/PolySound.h

@@ -52,6 +52,7 @@ namespace Polycode {
 		* @param fileName Path to an OGG or WAV file to load.
 		*/ 
 		Sound(const String& fileName);
+		Sound(const char *data, int size, int channels = 1, ALsizei freq = 44100, int bps = 16);
 		~Sound();
 		
 		/**
@@ -89,8 +90,27 @@ namespace Polycode {
 		void setSoundVelocity(Vector3 velocity);
 		void setSoundDirection(Vector3 direction);
 		
+		/**
+		* Sets the current sample offset of this sound.
+		* @param off A number 0 <= off < sound sample length
+		*/
+		void setOffset(int off);
+		
+		/**
+		* Returns the current sample offset (playback progress) of this sound.
+		* @return The sample offset if it is known, -1 otherwise.
+		*/
+		int getOffset();
+		
+		/**
+		* Returns the number of samples in the sound.
+		* @return The sample length if it is known, -1 otherwise.
+		*/
+		int getSampleLength();
+		
 		void setPositionalProperties(Number referenceDistance, Number maxDistance);
 		
+		ALuint loadBytes(const char *data, int size, int channels = 1, ALsizei freq = 44100, int bps = 16);
 		ALuint loadWAV(const String& fileName);
 		ALuint loadOGG(const String& fileName);
 		
@@ -107,6 +127,7 @@ namespace Polycode {
 	
 		bool isPositional;
 		ALuint soundSource;
+		int sampleLength;
 		
 	};
 }

+ 46 - 19
Core/Contents/Source/PolySound.cpp

@@ -52,7 +52,7 @@ long custom_tellfunc(void *datasource) {
 	return OSBasics::tell(file);
 }
 
-Sound::Sound(const String& fileName) {
+Sound::Sound(const String& fileName) : sampleLength(-1) {
 	String extension;
 	size_t found;
 	found=fileName.rfind(".");
@@ -73,6 +73,13 @@ Sound::Sound(const String& fileName) {
 	setIsPositional(false);
 }
 
+Sound::Sound(const char *data, int size, int channels, int freq, int bps) : sampleLength(-1) {
+	ALuint buffer = loadBytes(data, size, freq, channels, bps);
+	
+	soundSource = GenSource(buffer);
+	setIsPositional(false);
+}
+
 Sound::~Sound() {
 	Logger::log("destroying sound...\n");
 	alDeleteSources(1,&soundSource);
@@ -142,6 +149,20 @@ void Sound::setSoundDirection(Vector3 direction) {
 		alSource3f(soundSource,AL_DIRECTION, direction.x, direction.y, direction.z);
 }
 
+void Sound::setOffset(int off) {
+	alSourcei(soundSource, AL_SAMPLE_OFFSET, off);
+}
+
+int Sound::getOffset() {
+	ALint off = -1;
+	alGetSourcei(soundSource, AL_SAMPLE_OFFSET, &off);
+	return off;
+}
+
+int Sound::getSampleLength() {
+	return sampleLength;
+}
+
 void Sound::setPositionalProperties(Number referenceDistance, Number maxDistance) { 
 	alSourcef(soundSource,AL_REFERENCE_DISTANCE, referenceDistance);
 	alSourcef(soundSource,AL_MAX_DISTANCE, maxDistance);	
@@ -222,8 +243,26 @@ ALuint Sound::GenSource(ALuint buffer) {
 	return source;
 }
 
-ALuint Sound::loadOGG(const String& fileName) {
+ALuint Sound::loadBytes(const char *data, int size, int freq, int channels, int bps) {
+	ALuint buffer = AL_NONE;
+	ALenum format;
+	if (channels == 1)
+		format = (bps == 8) ? AL_FORMAT_MONO8 : AL_FORMAT_MONO16;
+	else
+		format = (bps == 8) ? AL_FORMAT_STEREO8 : AL_FORMAT_STEREO16;
+	
+	sampleLength = bps > 8 ? size / (bps/8) : -1;
 	
+	alGenBuffers(1, &buffer);
+	soundCheck(alGetError() == AL_NO_ERROR, "LoadBytes: Could not generate buffer");
+	soundCheck(AL_NONE != buffer, "LoadBytes: Could not generate buffer");
+	
+	alBufferData(buffer, format, data, size, freq);
+	soundCheck(alGetError() == AL_NO_ERROR, "LoadBytes: Could not load buffer data");
+	return buffer;
+}
+
+ALuint Sound::loadOGG(const String& fileName) {
 	vector<char> buffer;
 	
 	ALuint bufferID = AL_NONE; 
@@ -271,7 +310,9 @@ ALuint Sound::loadOGG(const String& fileName) {
 		// Append to end of buffer
 		buffer.insert(buffer.end(), array, array + bytes);
 	} while (bytes > 0);
-	ov_clear(&oggFile);	
+	ov_clear(&oggFile);
+	
+	sampleLength = buffer.size() / sizeof(uint16_t);
 	
 	alBufferData(bufferID, format, &buffer[0], static_cast<ALsizei>(buffer.size()), freq);
 	
@@ -281,13 +322,11 @@ ALuint Sound::loadOGG(const String& fileName) {
 ALuint Sound::loadWAV(const String& fileName) {
 	long bytes;
 	vector <char> data;
-	ALenum format;
 	ALsizei freq;
 	
 	// Local resources
 	OSFILE *f = NULL;
 	char *array = NULL;
-	ALuint buffer = AL_NONE;
 	
 	alGetError();
 	
@@ -342,11 +381,6 @@ ALuint Sound::loadWAV(const String& fileName) {
 		soundCheck(OSBasics::read(buffer16,2,1,f) == 1, "LoadWav: Cannot read wav file "+ fileName );
 		unsigned short bps = readByte16(buffer16);
 		
-		if (channels == 1)
-			format = (bps == 8) ? AL_FORMAT_MONO8 : AL_FORMAT_MONO16;
-		else
-			format = (bps == 8) ? AL_FORMAT_STEREO8 : AL_FORMAT_STEREO16;
-		
 		// check 'data' sub chunk (2)
 		soundCheck(OSBasics::read(magic,4,1,f) == 1, "LoadWav: Cannot read wav file "+ fileName );
 		soundCheck(String(magic) == "data", "LoadWav: Wrong wav file format. This file is not a .wav file (no data subchunk): "+ fileName );
@@ -379,15 +413,8 @@ ALuint Sound::loadWAV(const String& fileName) {
 		
 		OSBasics::close(f);
 		f = NULL;
-		
-		alGenBuffers(1, &buffer);
-		soundCheck(alGetError() == AL_NO_ERROR, "LoadWav: Could not generate buffer");
-		soundCheck(AL_NONE != buffer, "LoadWav: Could not generate buffer");
-		
-		alBufferData(buffer, format, &data[0], data.size(), freq);
-		soundCheck(alGetError() == AL_NO_ERROR, "LoadWav: Could not load buffer data");
-		
-		return buffer;
+				
+		return loadBytes(&data[0], data.size(), freq, channels, bps);
 //		if (buffer)
 //			if (alIsBuffer(buffer) == AL_TRUE)
 //				alDeleteBuffers(1, &buffer);