From f49c156a31b551d4c1a73156f072007ab29a83aa Mon Sep 17 00:00:00 2001 From: Maximilian Wagenbach Date: Thu, 1 Oct 2015 15:43:35 +0200 Subject: [PATCH] Implemented stereo audio recording. --- include/SFML/Audio/SoundRecorder.hpp | 35 ++++++++++++++++++++ src/SFML/Audio/SoundBufferRecorder.cpp | 2 +- src/SFML/Audio/SoundRecorder.cpp | 45 ++++++++++++++++++++++---- 3 files changed, 75 insertions(+), 7 deletions(-) diff --git a/include/SFML/Audio/SoundRecorder.hpp b/include/SFML/Audio/SoundRecorder.hpp index f05b4a59..f7724e69 100644 --- a/include/SFML/Audio/SoundRecorder.hpp +++ b/include/SFML/Audio/SoundRecorder.hpp @@ -144,6 +144,34 @@ public: //////////////////////////////////////////////////////////// const std::string& getDevice() const; + //////////////////////////////////////////////////////////// + /// \brief Set the channel count of the audio capture device + /// + /// This method allows you to specify the number of channels + /// used for recording. Currently only 16-bit mono and + /// 16-bit stereo are supported. + /// + /// \param channelCount Number of channels. Currently only + /// mono (1) and stereo (2) are supported. + /// + /// \see getChannelCount + /// + //////////////////////////////////////////////////////////// + void setChannelCount(unsigned int channelCount); + + //////////////////////////////////////////////////////////// + /// \brief Get the number of channels used by this recorder + /// + /// Currently only mono and stereo are supported, so the + /// value is either 1 (for mono) or 2 (for stereo). + /// + /// \return Number of channels + /// + /// \see setChannelCount + /// + //////////////////////////////////////////////////////////// + unsigned int getChannelCount() const; + //////////////////////////////////////////////////////////// /// \brief Check if the system supports audio capture /// @@ -263,6 +291,7 @@ private: Time m_processingInterval; ///< Time period between calls to onProcessSamples bool m_isCapturing; ///< Capturing state std::string m_deviceName; ///< Name of the audio capture device + unsigned int m_channelCount; ///< Number of recording channels }; } // namespace sf @@ -309,6 +338,12 @@ private: /// by calling setDevice() with the appropriate device. Otherwise /// the default capturing device will be used. /// +/// By default the recording is in 16-bit mono. Using the +/// setChannelCount method you can change the number of channels +/// used by the audio capture device to record. Note that you +/// have to decide whether you want to record in mono or stereo +/// before starting the recording. +/// /// It is important to note that the audio capture happens in a /// separate thread, so that it doesn't block the rest of the /// program. In particular, the onProcessSamples virtual function diff --git a/src/SFML/Audio/SoundBufferRecorder.cpp b/src/SFML/Audio/SoundBufferRecorder.cpp index e09c4ffc..4b3ab504 100644 --- a/src/SFML/Audio/SoundBufferRecorder.cpp +++ b/src/SFML/Audio/SoundBufferRecorder.cpp @@ -63,7 +63,7 @@ bool SoundBufferRecorder::onProcessSamples(const Int16* samples, std::size_t sam void SoundBufferRecorder::onStop() { if (!m_samples.empty()) - m_buffer.loadFromSamples(&m_samples[0], m_samples.size(), 1, getSampleRate()); + m_buffer.loadFromSamples(&m_samples[0], m_samples.size(), getChannelCount(), getSampleRate()); } diff --git a/src/SFML/Audio/SoundRecorder.cpp b/src/SFML/Audio/SoundRecorder.cpp index 510495b0..e30e1ed0 100644 --- a/src/SFML/Audio/SoundRecorder.cpp +++ b/src/SFML/Audio/SoundRecorder.cpp @@ -51,7 +51,8 @@ m_thread (&SoundRecorder::record, this), m_sampleRate (0), m_processingInterval(milliseconds(100)), m_isCapturing (false), -m_deviceName (getDefaultDevice()) +m_deviceName (getDefaultDevice()), +m_channelCount (1) { } @@ -86,8 +87,11 @@ bool SoundRecorder::start(unsigned int sampleRate) return false; } - // Open the capture device for capturing 16 bits mono samples - captureDevice = alcCaptureOpenDevice(m_deviceName.c_str(), sampleRate, AL_FORMAT_MONO16, sampleRate); + // Determine the recording format + ALCenum format = (m_channelCount == 1) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16; + + // Open the capture device for capturing 16 bits samples + captureDevice = alcCaptureOpenDevice(m_deviceName.c_str(), sampleRate, format, sampleRate); if (!captureDevice) { err() << "Failed to open the audio capture device with the name: " << m_deviceName << std::endl; @@ -180,8 +184,11 @@ bool SoundRecorder::setDevice(const std::string& name) m_isCapturing = false; m_thread.wait(); - // Open the requested capture device for capturing 16 bits mono samples - captureDevice = alcCaptureOpenDevice(name.c_str(), m_sampleRate, AL_FORMAT_MONO16, m_sampleRate); + // Determine the recording format + ALCenum format = (m_channelCount == 1) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16; + + // Open the requested capture device for capturing 16 bits samples + captureDevice = alcCaptureOpenDevice(name.c_str(), m_sampleRate, format, m_sampleRate); if (!captureDevice) { // Notify derived class @@ -210,6 +217,32 @@ const std::string& SoundRecorder::getDevice() const } +//////////////////////////////////////////////////////////// +void SoundRecorder::setChannelCount(unsigned int channelCount) +{ + if (m_isCapturing) + { + err() << "It's not possible to change the channels while recording." << std::endl; + return; + } + + if (channelCount < 1 || channelCount > 2) + { + err() << "Unsupported channel count: " << channelCount << " Currently only mono (1) and stereo (2) recording is supported." << std::endl; + return; + } + + m_channelCount = channelCount; +} + + +//////////////////////////////////////////////////////////// +unsigned int SoundRecorder::getChannelCount() const +{ + return m_channelCount; +} + + //////////////////////////////////////////////////////////// bool SoundRecorder::isAvailable() { @@ -267,7 +300,7 @@ void SoundRecorder::processCapturedSamples() if (samplesAvailable > 0) { // Get the recorded samples - m_samples.resize(samplesAvailable); + m_samples.resize(samplesAvailable * getChannelCount()); alcCaptureSamples(captureDevice, &m_samples[0], samplesAvailable); // Forward them to the derived class