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 dsfml.audio.soundbufferrecorder; 60 61 import dsfml.audio.soundrecorder; 62 import dsfml.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 short[] m_samples; 73 SoundBuffer m_buffer; 74 } 75 76 /// Default constructor. 77 this() 78 { 79 // Constructor code 80 m_buffer = new SoundBuffer(); 81 } 82 83 /// Destructor. 84 ~this() 85 { 86 import dsfml.system.config; 87 mixin(destructorOutput); 88 } 89 90 /** 91 * Get the sound buffer containing the captured audio data. 92 * 93 * The sound buffer is valid only after the capture has ended. This function 94 * provides a read-only access to the internal sound buffer, but it can be 95 * copied if you need to make any modification to it. 96 * 97 * Returns: Read-only access to the sound buffer. 98 */ 99 const(SoundBuffer) getBuffer() const 100 { 101 return m_buffer; 102 } 103 104 protected 105 { 106 /** 107 * Start capturing audio data. 108 * 109 * Returns: true to start the capture, or false to abort it. 110 */ 111 override bool onStart() 112 { 113 m_samples.length = 0; 114 m_buffer = new SoundBuffer(); 115 116 return true; 117 } 118 119 /** 120 * Process a new chunk of recorded samples. 121 * 122 * Params: 123 * samples = Array of the new chunk of recorded samples 124 * 125 * Returns: true to continue the capture, or false to stop it. 126 */ 127 override bool onProcessSamples(const(short)[] samples) 128 { 129 m_samples ~= samples; 130 131 return true; 132 } 133 134 /** 135 * Stop capturing audio data. 136 */ 137 override void onStop() 138 { 139 if(m_samples.length >0) 140 { 141 m_buffer.loadFromSamples(m_samples,1,sampleRate); 142 } 143 } 144 } 145 } 146 147 unittest 148 { 149 //When this unit test is run it occasionally throws an error which will vary, and 150 //is obviously in OpenAL. Probably something to do with the way the binding is done. Will be fixed in 2.1. 151 version(DSFML_Unittest_Audio) 152 { 153 import std.stdio; 154 import dsfml.window.keyboard; 155 import dsfml.audio.sound; 156 import dsfml.system.clock; 157 import dsfml.system.sleep; 158 159 writeln("Unit test for SoundBufferRecorder."); 160 161 assert(SoundRecorder.isAvailable()); 162 163 auto recorder = new SoundBufferRecorder(); 164 165 auto clock = new Clock(); 166 167 writeln("Recording for 5 seconds in..."); 168 writeln("3"); 169 clock.restart(); 170 171 while(clock.getElapsedTime().asSeconds() <1) 172 { 173 //wait for a second 174 } 175 176 writeln("2"); 177 178 clock.restart(); 179 180 while(clock.getElapsedTime().asSeconds() <1) 181 { 182 //wait for a second 183 } 184 185 writeln("1"); 186 187 clock.restart(); 188 189 while(clock.getElapsedTime().asSeconds() <1) 190 { 191 //wait for a second 192 } 193 194 writeln("Recording!"); 195 196 recorder.start(); 197 clock.restart(); 198 199 while(clock.getElapsedTime().asSeconds() <5) 200 { 201 //wait for a second 202 } 203 204 writeln("Done!"); 205 206 recorder.stop(); 207 208 auto buffer = recorder.getBuffer(); 209 auto recorderDuration = buffer.getDuration(); 210 auto recorderSound = new Sound(buffer); 211 212 clock.restart(); 213 214 recorderSound.play(); 215 while(clock.getElapsedTime() < recorderDuration) 216 { 217 //sound playing 218 } 219 220 writeln(); 221 } 222 }