1 /*
2 DSFML - The Simple and Fast Multimedia Library for D
3 
4 Copyright (c) 2013 - 2015 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 use of this software.
8 
9 Permission is granted to anyone to use this software for any purpose, including commercial applications,
10 and to alter it and redistribute it freely, subject to the following restrictions:
11 
12 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software.
13 If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
14 
15 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
16 
17 3. This notice may not be removed or altered from any source distribution
18 */
19 
20 module dsfml.audio.soundbufferrecorder;
21 
22 import dsfml.audio.soundrecorder;
23 import dsfml.audio.soundbuffer;
24 
25 
26 /++
27  + Specialized SoundRecorder which stores the captured audio data into a sound buffer.
28  + 
29  + SoundBufferRecorder allows to access a recorded sound through a SoundBuffer, so that it can be played, saved to a file, etc.
30  + 
31  + It has the same simple interface as its base class (start(), stop()) and adds a function to retrieve the recorded sound buffer (getBuffer()).
32  + 
33  + As usual, don't forget to call the isAvailable() function before using this class (see SoundRecorder for more details about this).
34  + 
35  + See_Also: http://www.sfml-dev.org/documentation/2.0/classsf_1_1SoundBufferRecorder.php#details
36  + Authors: Laurent Gomila, Jeremy DeHaan
37  +/
38 class SoundBufferRecorder : SoundRecorder
39 {
40 	private
41 	{
42 		short[] m_samples;
43 		SoundBuffer m_buffer;
44 	}
45 	
46 	this()
47 	{
48 		// Constructor code
49 		m_buffer = new SoundBuffer();
50 	}
51 	
52 	~this()
53 	{
54 		import dsfml.system.config;
55 		mixin(destructorOutput);
56 	}
57 	
58 	/**
59 	 * Get the sound buffer containing the captured audio data.
60 	 * 
61 	 * The sound buffer is valid only after the capture has ended. This function provides a read-only access to the internal sound buffer, but it can be copied if you need to make any modification to it.
62 	 * 
63 	 * Returns: Read-only access to the sound buffer
64 	 */
65 	const(SoundBuffer) getBuffer() const
66 	{
67 		return m_buffer;
68 	}
69 	
70 	protected
71 	{
72 		/// Start capturing audio data.
73 		/// Returns: True to start the capture, or false to abort it
74 		override bool onStart()
75 		{
76 			m_samples.length = 0;
77 			m_buffer = new SoundBuffer();
78 			
79 			return true;
80 		}
81 		
82 		/**
83 		 * Process a new chunk of recorded samples.
84 		 * 
85 		 * Params:
86 		 * 		samples =	Array of the new chunk of recorded samples'
87 		 * 
88 		 * Returns: True to continue the capture, or false to stop it
89 		 */
90 		override bool onProcessSamples(const(short)[] samples)
91 		{
92 			m_samples ~= samples;
93 			
94 			return true;
95 		}
96 		
97 		/// Stop capturing audio data.
98 		/// 
99 		/// Reimplemented from SoundRecorder.
100 		override void onStop()
101 		{
102 			if(m_samples.length >0)
103 			{
104 				m_buffer.loadFromSamples(m_samples,1,sampleRate);
105 			}
106 		}
107 	}
108 }
109 
110 unittest
111 {
112 	//When this unit test is run it occasionally throws an error which will vary, and
113 	//is obviously in OpenAL. Probably something to do with the way the binding is done. Will be fixed in 2.1.
114 	version(DSFML_Unittest_Audio)
115 	{
116 		import std.stdio;
117 		import core.time;
118 		import dsfml.window.keyboard;
119 		import dsfml.audio.sound;
120 		import dsfml.system.clock;
121 		import dsfml.system.sleep;
122 		
123 		
124 		writeln("Unit test for SoundBufferRecorder.");
125 		
126 		assert(SoundRecorder.isAvailable());
127 
128 
129 		auto recorder = new SoundBufferRecorder();
130 		
131 		
132 		auto clock = new Clock();
133 
134 		writeln("Recording for 5 seconds in...");
135 		writeln("3");
136 		clock.restart();
137 
138 		while(clock.getElapsedTime().total!"seconds" <1)
139 		{
140 			//wait for a second
141 		}
142 		writeln("2");
143 		
144 		clock.restart();
145 
146 		while(clock.getElapsedTime().total!"seconds" <1)
147 		{
148 			//wait for a second
149 		}
150 		writeln("1");
151 
152 		clock.restart();
153 
154 		while(clock.getElapsedTime().total!"seconds" <1)
155 		{
156 			//wait for a second
157 		}
158 		writeln("Recording!");	
159 
160 		recorder.start();	
161 		clock.restart();
162 
163 		while(clock.getElapsedTime().total!"seconds" <5)
164 		{
165 			//wait for a second
166 		}
167 		
168 		writeln("Done!");
169 		
170 		
171 		recorder.stop();
172 		
173 
174 
175 
176 		auto buffer = recorder.getBuffer();
177 		
178 		auto recorderDuration = buffer.getDuration();
179 		
180 		auto recorderSound = new Sound(buffer);
181 		
182 		clock.restart();
183 		
184 		recorderSound.play();
185 		while(clock.getElapsedTime() < recorderDuration)
186 		{
187 			//sound playing
188 		}
189 		
190 		
191 		
192 		
193 		writeln();
194 	}
195 }