1 /* 2 ******************************************************************************************* 3 * Dgame (a D game framework) - Copyright (c) Randy Schütt 4 * 5 * This software is provided 'as-is', without any express or implied warranty. 6 * In no event will the authors be held liable for any damages arising from 7 * the use of this software. 8 * 9 * Permission is granted to anyone to use this software for any purpose, 10 * including commercial applications, and to alter it and redistribute it 11 * freely, subject to the following restrictions: 12 * 13 * 1. The origin of this software must not be misrepresented; you must not claim 14 * that you wrote the original software. If you use this software in a product, 15 * an acknowledgment in the product documentation would be appreciated but is 16 * not required. 17 * 18 * 2. Altered source versions must be plainly marked as such, and must not be 19 * misrepresented as being the original software. 20 * 21 * 3. This notice may not be removed or altered from any source distribution. 22 ******************************************************************************************* 23 */ 24 module Dgame.Audio.WaveFile; 25 26 private { 27 debug import std.stdio; 28 import std..string : toStringz; 29 30 import derelict.openal.al; 31 32 import Dgame.Internal.Log; 33 import Dgame.Audio.SoundFile; 34 } 35 36 struct WaveHeader { 37 // RIFF - CHUNK 38 char[4] riff; // Enthält den Namen "RIFF" 39 uint riff_length; // Enthält Länge des Riffchunks 40 char[4] wave; // Hier steht "WAVE" 41 // FMT - CHUNK 42 char[4] fmt; // Enthält "FMT" 43 uint fmt_length; // Länge des fmt-chunks 44 ushort format; // 0 = Mono, 1 = Stereo 45 ushort channels; // Anz. der benutzten Kanäle 46 uint sample_rate; // Sample-Rate in Herz 47 uint byte_rate; 48 ushort block_align; 49 ushort bits_per_sample; 50 char[4] data; 51 } 52 53 struct DataHeader { 54 uint chunkSize; 55 } 56 57 /** 58 * A Wave implementation of BaseSoundFile 59 * Open a wave file and store the attributes from it's headers. 60 * 61 * Author: rschuett 62 */ 63 class WaveFile : BaseSoundFile { 64 protected: 65 override void _read(string filename) { 66 FILE* fp = fopen(toStringz(filename), toStringz("rb")); 67 scope(exit) { 68 fclose(fp); 69 fp = null; 70 } 71 72 WaveHeader wHeader = void; 73 fread(&wHeader, WaveHeader.sizeof, 1, fp); 74 75 if (wHeader.riff != "RIFF") 76 throw new Exception("No RIFF: " ~ wHeader.riff.idup); 77 if (wHeader.wave != "WAVE") 78 throw new Exception("No WAVE: " ~ wHeader.wave.idup); 79 if (wHeader.fmt[0 .. 3] != "fmt") 80 throw new Exception("No fmt: " ~wHeader.fmt.idup); 81 82 DataHeader dHeader = void; 83 if (wHeader.data == "data") { 84 fread(&dHeader, DataHeader.sizeof, 1, fp); 85 } else { 86 throw new Exception("Expected data chunk, not: " ~ wHeader.data.idup); 87 } 88 89 if (dHeader.chunkSize == 0) 90 throw new Exception("Invalid size"); 91 92 super._buffer = new byte[dHeader.chunkSize]; 93 fread(super._buffer.ptr, byte.sizeof, dHeader.chunkSize, fp); 94 95 super._sFile.rate = wHeader.sample_rate; 96 super._sFile.dataSize = dHeader.chunkSize; 97 super._sFile.channels = wHeader.channels; 98 super._sFile.bits = wHeader.bits_per_sample; 99 super._sFile.bytes = wHeader.bits_per_sample / 8; 100 101 //writeln(filename, "::", wHeader); 102 103 debug Log.info("Allocate %d memory for Wave file %s.", dHeader.chunkSize, filename); 104 } 105 106 public: 107 /** 108 * CTor 109 */ 110 this(string filename) { 111 super(filename); 112 } 113 114 /** 115 * Returns the music type. In this case: wave. 116 */ 117 override MusicType getType() const pure nothrow { 118 return MusicType.Wave; 119 } 120 }