1 module prova.assets.audio.audioclip; 2 3 import derelict.openal.al; 4 import derelict.vorbis; 5 import prova.assets; 6 import std.string; 7 8 /// Only supports ogg for now 9 final class AudioClip : Asset 10 { 11 /// What distance in units equals one meter (defaults to 1) 12 static float scale = 1; 13 /// 14 package(prova) uint bufferId; 15 private uint _channels; 16 17 /// 18 this(string path) 19 { 20 genFromOgg(path); 21 } 22 23 /// 24 @property uint channels() 25 { 26 return _channels; 27 } 28 29 private void genFromOgg(string path) 30 { 31 OggVorbis_File ogg; 32 33 if(ov_fopen(toStringz(path), &ogg) < 0) 34 throw new Exception("\"" ~ path ~ "\" is not a valid Ogg file"); 35 36 const BUFFER_SIZE = 4096; 37 byte[BUFFER_SIZE] dataBuffer; 38 byte[] data; 39 long bytesRead = 0; 40 int currentSection; 41 42 long requiredCapacity = ov_pcm_total(&ogg, -1) * ogg.vi.channels * 2; 43 data.reserve(requiredCapacity); 44 45 do{ 46 bytesRead = ov_read(&ogg, dataBuffer.ptr, BUFFER_SIZE, 0, 2, 1, ¤tSection); 47 48 data ~= dataBuffer[0 .. bytesRead]; 49 } 50 while(bytesRead > 0); 51 52 genBuffer(ogg.vi.channels, data, ogg.vi.rate); 53 54 ov_clear(&ogg); 55 } 56 57 private void genBuffer(uint channels, byte[] data, int frequency) 58 { 59 _channels = channels; 60 61 ALenum format = channels ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16; 62 63 alGenBuffers(1, &bufferId); 64 alBufferData(bufferId, format, data.ptr, cast(int) data.length, frequency); 65 } 66 }