SoundRecorder.cpp

00001 
00002 //
00003 // SFML - Simple and Fast Multimedia Library
00004 // Copyright (C) 2007 Laurent Gomila (laurent.gom@gmail.com)
00005 //
00006 // This software is provided 'as-is', without any express or implied warranty.
00007 // In no event will the authors be held liable for any damages arising from the use of this software.
00008 //
00009 // Permission is granted to anyone to use this software for any purpose,
00010 // including commercial applications, and to alter it and redistribute it freely,
00011 // subject to the following restrictions:
00012 //
00013 // 1. The origin of this software must not be misrepresented;
00014 //    you must not claim that you wrote the original software.
00015 //    If you use this software in a product, an acknowledgment
00016 //    in the product documentation would be appreciated but is not required.
00017 //
00018 // 2. Altered source versions must be plainly marked as such,
00019 //    and must not be misrepresented as being the original software.
00020 //
00021 // 3. This notice may not be removed or altered from any source distribution.
00022 //
00024 
00026 // Headers
00028 #include <SFML/Audio/SoundRecorder.hpp>
00029 #include <SFML/Audio/AudioDevice.hpp>
00030 #include <SFML/Audio/OpenAL.hpp>
00031 #include <SFML/System/Sleep.hpp>
00032 #include <iostream>
00033 
00034 
00036 // Private data
00038 namespace
00039 {
00040     ALCdevice* CaptureDevice = NULL;
00041 }
00042 
00043 namespace sf
00044 {
00048 SoundRecorder::SoundRecorder() :
00049 mySampleRate (0),
00050 myIsCapturing(false)
00051 {
00052 
00053 }
00054 
00055 
00059 SoundRecorder::~SoundRecorder()
00060 {
00061     // Nothing to do
00062 }
00063 
00064 
00069 void SoundRecorder::Start(unsigned int SampleRate)
00070 {
00071     // Check if the device can do audio capture
00072     if (!CanCapture())
00073     {
00074         std::cerr << "Failed to start capture : your system cannot capture audio data (call sfSoundRecorder::CanCapture to check it)" << std::endl;
00075         return;
00076     }
00077 
00078     // Check that another capture is not already running
00079     if (CaptureDevice)
00080     {
00081         std::cerr << "Trying to start audio capture, but another capture is already running" << std::endl;
00082         return;
00083     }
00084 
00085     // Open the capture device for capturing 16 bits mono samples
00086     CaptureDevice = alcCaptureOpenDevice(NULL, SampleRate, AL_FORMAT_MONO16, SampleRate);
00087     if (!CaptureDevice)
00088     {
00089         std::cerr << "Failed to open the audio capture device" << std::endl;
00090         return;
00091     }
00092 
00093     // Clear the sample array
00094     mySamples.clear();
00095 
00096     // Store the sample rate
00097     mySampleRate = SampleRate;
00098 
00099     // Start the capture
00100     alcCaptureStart(CaptureDevice);
00101 
00102     // Start the capture in a new thread, to avoid blocking the main thread
00103     myIsCapturing = true;
00104     Launch();
00105 }
00106 
00107 
00111 void SoundRecorder::Stop()
00112 {
00113     // If capture has not been started, we cannot stop
00114     if (!myIsCapturing)
00115     {
00116         std::cerr << "Trying to stop audio capture, but the capture has not been started ; call Start() first" << std::endl;
00117         return;
00118     }
00119 
00120     // Stop the capturing thread
00121     myIsCapturing = false;
00122     Wait();
00123 }
00124 
00125 
00129 unsigned int SoundRecorder::GetSampleRate() const
00130 {
00131     return mySampleRate;
00132 }
00133 
00134 
00139 bool SoundRecorder::CanCapture()
00140 {
00141     ALCdevice* Device = priv::AudioDevice::GetInstance().GetDevice();
00142 
00143     return alcIsExtensionPresent(Device, "ALC_EXT_CAPTURE") != AL_FALSE;
00144 }
00145 
00146 
00150 void SoundRecorder::Run()
00151 {
00152     while (myIsCapturing)
00153     {
00154         // Process available samples
00155         ProcessCapturedSamples();
00156 
00157         // Don't bother the CPU while waiting for more captured data
00158         Sleep(0.1f);
00159     }
00160 
00161     // Capture is finished : clean up everything
00162     CleanUp();
00163 }
00164 
00165 
00169 void SoundRecorder::ProcessCapturedSamples()
00170 {
00171     // Get the number of samples available
00172     ALCint SamplesAvailable;
00173     alcGetIntegerv(CaptureDevice, ALC_CAPTURE_SAMPLES, 1, &SamplesAvailable);
00174 
00175     if (SamplesAvailable > 0)
00176     {
00177         // Get the recorded samples
00178         mySamples.resize(SamplesAvailable);
00179         alcCaptureSamples(CaptureDevice, &mySamples[0], SamplesAvailable);
00180 
00181         // Forward them to the derived class
00182         if (!ProcessSamples(&mySamples[0], mySamples.size()))
00183         {
00184             // The user wants to stop the capture
00185             myIsCapturing = false;
00186         }
00187     }
00188 }
00189 
00190 
00194 void SoundRecorder::CleanUp()
00195 {
00196     // Stop the capture
00197     alcCaptureStop(CaptureDevice);
00198 
00199     // Get the samples left in the buffer
00200     ProcessCapturedSamples();
00201 
00202     // Close the device
00203     alcCaptureCloseDevice(CaptureDevice);
00204     CaptureDevice = NULL;
00205 }
00206 
00207 } // namespace sf