SoundRecorder.cpp
1 //
3 // SFML - Simple and Fast Multimedia Library
4 // Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@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,
10 // including commercial applications, and to alter it and redistribute it freely,
11 // subject to the following restrictions:
12 //
13 // 1. The origin of this software must not be misrepresented;
14 // you must not claim that you wrote the original software.
15 // If you use this software in a product, an acknowledgment
16 // in the product documentation would be appreciated but is not required.
17 //
18 // 2. Altered source versions must be plainly marked as such,
19 // and must not be misrepresented as being the original software.
20 //
21 // 3. This notice may not be removed or altered from any source distribution.
22 //
24 
26 // Headers
28 #include <SFML/Audio/SoundRecorder.hpp>
29 #include <SFML/Audio/AudioDevice.hpp>
30 #include <SFML/Audio/OpenAL.hpp>
31 #include <SFML/System/Sleep.hpp>
32 #include <iostream>
33 
34 
36 // Private data
38 namespace
39 {
40  ALCdevice* CaptureDevice = NULL;
41 }
42 
43 namespace sf
44 {
49 mySampleRate (0),
50 myIsCapturing(false)
51 {
52 
53 }
54 
55 
60 {
61  // Nothing to do
62 }
63 
64 
69 void SoundRecorder::Start(unsigned int SampleRate)
70 {
71  // Check if the device can do audio capture
72  if (!CanCapture())
73  {
74  std::cerr << "Failed to start capture : your system cannot capture audio data (call SoundRecorder::CanCapture to check it)" << std::endl;
75  return;
76  }
77 
78  // Check that another capture is not already running
79  if (CaptureDevice)
80  {
81  std::cerr << "Trying to start audio capture, but another capture is already running" << std::endl;
82  return;
83  }
84 
85  // Open the capture device for capturing 16 bits mono samples
86  CaptureDevice = alcCaptureOpenDevice(NULL, SampleRate, AL_FORMAT_MONO16, SampleRate);
87  if (!CaptureDevice)
88  {
89  std::cerr << "Failed to open the audio capture device" << std::endl;
90  return;
91  }
92 
93  // Clear the sample array
94  mySamples.clear();
95 
96  // Store the sample rate
97  mySampleRate = SampleRate;
98 
99  // Notify derived class
100  if (OnStart())
101  {
102  // Start the capture
103  alcCaptureStart(CaptureDevice);
104 
105  // Start the capture in a new thread, to avoid blocking the main thread
106  myIsCapturing = true;
107  Launch();
108  }
109 }
110 
111 
116 {
117  // Stop the capturing thread
118  myIsCapturing = false;
119  Wait();
120 }
121 
122 
126 unsigned int SoundRecorder::GetSampleRate() const
127 {
128  return mySampleRate;
129 }
130 
131 
137 {
138  ALCdevice* Device = priv::AudioDevice::GetInstance().GetDevice();
139 
140  return (alcIsExtensionPresent(Device, "ALC_EXT_CAPTURE") != AL_FALSE) ||
141  (alcIsExtensionPresent(Device, "ALC_EXT_capture") != AL_FALSE); // "bug" in Mac OS X 10.5 and 10.6
142 }
143 
144 
148 bool SoundRecorder::OnStart()
149 {
150  // Nothing to do
151  return true;
152 }
153 
154 
158 void SoundRecorder::OnStop()
159 {
160  // Nothing to do
161 }
162 
163 
167 void SoundRecorder::Run()
168 {
169  while (myIsCapturing)
170  {
171  // Process available samples
172  ProcessCapturedSamples();
173 
174  // Don't bother the CPU while waiting for more captured data
175  Sleep(0.1f);
176  }
177 
178  // Capture is finished : clean up everything
179  CleanUp();
180 
181  // Notify derived class
182  OnStop();
183 }
184 
185 
189 void SoundRecorder::ProcessCapturedSamples()
190 {
191  // Get the number of samples available
192  ALCint SamplesAvailable;
193  alcGetIntegerv(CaptureDevice, ALC_CAPTURE_SAMPLES, 1, &SamplesAvailable);
194 
195  if (SamplesAvailable > 0)
196  {
197  // Get the recorded samples
198  mySamples.resize(SamplesAvailable);
199  alcCaptureSamples(CaptureDevice, &mySamples[0], SamplesAvailable);
200 
201  // Forward them to the derived class
202  if (!OnProcessSamples(&mySamples[0], mySamples.size()))
203  {
204  // The user wants to stop the capture
205  myIsCapturing = false;
206  }
207  }
208 }
209 
210 
214 void SoundRecorder::CleanUp()
215 {
216  // Stop the capture
217  alcCaptureStop(CaptureDevice);
218 
219  // Get the samples left in the buffer
220  ProcessCapturedSamples();
221 
222  // Close the device
223  alcCaptureCloseDevice(CaptureDevice);
224  CaptureDevice = NULL;
225 }
226 
227 } // namespace sf
void Stop()
Stop the capture.
void Start(unsigned int SampleRate=44100)
Start the capture.
virtual ~SoundRecorder()
Virtual destructor.
void Wait()
Wait until the thread finishes.
Definition: Thread.cpp:89
SoundRecorder()
Default constructor.
static bool CanCapture()
Tell if the system supports sound capture.
unsigned int GetSampleRate() const
Get the sample rate.
void Launch()
Create and run the thread.
Definition: Thread.cpp:72