Back to index

libsfml  1.6+dfsg2
SoundRecorder.cpp
Go to the documentation of this file.
00001 
00002 //
00003 // SFML - Simple and Fast Multimedia Library
00004 // Copyright (C) 2007-2009 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 SoundRecorder::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     // Notify derived class
00100     if (OnStart())
00101     {
00102         // Start the capture
00103         alcCaptureStart(CaptureDevice);
00104 
00105         // Start the capture in a new thread, to avoid blocking the main thread
00106         myIsCapturing = true;
00107         Launch();
00108     }
00109 }
00110 
00111 
00115 void SoundRecorder::Stop()
00116 {
00117     // Stop the capturing thread
00118     myIsCapturing = false;
00119     Wait();
00120 }
00121 
00122 
00126 unsigned int SoundRecorder::GetSampleRate() const
00127 {
00128     return mySampleRate;
00129 }
00130 
00131 
00136 bool SoundRecorder::CanCapture()
00137 {
00138     ALCdevice* Device = priv::AudioDevice::GetInstance().GetDevice();
00139 
00140     return (alcIsExtensionPresent(Device, "ALC_EXT_CAPTURE") != AL_FALSE) ||
00141            (alcIsExtensionPresent(Device, "ALC_EXT_capture") != AL_FALSE); // "bug" in Mac OS X 10.5 and 10.6
00142 }
00143 
00144 
00148 bool SoundRecorder::OnStart()
00149 {
00150     // Nothing to do
00151     return true;
00152 }
00153 
00154 
00158 void SoundRecorder::OnStop()
00159 {
00160     // Nothing to do
00161 }
00162 
00163 
00167 void SoundRecorder::Run()
00168 {
00169     while (myIsCapturing)
00170     {
00171         // Process available samples
00172         ProcessCapturedSamples();
00173 
00174         // Don't bother the CPU while waiting for more captured data
00175         Sleep(0.1f);
00176     }
00177 
00178     // Capture is finished : clean up everything
00179     CleanUp();
00180 
00181     // Notify derived class
00182     OnStop();
00183 }
00184 
00185 
00189 void SoundRecorder::ProcessCapturedSamples()
00190 {
00191     // Get the number of samples available
00192     ALCint SamplesAvailable;
00193     alcGetIntegerv(CaptureDevice, ALC_CAPTURE_SAMPLES, 1, &SamplesAvailable);
00194 
00195     if (SamplesAvailable > 0)
00196     {
00197         // Get the recorded samples
00198         mySamples.resize(SamplesAvailable);
00199         alcCaptureSamples(CaptureDevice, &mySamples[0], SamplesAvailable);
00200 
00201         // Forward them to the derived class
00202         if (!OnProcessSamples(&mySamples[0], mySamples.size()))
00203         {
00204             // The user wants to stop the capture
00205             myIsCapturing = false;
00206         }
00207     }
00208 }
00209 
00210 
00214 void SoundRecorder::CleanUp()
00215 {
00216     // Stop the capture
00217     alcCaptureStop(CaptureDevice);
00218 
00219     // Get the samples left in the buffer
00220     ProcessCapturedSamples();
00221 
00222     // Close the device
00223     alcCaptureCloseDevice(CaptureDevice);
00224     CaptureDevice = NULL;
00225 }
00226 
00227 } // namespace sf