浏览代码

Implemented a simple mixer to replace OpenAL, still no positional sound support, fixed ES2 shaders to work on desktop GL

Ivan Safrin 10 年之前
父节点
当前提交
f14692353e

二进制
assets/default/default.pak


+ 3 - 1
assets/default/default/Unlit.frag

@@ -1,4 +1,6 @@
-precision mediump float;
+#ifdef GLES2
+	precision mediump float;
+#endif
 
 uniform sampler2D diffuse;
 uniform vec4 entityColor;

+ 3 - 1
assets/default/default/Unlit.vert

@@ -1,4 +1,6 @@
-precision mediump float;
+#ifdef GLES2
+	precision mediump float;
+#endif
 
 attribute vec4 position;
 attribute vec2 texCoord;

+ 3 - 1
assets/default/default/UnlitUntextured.frag

@@ -1,4 +1,6 @@
-precision mediump float;
+#ifdef GLES2
+	precision mediump float;
+#endif
 
 uniform vec4 entityColor;
 

+ 3 - 1
assets/default/default/UnlitUntextured.vert

@@ -1,4 +1,6 @@
-precision mediump float;
+#ifdef GLES2
+	precision mediump float;
+#endif
 
 attribute vec4 position;
 

+ 20 - 0
build/osx/TemplateApp/TemplateApp.xcodeproj/project.pbxproj

@@ -7,6 +7,11 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
+		8A7348FE1B865C1F00F660C0 /* bedlayer_main.wav in Resources */ = {isa = PBXBuildFile; fileRef = 8A7348FD1B865C1F00F660C0 /* bedlayer_main.wav */; };
+		8A7349001B86640200F660C0 /* marimba-lo.wav in Resources */ = {isa = PBXBuildFile; fileRef = 8A7348FF1B86640200F660C0 /* marimba-lo.wav */; };
+		8A7349021B86642300F660C0 /* koto_level.wav in Resources */ = {isa = PBXBuildFile; fileRef = 8A7349011B86642300F660C0 /* koto_level.wav */; };
+		8A7349041B86643400F660C0 /* curve_02_c.wav in Resources */ = {isa = PBXBuildFile; fileRef = 8A7349031B86643400F660C0 /* curve_02_c.wav */; };
+		8A7349061B866A3C00F660C0 /* initial_touch_01.wav in Resources */ = {isa = PBXBuildFile; fileRef = 8A7349051B866A3C00F660C0 /* initial_touch_01.wav */; };
 		8A825F271B82A2680039E823 /* libportaudio.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8A825F261B82A2680039E823 /* libportaudio.a */; };
 		8A825F291B82A29B0039E823 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8A825F281B82A29B0039E823 /* CoreAudio.framework */; };
 		8A825F2E1B82A2C80039E823 /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8A825F2C1B82A2B10039E823 /* AudioUnit.framework */; };
@@ -32,6 +37,11 @@
 /* End PBXBuildFile section */
 
 /* Begin PBXFileReference section */
+		8A7348FD1B865C1F00F660C0 /* bedlayer_main.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; name = bedlayer_main.wav; path = ../../../../../MSFT/MicrosoftSurfaceHub/Resources/pd/samples/bedlayer_main.wav; sourceTree = "<group>"; };
+		8A7348FF1B86640200F660C0 /* marimba-lo.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; name = "marimba-lo.wav"; path = "../../../../../MSFT/MicrosoftSurfaceHub/Resources/pd/samples/marimba-lo.wav"; sourceTree = "<group>"; };
+		8A7349011B86642300F660C0 /* koto_level.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; name = koto_level.wav; path = ../../../../../MSFT/MicrosoftSurfaceHub/Resources/pd/samples/koto_level.wav; sourceTree = "<group>"; };
+		8A7349031B86643400F660C0 /* curve_02_c.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; name = curve_02_c.wav; path = ../../../../../MSFT/MicrosoftSurfaceHub/Resources/pd/samples/curve_02_c.wav; sourceTree = "<group>"; };
+		8A7349051B866A3C00F660C0 /* initial_touch_01.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; name = initial_touch_01.wav; path = ../../../../../MSFT/MicrosoftSurfaceHub/Resources/pd/samples/initial_touch_01.wav; sourceTree = "<group>"; };
 		8A825F261B82A2680039E823 /* libportaudio.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libportaudio.a; path = ../../../../lib/osx/libportaudio.a; sourceTree = "<group>"; };
 		8A825F281B82A29B0039E823 /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; };
 		8A825F2A1B82A2A50039E823 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
@@ -117,6 +127,11 @@
 				8A86536C1B729D77009F94DD /* PolycodeView.mm */,
 				8A86536F1B72C431009F94DD /* default.pak */,
 				8A86533A1B72931C009F94DD /* Images.xcassets */,
+				8A7348FF1B86640200F660C0 /* marimba-lo.wav */,
+				8A7349011B86642300F660C0 /* koto_level.wav */,
+				8A7348FD1B865C1F00F660C0 /* bedlayer_main.wav */,
+				8A7349051B866A3C00F660C0 /* initial_touch_01.wav */,
+				8A7349031B86643400F660C0 /* curve_02_c.wav */,
 				8A8653951B752DBE009F94DD /* main_icon.png */,
 				8A86533C1B72931C009F94DD /* MainMenu.xib */,
 				8A8653331B72931C009F94DD /* Supporting Files */,
