using OpenTK.Audio.OpenAL; using System.IO; using OpenTK; using System; /** * * @author Jarl */ namespace Ogg { public class Stream { const int BUFFER_SIZE = 4096 * 8; OggInputStream oggStream; int rate; ALFormat format; int []buffers; int []source; public bool loop; public string fileName; public Stream(string fileName){ open(fileName); this.fileName = fileName; loop = false; } public Stream(string fileName, bool loop){ open(fileName); this.fileName = fileName; this.loop = loop; } public Stream(Stream stream){ open(stream.fileName); loop = stream.loop; } public void open(string path){ oggStream = new OggInputStream(File.OpenRead(path)); format = oggStream.getFormat() == OggInputStream.FORMAT_MONO16 ? ALFormat.Mono16 : ALFormat.Stereo16; rate = oggStream.getRate(); buffers = AL.GenBuffers(2); check(); source = AL.GenSources(1); check(); Vector3 zeros = new Vector3( 0, 0, 0); AL.Source(source[0], ALSource3f.Position, ref zeros); AL.Source(source[0], ALSource3f.Velocity, ref zeros); AL.Source(source[0], ALSource3f.Direction, ref zeros); AL.Source(source[0], ALSourcef.RolloffFactor, 0.0f); AL.Source(source[0], ALSourceb.SourceRelative, true); } public void release(){ AL.SourceStop(source[0]); empty(); AL.DeleteSource(source[0]); check(); AL.DeleteBuffers(buffers); check(); } public void rewind(){ //oggStream.close(); release(); open(fileName); } public void display(){ Console.WriteLine(oggStream); } public bool playback(){ if(playing()){ return true; } if(!stream(buffers[0])){ return false; } if(!stream(buffers[1])){ return false; } AL.SourceQueueBuffers(source[0], buffers.Length, buffers); AL.SourcePlay(source[0]); return true; } public bool playing(){ ALSourceState state; state = AL.GetSourceState(source[0]); return (state == ALSourceState.Playing); } public bool update(){ int processed; bool active = true; AL.GetSource(source[0], ALGetSourcei.BuffersProcessed, out processed); while(processed-- != 0) { int []buffer; buffer = AL.SourceUnqueueBuffers(source[0], 1); check(); active = stream(buffer[0]); AL.SourceQueueBuffers(source[0], buffer.Length, buffer); check(); } if(!playing()){ AL.SourcePlay(source[0]); } return active; } public void pause(){ AL.SourcePause(source[0]); } public bool stream(int buffer){ byte []data = new byte[BUFFER_SIZE]; int size = 0; int result; while(size < BUFFER_SIZE){ result = oggStream.read(data, size, BUFFER_SIZE - size); if(result > 0){ size += result; }else{ if(result < 0){ throw new Exception("Stream Error: " + result); }else{ break; } } } if(size == 0){ return false; } AL.BufferData(buffer, format, data, data.Length, rate); check(); return true; } public void empty(){ int queued; AL.GetSource(source[0], ALGetSourcei.BuffersQueued, out queued); while(queued-- != 0) { int []buffer; buffer = AL.SourceUnqueueBuffers(source[0], 1); check(); } } public void check(){ ALError error = AL.GetError(); if(error != ALError.NoError) { Console.WriteLine(error); throw new Exception("OpenAL error was raised."); } } } }