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