1 /* 2 * DSFML - The Simple and Fast Multimedia Library for D 3 * 4 * Copyright (c) 2013 - 2018 Jeremy DeHaan (dehaan.jeremiah@gmail.com) 5 * 6 * This software is provided 'as-is', without any express or implied warranty. 7 * In no event will the authors be held liable for any damages arising from the 8 * use of this software. 9 * 10 * Permission is granted to anyone to use this software for any purpose, 11 * including commercial applications, and to alter it and redistribute it 12 * freely, subject to the following restrictions: 13 * 14 * 1. The origin of this software must not be misrepresented; you must not claim 15 * that you wrote the original software. If you use this software in a product, 16 * an acknowledgment in the product documentation would be appreciated but is 17 * not required. 18 * 19 * 2. Altered source versions must be plainly marked as such, and must not be 20 * misrepresented as being the original software. 21 * 22 * 3. This notice may not be removed or altered from any source distribution 23 * 24 * 25 * DSFML is based on SFML (Copyright Laurent Gomila) 26 */ 27 28 /** 29 * $(U InputSoundFile) decodes audio samples from a sound file. It is used 30 * internally by higher-level classes such as $(SOUNDBUFFER_LINK) and 31 * $(MUSIC_LINK), but can also be useful if you want to process or analyze audio 32 * files without playing them, or if you want to implement your own version of 33 * $(MUSIC_LINK) with more specific features. 34 * 35 * Example: 36 * --- 37 * // Open a sound file 38 * auto file = new InputSoundFile(); 39 * if (!file.openFromFile("music.ogg")) 40 * { 41 * //error 42 * } 43 * 44 * // Print the sound attributes 45 * writeln("duration: ", file.getDuration().total!"seconds"); 46 * writeln("channels: ", file.getChannelCount()); 47 * writeln("sample rate: ", file.getSampleRate()); 48 * writeln("sample count: ", file.getSampleCount()); 49 * 50 * // Read and process batches of samples until the end of file is reached 51 * short samples[1024]; 52 * long count; 53 * do 54 * { 55 * count = file.read(samples, 1024); 56 * 57 * // process, analyze, play, convert, or whatever 58 * // you want to do with the samples... 59 * } 60 * while (count > 0); 61 * --- 62 * 63 * See_Also: 64 * $(OUTPUTSOUNDFILE_LINK) 65 */ 66 module dsfml.audio.inputsoundfile; 67 68 import std..string; 69 import dsfml.system.inputstream; 70 import dsfml.system.err; 71 72 public import dsfml.system.time; 73 74 /** 75 * Provide read access to sound files. 76 */ 77 class InputSoundFile 78 { 79 private sfInputSoundFile* m_soundFile; 80 81 //keeps an instance of the C++ interface stored if used 82 private soundFileStream m_stream; 83 84 /// Default constructor. 85 this() 86 { 87 m_soundFile = sfInputSoundFile_create(); 88 } 89 90 /// Destructor. 91 ~this() 92 { 93 import dsfml.system.config: destructorOutput; 94 mixin(destructorOutput); 95 sfInputSoundFile_destroy(m_soundFile); 96 } 97 98 /** 99 * Open a sound file from the disk for reading. 100 * 101 * The supported audio formats are: WAV (PCM only), OGG/Vorbis, FLAC. The 102 * supported sample sizes for FLAC and WAV are 8, 16, 24 and 32 bit. 103 * 104 * Params: 105 * filename = Path of the sound file to load 106 * 107 * Returns: true if the file was successfully opened. 108 */ 109 bool openFromFile(const(char)[] filename) 110 { 111 import dsfml.system..string; 112 return sfInputSoundFile_openFromFile(m_soundFile, filename.ptr, filename.length); 113 } 114 115 /** 116 * Open a sound file in memory for reading. 117 * 118 * The supported audio formats are: WAV (PCM only), OGG/Vorbis, FLAC. The 119 * supported sample sizes for FLAC and WAV are 8, 16, 24 and 32 bit. 120 * 121 * Params: 122 * data = file data in memory 123 * 124 * Returns: true if the file was successfully opened. 125 */ 126 bool openFromMemory(const(void)[] data) 127 { 128 return sfInputSoundFile_openFromMemory(m_soundFile, data.ptr, data.length); 129 } 130 131 /** 132 * Open a sound file from a custom stream for reading. 133 * 134 * The supported audio formats are: WAV (PCM only), OGG/Vorbis, FLAC. The 135 * supported sample sizes for FLAC and WAV are 8, 16, 24 and 32 bit. 136 * 137 * Params: 138 * stream = Source stream to read from 139 * 140 * Returns: true if the file was successfully opened. 141 */ 142 bool openFromStream(InputStream stream) 143 { 144 m_stream = new soundFileStream(stream); 145 return sfInputSoundFile_openFromStream(m_soundFile, m_stream); 146 } 147 148 /** 149 * Read audio samples from the open file. 150 * 151 * Params: 152 * samples = array of samples to fill 153 * 154 * Returns: Number of samples actually read (may be less samples.length) 155 */ 156 long read(short[] samples) 157 { 158 return sfInputSoundFile_read(m_soundFile, samples.ptr, samples.length); 159 160 } 161 162 /** 163 * Change the current read position to the given sample offset. 164 * 165 * This function takes a sample offset to provide maximum precision. If you 166 * need to jump to a given time, use the other overload. 167 * 168 * The sample offset takes the channels into account. Offsets can be 169 * calculated like this: sampleNumber * sampleRate * channelCount. 170 * If the given offset exceeds to total number of samples, this function 171 * jumps to the end of the sound file. 172 * 173 * Params: 174 * sampleOffset = Index of the sample to jump to, relative to the beginning 175 */ 176 void seek(long sampleOffset) 177 { 178 sfInputSoundFile_seek(m_soundFile, sampleOffset); 179 } 180 181 /** 182 * Change the current read position to the given time offset. 183 * 184 * Using a time offset is handy but imprecise. If you need an accurate 185 * result, consider using the overload which takes a sample offset. 186 * 187 * If the given time exceeds to total duration, this function jumps to the 188 * end of the sound file. 189 * 190 * Params: 191 * timeOffset = Time to jump to, relative to the beginning 192 */ 193 void seek(Time timeOffset) 194 { 195 seek(timeOffset.asMicroseconds()); 196 } 197 198 /** 199 * Get the total number of audio samples in the file 200 * 201 * Returns: Number of samples. 202 */ 203 long getSampleCount() const 204 { 205 return sfInputSoundFile_getSampleCount(m_soundFile); 206 } 207 208 /** 209 * Get the sample rate of the sound 210 * 211 * Returns: Sample rate, in samples per second. 212 */ 213 uint getSampleRate() const 214 { 215 return sfInputSoundFile_getSampleRate(m_soundFile); 216 } 217 218 /** 219 * Get the number of channels used by the sound 220 * 221 * Returns: Number of channels (1 = mono, 2 = stereo). 222 */ 223 uint getChannelCount() const 224 { 225 return sfInputSoundFile_getChannelCount(m_soundFile); 226 } 227 } 228 229 private 230 { 231 232 extern(C++) interface soundInputStream 233 { 234 long read(void* data, long size); 235 236 long seek(long position); 237 238 long tell(); 239 240 long getSize(); 241 } 242 243 244 class soundFileStream:soundInputStream 245 { 246 private InputStream myStream; 247 248 this(InputStream stream) 249 { 250 myStream = stream; 251 } 252 253 extern(C++)long read(void* data, long size) 254 { 255 return myStream.read(data[0..cast(size_t)size]); 256 } 257 258 extern(C++)long seek(long position) 259 { 260 return myStream.seek(position); 261 } 262 263 extern(C++)long tell() 264 { 265 return myStream.tell(); 266 } 267 268 extern(C++)long getSize() 269 { 270 return myStream.getSize(); 271 } 272 } 273 274 extern(C) 275 { 276 277 struct sfInputSoundFile; 278 279 sfInputSoundFile* sfInputSoundFile_create(); 280 281 void sfInputSoundFile_destroy(sfInputSoundFile* file); 282 283 long sfInputSoundFile_getSampleCount(const sfInputSoundFile* file); 284 285 uint sfInputSoundFile_getChannelCount( const sfInputSoundFile* file); 286 287 uint sfInputSoundFile_getSampleRate(const sfInputSoundFile* file); 288 289 bool sfInputSoundFile_openFromFile(sfInputSoundFile* file, const char* filename, size_t length); 290 291 bool sfInputSoundFile_openFromMemory(sfInputSoundFile* file,const(void)* data, long sizeInBytes); 292 293 bool sfInputSoundFile_openFromStream(sfInputSoundFile* file, soundInputStream stream); 294 295 bool sfInputSoundFile_openForWriting(sfInputSoundFile* file, const(char)* filename,uint channelCount,uint sampleRate); 296 297 long sfInputSoundFile_read(sfInputSoundFile* file, short* data, long sampleCount); 298 299 void sfInputSoundFile_seek(sfInputSoundFile* file, long timeOffset); 300 } 301 }