1 /* 2 * DSFML - The Simple and Fast Multimedia Library for D 3 * 4 * Copyright (c) 2013 - 2017 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 /** 26 * $(U SoundBufferRecorder) allows to access a recorded sound through a 27 * $(SOUNDBUFFER_LINK), so that it can be played, saved to a file, etc. 28 * 29 * It has the same simple interface as its base class (`start()`, `stop()`) and 30 * adds a function to retrieve the recorded sound buffer (`getBuffer()`). 31 * 32 * As usual, don't forget to call the `isAvailable()` function before using this 33 * class (see $(SOUNDRECORDER_LINK) for more details about this). 34 * 35 * Example: 36 * --- 37 * if (SoundBufferRecorder.isAvailable()) 38 * { 39 * // Record some audio data 40 * auto recorder = SoundBufferRecorder(); 41 * recorder.start(); 42 * ... 43 * recorder.stop(); 44 * 45 * // Get the buffer containing the captured audio data 46 * auto buffer = recorder.getBuffer(); 47 * 48 * // Save it to a file (for example...) 49 * buffer.saveToFile("my_record.ogg"); 50 * } 51 * --- 52 * 53 * See_Also: 54 * $(SOUNDRECORDER_LINK) 55 */ 56 module dsfml.audio.soundbufferrecorder; 57 58 import dsfml.audio.soundrecorder; 59 import dsfml.audio.soundbuffer; 60 61 62 /** 63 * Specialized SoundRecorder which stores the captured audio data into a sound 64 * buffer. 65 */ 66 class SoundBufferRecorder : SoundRecorder 67 { 68 private 69 { 70 short[] m_samples; 71 SoundBuffer m_buffer; 72 } 73 74 /// Default constructor. 75 this() 76 { 77 // Constructor code 78 m_buffer = new SoundBuffer(); 79 } 80 81 /// Destructor. 82 ~this() 83 { 84 import dsfml.system.config; 85 mixin(destructorOutput); 86 } 87 88 /** 89 * Get the sound buffer containing the captured audio data. 90 * 91 * The sound buffer is valid only after the capture has ended. This function 92 * provides a read-only access to the internal sound buffer, but it can be 93 * copied if you need to make any modification to it. 94 * 95 * Returns: Read-only access to the sound buffer. 96 */ 97 const(SoundBuffer) getBuffer() const 98 { 99 return m_buffer; 100 } 101 102 protected 103 { 104 /** 105 * Start capturing audio data. 106 * 107 * Returns: true to start the capture, or false to abort it. 108 */ 109 override bool onStart() 110 { 111 m_samples.length = 0; 112 m_buffer = new SoundBuffer(); 113 114 return true; 115 } 116 117 /** 118 * Process a new chunk of recorded samples. 119 * 120 * Params: 121 * samples = Array of the new chunk of recorded samples 122 * 123 * Returns: true to continue the capture, or false to stop it. 124 */ 125 override bool onProcessSamples(const(short)[] samples) 126 { 127 m_samples ~= samples; 128 129 return true; 130 } 131 132 /** 133 * Stop capturing audio data. 134 */ 135 override void onStop() 136 { 137 if(m_samples.length >0) 138 { 139 m_buffer.loadFromSamples(m_samples,1,sampleRate); 140 } 141 } 142 } 143 } 144 145 unittest 146 { 147 //When this unit test is run it occasionally throws an error which will vary, and 148 //is obviously in OpenAL. Probably something to do with the way the binding is done. Will be fixed in 2.1. 149 version(DSFML_Unittest_Audio) 150 { 151 import std.stdio; 152 import core.time; 153 import dsfml.window.keyboard; 154 import dsfml.audio.sound; 155 import dsfml.system.clock; 156 import dsfml.system.sleep; 157 158 159 writeln("Unit test for SoundBufferRecorder."); 160 161 assert(SoundRecorder.isAvailable()); 162 163 164 auto recorder = new SoundBufferRecorder(); 165 166 167 auto clock = new Clock(); 168 169 writeln("Recording for 5 seconds in..."); 170 writeln("3"); 171 clock.restart(); 172 173 while(clock.getElapsedTime().total!"seconds" <1) 174 { 175 //wait for a second 176 } 177 writeln("2"); 178 179 clock.restart(); 180 181 while(clock.getElapsedTime().total!"seconds" <1) 182 { 183 //wait for a second 184 } 185 writeln("1"); 186 187 clock.restart(); 188 189 while(clock.getElapsedTime().total!"seconds" <1) 190 { 191 //wait for a second 192 } 193 writeln("Recording!"); 194 195 recorder.start(); 196 clock.restart(); 197 198 while(clock.getElapsedTime().total!"seconds" <5) 199 { 200 //wait for a second 201 } 202 203 writeln("Done!"); 204 205 206 recorder.stop(); 207 208 auto buffer = recorder.getBuffer(); 209 210 auto recorderDuration = buffer.getDuration(); 211 212 auto recorderSound = new Sound(buffer); 213 214 clock.restart(); 215 216 recorderSound.play(); 217 while(clock.getElapsedTime() < recorderDuration) 218 { 219 //sound playing 220 } 221 222 writeln(); 223 } 224 }