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