@@ -201,7 +216,12 @@
 			buildActionMask = 2147483647;
 			files = (
 				8A86533B1B72931C009F94DD /* Images.xcassets in Resources */,
+				8A7349001B86640200F660C0 /* marimba-lo.wav in Resources */,
+				8A7349041B86643400F660C0 /* curve_02_c.wav in Resources */,
+				8A7348FE1B865C1F00F660C0 /* bedlayer_main.wav in Resources */,
 				8A8653961B752DBE009F94DD /* main_icon.png in Resources */,
+				8A7349061B866A3C00F660C0 /* initial_touch_01.wav in Resources */,
+				8A7349021B86642300F660C0 /* koto_level.wav in Resources */,
 				8A86533E1B72931C009F94DD /* MainMenu.xib in Resources */,
 				8A8653701B72C431009F94DD /* default.pak in Resources */,
 			);

+ 10 - 1
build/osx/TemplateApp/TemplateApp/PolycodeTemplateApp.h

@@ -7,13 +7,22 @@
 
 using namespace Polycode;
 
-class PolycodeTemplateApp {
+class PolycodeTemplateApp : public EventHandler {
 public:
     PolycodeTemplateApp(PolycodeView *view);
     ~PolycodeTemplateApp();
     
+    void handleEvent(Event *event);
+    
     bool Update();
     
 private:
+    
+    Sound *bgSound;
+    
+    Sound *sound1;
+    Sound *sound2;
+    Sound *sound3;
+    
     Core *core;
 };

+ 32 - 0
build/osx/TemplateApp/TemplateApp/PolycodeTemplateApp.mm

@@ -22,6 +22,38 @@ PolycodeTemplateApp::PolycodeTemplateApp(PolycodeView *view) {
     test->getLocalShaderOptions()->loadTextureForParam("diffuse", "main_icon.png");
     scene->addChild(test);
     
+    SceneLabel *testLabel = new SceneLabel("Test!", 32, "sans", Label::ANTIALIAS_FULL, 0.2);
+    scene->addChild(testLabel);
+    
+    bgSound = new Sound("bedlayer_main.wav");
+    bgSound->Play();
+    
+    
+    sound1 = new Sound("marimba-lo.wav");
+    
+    sound2 = new Sound("initial_touch_01.wav");
+    sound3 = new Sound("curve_02_c.wav");
+    
+    //sound2->Play(true);
+    
+    Services()->getInput()->addEventListener(this, InputEvent::EVENT_KEYDOWN);
+}
+
+void PolycodeTemplateApp::handleEvent(Event *event) {
+    InputEvent *inputEvent = (InputEvent*) event;
+    
+    switch(inputEvent->getKey()) {
+        case KEY_z:
+            sound1->Play();
+        break;
+        case KEY_x:
+            sound2->Play();
+        break;
+        case KEY_c:
+            sound3->Play();
+        break;
+            
+    }
 }
 
 PolycodeTemplateApp::~PolycodeTemplateApp() {

+ 34 - 28
include/polycode/core/PolySound.h

@@ -27,27 +27,25 @@
 #include "polycode/core/PolyCoreServices.h"
 
 #define BUFFER_SIZE 32768
-#define STREAMING_BUFFER_COUNT 4
-#define STREAMING_BUFFER_SIZE 4096
+#define STREAMING_BUFFER_SIZE
 
 namespace Polycode {
-	
+
+    enum SoundFormat {SoundFormatUnsupported, SoundFormat8, SoundFormat16, SoundFormat32};
+    
 	class String;
     
     class  AudioStreamingSource {
         public:
-            AudioStreamingSource(unsigned int channels, unsigned int bps, unsigned int freq);
-        
-            POLYIGNORE virtual unsigned int streamData(char *buffer, unsigned int size);
+            AudioStreamingSource(unsigned int channels, unsigned int freq);        
+            POLYIGNORE virtual unsigned int streamData(int16_t *buffer, unsigned int size);
         
             unsigned int getNumChannels();
-            unsigned int getBitsPerSample();
             unsigned int getFrequency();
         
         protected:
         
             unsigned int channels;
-            unsigned int bps;
             unsigned int freq;
         
     };
@@ -62,21 +60,21 @@ namespace Polycode {
 		* Constructor.
 		* @param fileName Path to an OGG or WAV file to load.
 		*/ 
-		Sound(const String& fileName, bool generateFloatBuffer = false);
-		Sound(int size, const char *data, int channels = 1, unsigned int freq = 44100, int bps = 16, bool generateFloatBuffer = false);
+		Sound(const String& fileName);
+		Sound(int size, const char *data, int channels, unsigned int freq, SoundFormat format);
         Sound(AudioStreamingSource *streamingSource);
         
+        Number getSampleAsNumber(unsigned int offset, unsigned int channel);
+        
 		virtual ~Sound();
 		
-		void loadFile(String fileName, bool generateFloatBuffer);
-		
-		void reloadProperties();
+		void loadFile(String fileName);
 		
 		/**
 		* Play the sound once or in a loop.
 		* @param once If this is true, play it once, otherwise, loop.
 		*/
-		void Play(bool loop=false);
+		void Play(bool loop=false, bool restartSound=true);
 		
 		/**
 		* Stop the sound playback.
@@ -104,7 +102,9 @@ namespace Polycode {
 		* @return True if sound is playing, false if otherwise.
 		*/
 		bool isPlaying();
-				
+		
+        bool isLooped();
+        
 		void setIsPositional(bool isPositional);
 		
 		void setSoundPosition(Vector3 position);
@@ -115,7 +115,7 @@ namespace Polycode {
 		* Sets the current sample offset of this sound.
 		* @param off A number 0 <= off < sound sample length
 		*/
-		void setOffset(int off);
+		void setOffset(unsigned int offset);
 		
 		String getFileName();
 		
@@ -129,13 +129,15 @@ namespace Polycode {
 		* @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();
 		
+        unsigned int getFrequency();
+        
 		void setPositionalProperties(Number referenceDistance, Number maxDistance);
 		
 		void setReferenceDistance(Number referenceDistance);
@@ -144,10 +146,11 @@ namespace Polycode {
 		Number getReferenceDistance();
 		Number getMaxDistance();
         
+
+		bool loadBytes(const char *data, int size, int channels, unsigned int freq, SoundFormat format);
+		bool loadWAV(const String& fileName);
+		bool loadOGG(const String& fileName);
 		/*
-		ALuint loadBytes(const char *data, int size, int channels = 1, ALsizei freq = 44100, int bps = 16, bool generateFloatBuffer = false);
-		ALuint loadWAV(const String& fileName, bool generateFloatBuffer);
-		ALuint loadOGG(const String& fileName, bool generateFloatBuffer);
 		ALuint GenSource(ALuint buffer);
 		ALuint GenSource();
         */
@@ -158,13 +161,9 @@ namespace Polycode {
 		static unsigned long readByte32(const unsigned char buffer[4]);		
 		static unsigned short readByte16(const unsigned char buffer[2]);
 		
-        void updateStream();
-        
-		POLYIGNORE std::vector<float> *getFloatBuffer();
+        void updateStream(unsigned int streamCount);
 
 	protected:
-        
-        bool updateALBuffer(unsigned int buffer);
 	
 		Number referenceDistance;
 		Number maxDistance;
@@ -179,9 +178,16 @@ namespace Polycode {
 		
 		bool soundLoaded;
 	
+        bool playing;
+        bool looped;
+        
 		bool isPositional;
-		int sampleLength;
-		
-		std::vector<float> floatBuffer;
+		unsigned int numSamples;
+        unsigned int numChannels;
+        unsigned int playbackOffset;
+        unsigned int frequency;
+    
+        int16_t *soundBuffer;
+
 	};
 }

+ 12 - 7
include/polycode/core/PolySoundManager.h

@@ -25,23 +25,25 @@
 #include "polycode/core/PolyVector3.h"
 #include "polycode/core/PolySound.h"
 
-#define POLY_FRAMES_PER_BUFFER 256
+#define POLY_FRAMES_PER_BUFFER 512
 #define POLY_AUDIO_FREQ 44100
-#define POLY_CIRCULAR_BUFFER_SIZE 128
+#define POLY_CIRCULAR_BUFFER_SIZE 32
 #define POLY_NUM_CHANNELS 2
+#define POLY_MIX_BUFFER_SIZE (POLY_FRAMES_PER_BUFFER*POLY_CIRCULAR_BUFFER_SIZE)
 
 namespace Polycode {
 	
     class _PolyExport AudioInterface {
         public:
             AudioInterface();
-            void addToBuffer(float *data, unsigned int count);
+            void addToBuffer(int16_t *data, unsigned int count);
         
-            float bufferData[POLY_NUM_CHANNELS][POLY_FRAMES_PER_BUFFER*POLY_CIRCULAR_BUFFER_SIZE];
+            int16_t bufferData[POLY_NUM_CHANNELS][POLY_FRAMES_PER_BUFFER*POLY_CIRCULAR_BUFFER_SIZE];
             unsigned int readOffset;
             unsigned int writeOffset;
     };
     
+    
 	/**
 	* Controls global sound settings.
 	*/
@@ -65,17 +67,20 @@ namespace Polycode {
 		*/ 
 		void setGlobalVolume(Number globalVolume);
         
-        void registerStreamingSound(Sound *sound);
-        void unregisterStreamingSound(Sound *sound);
+        void registerSound(Sound *sound);
+        void unregisterSound(Sound *sound);
 		
 	protected:
 		
         AudioInterface *audioInterface;
         
+        int16_t mixBuffer[POLY_MIX_BUFFER_SIZE*POLY_NUM_CHANNELS];
+        
         Number globalVolume;
         Number testVal;
+        Number leftOver;
         
-        std::vector<Sound*> streamingSounds;
+        std::vector<Sound*> sounds;
         int recordingBufferSize;
         int recordingBufferRate;
 	};

二进制
lib/osx/libPolycore.a


+ 2 - 2
src/core/PolyPAAudioInterface.cpp

@@ -38,7 +38,7 @@ PAAudioInterface::PAAudioInterface() {
     error = Pa_OpenDefaultStream( &stream,
                                0,
                                POLY_NUM_CHANNELS,
-                               paFloat32,
+                               paInt16,
                                POLY_AUDIO_FREQ,
                                POLY_FRAMES_PER_BUFFER,
                                PAAudioInterface::paCallback,
@@ -78,7 +78,7 @@ int PAAudioInterface::paCallback(const void *inputBuffer, void *outputBuffer,
                                  void *userData) {
     PAAudioInterface *audioInterface = (PAAudioInterface*) userData;
     if(outputBuffer) {
-        float *out = (float*)outputBuffer;
+        int16_t *out = (int16_t*)outputBuffer;
         for(int i=0; i < framesPerBuffer; i++) {
             for(int b=0; b < POLY_NUM_CHANNELS; b++) {
                 *out++ = audioInterface->bufferData[b][audioInterface->readOffset];

+ 215 - 299
src/core/PolySound.cpp

@@ -45,22 +45,18 @@
 using namespace std;
 using namespace Polycode;
 
-AudioStreamingSource::AudioStreamingSource(unsigned int channels, unsigned int bps, unsigned int freq) : channels(channels), freq(freq), bps(bps) {
+AudioStreamingSource::AudioStreamingSource(unsigned int channels, unsigned int freq) : channels(channels), freq(freq) {
 }
 
 unsigned int AudioStreamingSource::getNumChannels() {
     return channels;
 }
 
-unsigned int AudioStreamingSource::getBitsPerSample() {
-    return bps;
-}
-
 unsigned int AudioStreamingSource::getFrequency() {
     return freq;
 }
 
-unsigned int AudioStreamingSource::streamData(char *buffer, unsigned int size) {
+unsigned int AudioStreamingSource::streamData(int16_t *buffer, unsigned int size) {
     return 0;
 }
 
@@ -86,102 +82,42 @@ long custom_tellfunc(void *datasource) {
 	return file->tell();
 }
 
-Sound::Sound(const String& fileName, bool generateFloatBuffer) :  referenceDistance(1), maxDistance(MAX_FLOAT), pitch(1), volume(1), sampleLength(-1), streamingSound(false) {
+Sound::Sound(const String& fileName) :  referenceDistance(1), maxDistance(MAX_FLOAT), pitch(1), volume(1), numSamples(-1), streamingSound(false), playing(false), playbackOffset(0), streamingSource(NULL) {
 	soundLoaded = false;
-	loadFile(fileName, generateFloatBuffer);
 	setIsPositional(false);
+	loadFile(fileName);
+    if(soundLoaded) {
+        Services()->getSoundManager()->registerSound(this);
+    }
 }
 
-Sound::Sound(int size, const char *data, int channels, unsigned int freq, int bps, bool generateFloatBuffer) : referenceDistance(1), maxDistance(MAX_FLOAT), pitch(1), volume(1), sampleLength(-1), streamingSound(false) {
-    
-	//buffer = loadBytes(data, size, freq, channels, bps, generateFloatBuffer);
-	//soundSource = GenSource(buffer);
-	
+Sound::Sound(int size, const char *data, int channels, unsigned int freq, SoundFormat format) : referenceDistance(1), maxDistance(MAX_FLOAT), pitch(1), volume(1), numSamples(-1), streamingSound(false), playing(false) , playbackOffset(0), streamingSource(NULL) {
 	setIsPositional(false);
-	reloadProperties();
-	
-	soundLoaded = true;
-}
-
-Sound::Sound(AudioStreamingSource *streamingSource) : referenceDistance(1), maxDistance(MAX_FLOAT), pitch(1), volume(1),  sampleLength(-1), streamingSound(true), streamingSource(streamingSource) {
-    
-    /*
-    alGenSources(1, &soundSource);
-    
-    alSourcef(soundSource, AL_PITCH, 1.0);
-    alSourcef(soundSource, AL_GAIN, 1.0);
-    
-    ALfloat sourcePos[] = {0.0, 0.0, 0.0};
-    ALfloat sourceVel[] = {0.0, 0.0, 0.0};
-    
-    alSourcefv(soundSource, AL_POSITION, sourcePos);
-    alSourcefv(soundSource, AL_VELOCITY, sourceVel);
-    
-    
-    alGenBuffers(STREAMING_BUFFER_COUNT, streamingBuffers);
-    
-    for(int i=0; i < STREAMING_BUFFER_COUNT; i++) {
-        if(updateALBuffer(streamingBuffers[i])) {
-            alSourceQueueBuffers(soundSource, 1, &streamingBuffers[i]);
-        }
+    soundLoaded = loadBytes(data, size, channels, freq, format);
+    if(soundLoaded) {
+        Services()->getSoundManager()->registerSound(this);
     }
-    Services()->getSoundManager()->registerStreamingSound(this);
-    
-	alSourcePlay(soundSource);
-     */
-        // NOAL_TODO
-    
 }
 
-void Sound::updateStream() {
-    /*
-    ALint processed = 0;
-    alGetSourcei(soundSource, AL_BUFFERS_PROCESSED, &processed);
-    
-    while(processed--) {
-        ALuint buffer;
-        alSourceUnqueueBuffers(soundSource, 1, &buffer);
-        if(updateALBuffer(buffer)) {
-            alSourceQueueBuffers(soundSource, 1, &buffer);
-        }
-    }
+Sound::Sound(AudioStreamingSource *streamingSource) : referenceDistance(1), maxDistance(MAX_FLOAT), pitch(1), volume(1),  numSamples(-1), streamingSound(true), streamingSource(streamingSource), playing(false), playbackOffset(0) {
 
-    ALenum state;
-    alGetSourcei(soundSource, AL_SOURCE_STATE, &state);
-    if(state != AL_PLAYING) {
-        alSourcePlay(soundSource);
-    }
-     */
-    //NOAL_TODO
+    soundBuffer = (int16_t*) malloc(sizeof(int16_t) * streamingSource->getNumChannels() * POLY_MIX_BUFFER_SIZE);
+    Services()->getSoundManager()->registerSound(this);
+    numChannels = streamingSource->getNumChannels();
 }
 
-bool Sound::updateALBuffer(unsigned int buffer) {
-    /*
-    char data[STREAMING_BUFFER_SIZE];
-    unsigned int bytesStreamed = streamingSource->streamData(data, STREAMING_BUFFER_SIZE);
-    
-    if(bytesStreamed == 0) {
-        return false;
-    }
-    
-    ALenum format;
-    if (streamingSource->getNumChannels() == 1) {
-        format = (streamingSource->getBitsPerSample() == 8) ? AL_FORMAT_MONO8 : AL_FORMAT_MONO16;
-    } else {
-        format = (streamingSource->getBitsPerSample() == 8) ? AL_FORMAT_STEREO8 : AL_FORMAT_STEREO16;
+void Sound::updateStream(unsigned int streamCount) {
+    if(streamingSource) {
+        playbackOffset = 0;
+        numSamples = streamCount;
+        streamingSource->streamData(soundBuffer, streamCount);
     }
-    
-    alBufferData(buffer, format, data, bytesStreamed, streamingSource->getFrequency());
-    */
-            // NOAL_TODO
-    return true;
 }
 
+void Sound::loadFile(String fileName) {
 
-void Sound::loadFile(String fileName, bool generateFloatBuffer) {
-/*
 	if(soundLoaded) {
-		alDeleteSources(1,&soundSource);	
+        free(soundBuffer);
 	}
 
 	String actualFilename = fileName;
@@ -202,30 +138,12 @@ void Sound::loadFile(String fileName, bool generateFloatBuffer) {
 	}
 	
 	if(extension == "wav" || extension == "WAV") {
-		buffer = loadWAV(actualFilename, generateFloatBuffer);			
+		soundLoaded = loadWAV(actualFilename);
 	} else if(extension == "ogg" || extension == "OGG") {
-		buffer = loadOGG(actualFilename, generateFloatBuffer);
+		soundLoaded = loadOGG(actualFilename);
 	}
 	
 	this->fileName = actualFilename;
-	
-	soundSource = GenSource(buffer);	
-	
-	reloadProperties();
-	
-	soundLoaded = true;
-	
-	checkALError("Sound load: complete");
- */
-    //NOAL_TODO
-}
-
-void Sound::reloadProperties() { // Re-set stored properties into sound source.
-	setVolume(volume);
-	setPitch(pitch);
-	
-	setReferenceDistance(referenceDistance);
-	setMaxDistance(maxDistance);
 }
 
 String Sound::getFileName() {
@@ -241,19 +159,8 @@ Number Sound::getPitch() {
 }
 
 Sound::~Sound() {
-/*
-	alSourcei(soundSource, AL_BUFFER, 0);
-    
-	alDeleteSources(1,&soundSource);
-	checkALError("Destroying sound");
-	alDeleteBuffers(1, &buffer);
-	checkALError("Deleting buffer");
-    if(streamingSound) {
-        alDeleteBuffers(STREAMING_BUFFER_COUNT, streamingBuffers);
-        Services()->getSoundManager()->unregisterStreamingSound(this);
-    }
- */
-        //NOAL_TODO
+    free(soundBuffer);
+    Services()->getSoundManager()->unregisterSound(this);
 }
 
 void Sound::soundCheck(bool result, const String& err) {
@@ -281,48 +188,29 @@ unsigned short Sound::readByte16(const unsigned char data[2]) {
 #endif	
 }
 
-void Sound::Play(bool loop) {
-    
-    /*
-	if(!loop) {
-		alSourcei(soundSource, AL_LOOPING, AL_FALSE);
-	} else {
-		alSourcei(soundSource, AL_LOOPING, AL_TRUE);		
-	}
-	checkALError("Play: loop");
-	alSourcePlay(soundSource);
-	checkALError("Play: play");
-     */
-        //NOAL_TODO
+void Sound::Play(bool loop, bool restartSound) {
+    if(restartSound) {
+        playbackOffset = 0;
+    }
+    playing = true;
+    looped = loop;
 }
 
 bool Sound::isPlaying() {
-    /*
-	ALenum state;
-	alGetSourcei(soundSource, AL_SOURCE_STATE, &state);
-	return (state == AL_PLAYING);
-     */
-        //NOAL_TODO
-    return false;
+    return playing;
+}
+
+bool Sound::isLooped() {
+    return looped;
 }
 
 
 void Sound::setVolume(Number newVolume) {
 	this->volume = newVolume;
-    /*
-	alSourcef(soundSource, AL_GAIN, newVolume);
-	checkALError("Set volume");
-     */
-        //NOAL_TODO
 }
 
 void Sound::setPitch(Number newPitch) {
 	this->pitch = newPitch;
-    /*
-	alSourcef(soundSource, AL_PITCH, newPitch);
-	checkALError("Set pitch");
-     */
-        //NOAL_TODO
 }
 
 void Sound::setSoundPosition(Vector3 position) {
@@ -352,13 +240,6 @@ void Sound::setSoundDirection(Vector3 direction) {
         //NOAL_TODO
 }
 
-void Sound::setOffset(int off) {
-    /*
-	alSourcei(soundSource, AL_SAMPLE_OFFSET, off);
-     */
-        //NOAL_TODO
-}
-
 
 Number Sound::getPlaybackTime() {
     /*
@@ -395,13 +276,17 @@ Number Sound::getPlaybackDuration() {
 }
 		
 int Sound::getOffset() {
-    /*
-	ALint off = -1;
-	alGetSourcei(soundSource, AL_SAMPLE_OFFSET, &off);
-	return off;
-     */
-            //NOAL_TODO
-    return 0;
+    return playbackOffset;
+}
+
+void Sound::setOffset(unsigned int offset) {
+    playbackOffset = (offset % numSamples);
+    if(offset >= numSamples) {
+        offset = 0;
+        if(!looped && !streamingSource) {
+            playing = false;
+        }
+    }
 }
 
 void Sound::seekTo(Number time) {
@@ -415,7 +300,7 @@ void Sound::seekTo(Number time) {
 }
 
 int Sound::getSampleLength() {
-	return sampleLength;
+	return numSamples;
 }
 
 void Sound::setPositionalProperties(Number referenceDistance, Number maxDistance) { 
@@ -462,48 +347,77 @@ void Sound::setIsPositional(bool isPositional) {
 }
 
 void Sound::Stop() {
-        //NOAL_TODO
+    playing = false;
 }
 
 
-
-std::vector<float> *Sound::getFloatBuffer() {
-    return &floatBuffer;
+Number Sound::getSampleAsNumber(unsigned int offset, unsigned int channel) {
+    Number ret = (((Number)(soundBuffer[((offset%numSamples)*numChannels)+(channel % numChannels)])/((Number)INT16_MAX))) * volume;
+    return ret;
 }
 
 
-/*
-ALuint Sound::loadBytes(const char *data, int size, int freq, int channels, int bps, bool generateFloatBuffer) {
-    /*
-	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;
-
-	checkALError("LoadBytes: pre-generate buffer");
-	
-	alGenBuffers(1, &buffer);
-	checkALError("LoadBytes: generate buffer");
-	soundCheck(AL_NONE != buffer, "LoadBytes: Did not generate buffer");
-	
-	alBufferData(buffer, format, data, size, freq);
-	checkALError("LoadBytes: load buffer data");
+bool Sound::loadBytes(const char *data, int size, int channels, unsigned int freq, SoundFormat format) {
     
-	if(generateFloatBuffer) {
-		int32_t *ptr32 = (int32_t*) &data[0];
-		for(int i=0; i < size/4; i++ ) {
-			floatBuffer.push_back(((Number)ptr32[i])/((Number)INT32_MAX));
-		}
-	}
+    if(format == SoundFormatUnsupported) {
+        Logger::log("[%s] Error: sound format unsupported!\n", fileName.c_str());
+        return false;
+    }
+    
+    soundBuffer = (int16_t*) malloc(sizeof(int16_t) * channels * size);
+    
+    int16_t *soundBufferPtr = soundBuffer;
+    
+    unsigned int dataOffset = 0;
+    
+    switch(format) {
+        case SoundFormat8:
+            numSamples = size / channels;
+            break;
+        case SoundFormat16:
+            numSamples = size / channels / 2;
+            break;
+        case SoundFormat32:
+            numSamples = size / channels / 4;
+            break;
+        default:
+        break;
+    }
+    
+    
+    for(int i=0; i < numSamples; i++){
+        for(int c=0; c < channels; c++) {
+            switch(format) {
+                case SoundFormat8:
+                    *soundBufferPtr = ((int8_t*)data)[dataOffset];
+                break;
+                case SoundFormat16:
+                    *soundBufferPtr = ((int16_t*)data)[dataOffset];
+                break;
+                case SoundFormat32:
+                    *soundBufferPtr = ((int32_t*)data)[dataOffset];
+                break;
+                default:
+                break;
+            }
+            soundBufferPtr++;
+            dataOffset++;
+        }
+    }
+    
+    numChannels = channels;
+    frequency = freq;
 
-	return buffer;
+    return true;
 }
 
+unsigned int Sound::getFrequency() {
+    return frequency;
+}
 
-ALuint Sound::loadOGG(const String& fileName, bool generateFloatBuffer) {
+
+bool Sound::loadOGG(const String& fileName) {
+    /*
 //	floatBuffer.clear();
 	vector<char> data;
 	
@@ -563,120 +477,122 @@ ALuint Sound::loadOGG(const String& fileName, bool generateFloatBuffer) {
 			floatBuffer.push_back(((Number)ptr32[i])/((Number)INT32_MAX));
 		}	
 	}
-	return buffer;
+     */
+	return false;
+
 }
 
-ALuint Sound::loadWAV(const String& fileName, bool generateFloatBuffer) {
+bool Sound::loadWAV(const String& fileName) {
+    
 	long bytes;
 	vector <char> data;
-	ALsizei freq;
 	
 	// Local resources
 	CoreFile *f = NULL;
 	char *array = NULL;
 	
-	checkALError("loadWAV: pre-generate buffer");
-	
-		// Open for binary reading
-		f = Services()->getCore()->openFile(fileName.c_str(), "rb");
-		if (!f) {
-			soundError("LoadWav: Could not load wav from " + fileName);
-			return buffer;
-		}
-		
-		// buffers
-		char magic[5];
-		magic[4] = '\0';
-		unsigned char data32[4];
-		unsigned char data16[2];
-		
-		// check magic
-		soundCheck(f->read(magic,4,1) == 1, "LoadWav: Cannot read wav file "+ fileName );
-		soundCheck(String(magic) == "RIFF", "LoadWav: Wrong wav file format. This file is not a .wav file (no RIFF magic): "+ fileName );
-		
-		// skip 4 bytes (file size)
-		f->seek(4,SEEK_CUR);
-		
-		// check file format
-		soundCheck(f->read(magic,4,1) == 1, "LoadWav: Cannot read wav file "+ fileName );
-		soundCheck(String(magic) == "WAVE", "LoadWav: Wrong wav file format. This file is not a .wav file (no WAVE format): "+ fileName );
-		
-		// check 'fmt ' sub chunk (1)
-		soundCheck(f->read(magic,4,1) == 1, "LoadWav: Cannot read wav file "+ fileName );
-		soundCheck(String(magic) == "fmt ", "LoadWav: Wrong wav file format. This file is not a .wav file (no 'fmt ' subchunk): "+ fileName );
-		
-		// read (1)'s size
-		soundCheck(f->read(data32,4,1)   == 1, "LoadWav: Cannot read wav file "+ fileName );
-		unsigned long subChunk1Size = readByte32(data32);
-		soundCheck(subChunk1Size >= 16, "Wrong wav file format. This file is not a .wav file ('fmt ' chunk too small, truncated file?): "+ fileName );
-		
-		// check PCM audio format
-		soundCheck(f->read(data16,2,1) == 1, "LoadWav: Cannot read wav file "+ fileName );
-		unsigned short audioFormat = readByte16(data16);
-		soundCheck(audioFormat == 1, "LoadWav: Wrong wav file format. This file is not a .wav file (audio format is not PCM): "+ fileName );
-		
-		// read number of channels
-		soundCheck(f->read(data16,2,1) == 1, "LoadWav: Cannot read wav file "+ fileName );
-		unsigned short channels = readByte16(data16);
-		
-		// read frequency (sample rate)
-		soundCheck(f->read(data32,4,1) == 1, "LoadWav: Cannot read wav file "+ fileName );
-		unsigned long frequency = readByte32(data32);
-		
-		// skip 6 bytes (Byte rate (4), Block align (2))
-		f->seek(6,SEEK_CUR);
-		
-		// read bits per sample
-		soundCheck(f->read(data16,2,1) == 1, "LoadWav: Cannot read wav file "+ fileName );
-		unsigned short bps = readByte16(data16);
-		
-		// check 'data' sub chunk (2)
-		soundCheck(f->read(magic,4,1) == 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 );
-		
-		soundCheck(f->read(data32,4,1) == 1, "LoadWav: Cannot read wav file "+ fileName );
-		unsigned long subChunk2Size = readByte32(data32);
-		
-		// The frequency of the sampling rate
-		freq = frequency;
-		soundCheck(sizeof(freq) == sizeof(frequency), "LoadWav: freq and frequency different sizes");
-		
-		array = new char[BUFFER_SIZE];
-		
-		while (data.size() != subChunk2Size) {
-			// Read up to a buffer's worth of decoded sound data
-			bytes = f->read(array, 1, BUFFER_SIZE);
-			
-			if (bytes <= 0)
-				break;
-			
-			if (data.size() + bytes > subChunk2Size)
-				bytes = subChunk2Size - data.size();
-			
-			// Append to end of buffer
-			data.insert(data.end(), array, array + bytes);
-		};
-		
-		delete []array;
-		array = NULL;
-		
-		Services()->getCore()->closeFile(f);
-		f = NULL;
-				
-		return loadBytes(&data[0], data.size(), freq, channels, bps, generateFloatBuffer);
-//		if (buffer)
-//			if (alIsBuffer(buffer) == AL_TRUE)
-//				alDeleteBuffers(1, &buffer);
-//		
-//		if (array)
-//			delete []array;
-//		
-//		if (f)
-//			OSBasics::close(f);
-//		
-//		throw (e);
+    // Open for binary reading
+    f = Services()->getCore()->openFile(fileName.c_str(), "rb");
+    if (!f) {
+        soundError("LoadWav: Could not load wav from " + fileName);
+        return false;
+    }
+    
+    // buffers
+    char magic[5];
+    magic[4] = '\0';
+    unsigned char data32[4];
+    unsigned char data16[2];
+    
+    // check magic
+    soundCheck(f->read(magic,4,1) == 1, "LoadWav: Cannot read wav file "+ fileName );
+    soundCheck(String(magic) == "RIFF", "LoadWav: Wrong wav file format. This file is not a .wav file (no RIFF magic): "+ fileName );
+    
+    // skip 4 bytes (file size)
+    f->seek(4,SEEK_CUR);
+    
+    // check file format
+    soundCheck(f->read(magic,4,1) == 1, "LoadWav: Cannot read wav file "+ fileName );
+    soundCheck(String(magic) == "WAVE", "LoadWav: Wrong wav file format. This file is not a .wav file (no WAVE format): "+ fileName );
+    
+    // check 'fmt ' sub chunk (1)
+    soundCheck(f->read(magic,4,1) == 1, "LoadWav: Cannot read wav file "+ fileName );
+    soundCheck(String(magic) == "fmt ", "LoadWav: Wrong wav file format. This file is not a .wav file (no 'fmt ' subchunk): "+ fileName );
+    
+    // read (1)'s size
+    soundCheck(f->read(data32,4,1)   == 1, "LoadWav: Cannot read wav file "+ fileName );
+    unsigned long subChunk1Size = readByte32(data32);
+    soundCheck(subChunk1Size >= 16, "Wrong wav file format. This file is not a .wav file ('fmt ' chunk too small, truncated file?): "+ fileName );
+    
+    // check PCM audio format
+    soundCheck(f->read(data16,2,1) == 1, "LoadWav: Cannot read wav file "+ fileName );
+    unsigned short audioFormat = readByte16(data16);
+    soundCheck(audioFormat == 1, "LoadWav: Wrong wav file format. This file is not a .wav file (audio format is not PCM): "+ fileName );
+    
+    // read number of channels
+    soundCheck(f->read(data16,2,1) == 1, "LoadWav: Cannot read wav file "+ fileName );
+    unsigned short channels = readByte16(data16);
+    
+    // read frequency (sample rate)
+    soundCheck(f->read(data32,4,1) == 1, "LoadWav: Cannot read wav file "+ fileName );
+    unsigned long frequency = readByte32(data32);
+    
+    // skip 6 bytes (Byte rate (4), Block align (2))
+    f->seek(6,SEEK_CUR);
+    
+    // read bits per sample
+    soundCheck(f->read(data16,2,1) == 1, "LoadWav: Cannot read wav file "+ fileName );
+    unsigned short bps = readByte16(data16);
+    
+    SoundFormat format = SoundFormatUnsupported;
+    
+    switch(bps) {
+        case 8:
+            format = SoundFormat8;
+        break;
+        case 16:
+            format = SoundFormat16;
+        break;
+        case 32:
+            format = SoundFormat32;
+        break;
+            
+    }
+    
+    // check 'data' sub chunk (2)
+    soundCheck(f->read(magic,4,1) == 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 );
+    
+    soundCheck(f->read(data32,4,1) == 1, "LoadWav: Cannot read wav file "+ fileName );
+    unsigned long subChunk2Size = readByte32(data32);
+    
+    array = new char[BUFFER_SIZE];
+    
+    while (data.size() != subChunk2Size) {
+        // Read up to a buffer's worth of decoded sound data
+        bytes = f->read(array, 1, BUFFER_SIZE);
+        
+        if (bytes <= 0)
+            break;
+        
+        if (data.size() + bytes > subChunk2Size)
+            bytes = subChunk2Size - data.size();
+        
+        // Append to end of buffer
+        data.insert(data.end(), array, array + bytes);
+    };
+    
+    delete []array;
+    array = NULL;
+    
+    Services()->getCore()->closeFile(f);
+    f = NULL;
+    
+    
+    
+    return loadBytes(&data[0], data.size(), channels, frequency, format);
 
 }
  
- */
+
 //NOAL_TODO

+ 65 - 34
src/core/PolySoundManager.cpp

@@ -30,11 +30,12 @@ using namespace Polycode;
 SoundManager::SoundManager() {
     audioInterface = NULL;
     testVal = 0.0;
+    globalVolume = 1.0;
+    leftOver = 0.0;
 }
 
 void SoundManager::setGlobalVolume(Number globalVolume) {
-    // NOAL_TODO
-	//alListenerf(AL_GAIN, globalVolume);
+    this->globalVolume = globalVolume;
 }
 
 void SoundManager::setListenerPosition(Vector3 position) {
@@ -101,14 +102,14 @@ Sound *SoundManager::stopRecording(bool generateFloatBuffer) {
     return NULL;
 }
 
-void SoundManager::registerStreamingSound(Sound *sound) {
-    streamingSounds.push_back(sound);
+void SoundManager::registerSound(Sound *sound) {
+    sounds.push_back(sound);
 }
 
-void SoundManager::unregisterStreamingSound(Sound *sound) {
-    for(int i=0; i < streamingSounds.size(); i++) {
-        if(streamingSounds[i] == sound) {
-            streamingSounds.erase(streamingSounds.begin()+i);
+void SoundManager::unregisterSound(Sound *sound) {
+    for(int i=0; i < sounds.size(); i++) {
+        if(sounds[i] == sound) {
+            sounds.erase(sounds.begin()+i);
             return;
         }
     }
@@ -122,10 +123,10 @@ void SoundManager::setAudioInterface(AudioInterface *audioInterface) {
 AudioInterface::AudioInterface() {
     readOffset = 0;
     writeOffset = 0;
-    memset(bufferData, 0, sizeof(float) * POLY_FRAMES_PER_BUFFER*POLY_CIRCULAR_BUFFER_SIZE);
+    memset(bufferData, 0, sizeof(int16_t) * POLY_FRAMES_PER_BUFFER*POLY_CIRCULAR_BUFFER_SIZE);
 }
 
-void AudioInterface::addToBuffer(float *data, unsigned int count) {
+void AudioInterface::addToBuffer(int16_t *data, unsigned int count) {
     for(int i=0; i < count; i++) {
         for(int b=0; b < POLY_NUM_CHANNELS; b++) {
             bufferData[b][writeOffset] = data[(i*POLY_NUM_CHANNELS)+b];
@@ -138,39 +139,69 @@ void AudioInterface::addToBuffer(float *data, unsigned int count) {
     }
 }
 
+inline Number mixSamples(Number A, Number B) {
+
+    if (A < 0 && B < 0 ) {
+        return  (A + B) - (A * B)/-1.0;
+    } else if (A > 0 && B > 0 ) {
+        return (A + B) - (A * B)/1.0;
+    } else {
+        return A + B;
+    }
+}
+
 void SoundManager::Update() {
     Number elapsed = Services()->getCore()->getElapsed();
     
     if(audioInterface) {
-        unsigned int numSamples = ((Number)POLY_AUDIO_FREQ)*elapsed;
+
+        // mix sounds
+        unsigned int numSamples = ((Number)POLY_AUDIO_FREQ)*(elapsed);
         
-        for(int i=0; i < numSamples; i++) {
-            float sinVal = sin(testVal);
-            float data[2] = {sinVal, sinVal};
-            audioInterface->addToBuffer(data, 1);
-            testVal += 1.0/44100.0 * 261.62 * 2.0 * PI; // middle C for testing
+        // align to 64 samples
+       // numSamples = numSamples-(numSamples%64);
+        
+        
+        if(numSamples > POLY_MIX_BUFFER_SIZE) {
+            numSamples = POLY_MIX_BUFFER_SIZE;
+        }
+
+        for(int i=0; i < sounds.size(); i++) {
+            sounds[i]->updateStream(numSamples);
         }
-    }
-    
-    // if recording sound, save samples
-    /*
-    if(captureDevice) {
-        ALint samples;
-        alcGetIntegerv(captureDevice, ALC_CAPTURE_SAMPLES, (ALCsizei)sizeof(ALint), &samples);
-        if(samples) {
-            unsigned int newBufferSize = sizeof(ALbyte) * samples * 4;
-            recordingBuffer = (ALbyte*) realloc(recordingBuffer, recordingBufferSize + newBufferSize);
         
-            alcCaptureSamples(captureDevice, (ALCvoid *)(recordingBuffer+recordingBufferSize), samples);
-            recordingBufferSize += newBufferSize;
+        int16_t *bufferPtr = mixBuffer;
+        for(int i=0; i < numSamples; i++) {
+            
+            Number mixResults[POLY_NUM_CHANNELS];
+            memset(mixResults, 0, sizeof(Number) * POLY_NUM_CHANNELS);
+            
+            int mixNum = 0;
+            for(int i=0; i < sounds.size(); i++) {
+                if(sounds[i]->isPlaying()) {
+                    for(int c=0; c < POLY_NUM_CHANNELS; c++) {
+                        Number A = mixResults[c];
+                        Number B = sounds[i]->getSampleAsNumber(sounds[i]->getOffset(), c);
+                        
+                        if(mixNum == 0) {
+                            mixResults[c] = B;
+                        } else {
+                            mixResults[c] = mixSamples(A, B);
+                        }
+                    }
+                    sounds[i]->setOffset(sounds[i]->getOffset()+1);
+                    mixNum++;
+                }
+            }
+            
+            for(int c=0; c < POLY_NUM_CHANNELS; c++) {
+                *bufferPtr = (int16_t)(((Number)INT16_MAX) * (mixResults[c] * globalVolume));
+                bufferPtr++;
+            }
         }
+        
+        audioInterface->addToBuffer(mixBuffer, numSamples);
     }
-    
-    for(int i=0; i < streamingSounds.size(); i++) {
-        streamingSounds[i]->updateStream();
-    }
-     */
-        // NOAL_TODO
 }
 
 SoundManager::~SoundManager() {