YARP
Yet Another Robot Platform
 
Loading...
Searching...
No Matches
AudioRecorderDeviceBase.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5
7#include <yarp/os/LogStream.h>
8#include <mutex>
9#include <limits>
10#include <functional>
11
12using namespace yarp::os;
13using namespace yarp::dev;
14using namespace yarp::sig;
15
16constexpr double c_sleep_time=0.005;
17
18YARP_LOG_COMPONENT(AUDIORECORDER_BASE, "yarp.devices.AudioRecorderDeviceBase")
19
20//the following macros should never be modified and are used only for development purposes
21#define AUTOMATIC_REC_START 0
22#define DEBUG_TIME_SPENT 0
23
24//Default device parameters
25#define DEFAULT_SAMPLE_RATE (44100)
26#define DEFAULT_NUM_CHANNELS (2)
27#define DEFAULT_SAMPLE_SIZE (2)
28
29ReturnValue AudioRecorderDeviceBase::getSound(yarp::sig::Sound& sound, size_t min_number_of_samples, size_t max_number_of_samples, double max_samples_timeout_s)
30{
31 //check for something_to_record
32 {
33 #if AUTOMATIC_REC_START
34 if (m_isRecording == false)
35 {
36 this->startRecording();
37 }
38 #else
40 while (m_recording_enabled == false)
41 {
42 if (yarp::os::Time::now() - debug_time > 5.0)
43 {
44 yCInfo(AUDIORECORDER_BASE) << "getSound() is currently waiting. Use startRecording() to start the audio stream";
46 }
48 }
49 #endif
50 }
51
52 //prevents simultaneous start/stop/reset etc.
53 //std::lock_guard<std::mutex> lock(m_mutex); //This must be used carefully
54
55 //check on input parameters
56 if (max_number_of_samples < min_number_of_samples)
57 {
58 yCError(AUDIORECORDER_BASE) << "max_number_of_samples must be greater than min_number_of_samples!";
60 }
61 if (max_number_of_samples > this->m_audiorecorder_cfg.numSamples)
62 {
63 yCWarning(AUDIORECORDER_BASE) << "max_number_of_samples ("<< max_number_of_samples <<") is bigger than the internal audio buffer! It will be truncated to:" << this->m_audiorecorder_cfg.numSamples;
64 max_number_of_samples = this->m_audiorecorder_cfg.numSamples;
65 }
66
67 //wait until the desired number of samples are obtained
68 size_t buff_size = 0;
71 do
72 {
74 if (buff_size >= max_number_of_samples) { break; }
75 if (buff_size >= min_number_of_samples && yarp::os::Time::now() - start_time > max_samples_timeout_s) { break; }
76 if (m_recording_enabled == false) { break; }
77
78 if (yarp::os::Time::now() - debug_time > 1.0)
79 {
81 yCDebug(AUDIORECORDER_BASE) << "getSound() Buffer size is " << buff_size << "/" << max_number_of_samples << " after 1s";
82 }
84 } while (true);
85
86 //prepare the sound data struct
88 if (samples_to_be_copied > max_number_of_samples) {
89 samples_to_be_copied = max_number_of_samples;
90 }
91 if (sound.getChannels() != this->m_audiorecorder_cfg.numChannels || sound.getSamples() != samples_to_be_copied)
92 {
94 }
96
97 //fill the sound data struct, reading samples from the circular buffer
98 #if DEBUG_TIME_SPENT
99 double ct1 = yarp::os::Time::now();
100 #endif
101 for (size_t i = 0; i < samples_to_be_copied; i++)
102 {
103 for (size_t j = 0; j < this->m_audiorecorder_cfg.numChannels; j++)
104 {
106 if (s > (std::numeric_limits<int16_t>::max() - m_cliptol) ||
107 s < (std::numeric_limits<int16_t>::min() + m_cliptol))
108 {
109 yCWarningThrottle(AUDIORECORDER_BASE, 0.1) << "Sound clipped!";
110 }
111 sound.set(s, i, j);
112 }
113 }
114
115 //amplify if required
116 if (m_sw_gain!=1.0) {sound.amplify(m_sw_gain);}
117
118 auto debug_p = sound.getInterleavedAudioRawData();
119 #if DEBUG_TIME_SPENT
120 double ct2 = yarp::os::Time::now();
122 #endif
123 return ReturnValue_ok;
124}
125
127{
128 if (m_inputBuffer == nullptr)
129 {
130 yCError(AUDIORECORDER_BASE) << "getRecordingAudioBufferMaxSize() called, but no audio buffer is allocated yet";
132 }
133 //no lock guard is needed here
134 size = this->m_inputBuffer->getMaxSize();
135 return ReturnValue_ok;
136}
137
138
140{
141 if (m_inputBuffer == nullptr)
142 {
143 yCError(AUDIORECORDER_BASE) << "getRecordingAudioBufferCurrentSize() called, but no audio buffer is allocated yet";
145 }
146 //no lock guard is needed here
147 size = this->m_inputBuffer->size();
148 return ReturnValue_ok;
149}
150
152{
153 std::lock_guard<std::mutex> lock(m_mutex);
154 if (gain > 0)
155 {
156 m_sw_gain = gain;
157 return ReturnValue_ok;
158 }
159 //negative gain
161}
162
164{
165 if (m_inputBuffer == nullptr)
166 {
167 yCError(AUDIORECORDER_BASE) << "resetRecordingAudioBuffer() called, but no audio buffer is allocated yet";
169 }
170 std::lock_guard<std::mutex> lock(m_mutex);
172 yCDebug(AUDIORECORDER_BASE) << "resetRecordingAudioBuffer";
173 return ReturnValue_ok;
174}
175
177{
178 std::lock_guard<std::mutex> lock(m_mutex);
179 m_recording_enabled = true;
181 {
182 this->m_inputBuffer->clear();
183 }
184 yCInfo(AUDIORECORDER_BASE) << "Recording started";
185 return ReturnValue_ok;
186}
187
189{
190 std::lock_guard<std::mutex> lock(m_mutex);
191 m_recording_enabled = false;
193 {
194 //In this case we do not want to clear the because we want to transmit the last sound frame
195 //which has been partially captured until the stopRecording has been called.
196 //this->m_inputBuffer->clear();
197 }
198 yCInfo(AUDIORECORDER_BASE) << "Recording stopped";
199 return ReturnValue_ok;
200}
201
207
209{
210 if (m_inputBuffer != nullptr)
211 {
212 delete m_inputBuffer;
213 m_inputBuffer = nullptr;
214 }
215}
216
218{
219 std::string debug_cfg_string = config.toString();
220
221 m_audiorecorder_cfg.frequency = config.check("rate", Value(0), "audio sample rate (0=automatic)").asInt32();
222 m_audiorecorder_cfg.numSamples = config.check("samples", Value(0), "number of samples per network packet (0=automatic). For chunks of 1 second of recording set samples=rate. Channels number is handled internally.").asInt32();
223 m_audiorecorder_cfg.numChannels = config.check("channels", Value(0), "number of audio channels (0=automatic, max is 2)").asInt32();
224 m_hw_gain = config.check("hw_gain", Value(1.0), "HW gain").asFloat32();
225 m_sw_gain = config.check("sw_gain", Value(1.0), "SW gain").asFloat32();
226
229 }
232 }
234 m_audiorecorder_cfg.numSamples = m_audiorecorder_cfg.frequency; // by default let's use chunks of 1 second
235 }
236
237 yCInfo(AUDIORECORDER_BASE) << "Device configured with the following options:";
239 yCInfo(AUDIORECORDER_BASE) << "Samples (buffer size):"<< m_audiorecorder_cfg.numSamples;
242 yCInfo(AUDIORECORDER_BASE) << "HW gain:" << m_hw_gain;
243 yCInfo(AUDIORECORDER_BASE) << "SW gain:" << m_sw_gain;
244
246 if (m_inputBuffer == nullptr)
247 {
249 }
250
251 //additional options
252 m_enable_buffer_autoclear = config.check("buffer_autoclear", Value(true), "Automatically clear the buffer every time the devices is started/stopped").asBool();
253 m_audiobase_debug = config.check("debug", Value(false), "Enable debug mode").asBool();
254
255 return true;
256}
#define DEFAULT_NUM_CHANNELS
#define DEFAULT_SAMPLE_RATE
constexpr double c_sleep_time
const yarp::os::LogComponent & AUDIORECORDER_BASE()
constexpr double c_sleep_time
#define ReturnValue_ok
Definition ReturnValue.h:77
yarp::dev::CircularAudioBuffer_16t * m_inputBuffer
virtual yarp::dev::ReturnValue resetRecordingAudioBuffer() override
virtual yarp::dev::ReturnValue getRecordingAudioBufferCurrentSize(yarp::sig::AudioBufferSize &size) override
virtual yarp::dev::ReturnValue getRecordingAudioBufferMaxSize(yarp::sig::AudioBufferSize &size) override
virtual yarp::dev::ReturnValue startRecording() override
Start the recording.
virtual yarp::dev::ReturnValue setSWGain(double gain) override
Sets a software gain for the grabbed audio.
virtual yarp::dev::ReturnValue stopRecording() override
Stop the recording.
virtual yarp::dev::ReturnValue getSound(yarp::sig::Sound &sound, size_t min_number_of_samples, size_t max_number_of_samples, double max_samples_timeout_s) override
Get a sound from a device.
bool configureRecorderAudioDevice(yarp::os::Searchable &config, std::string device_name)
AudioDeviceDriverSettings m_audiorecorder_cfg
virtual yarp::dev::ReturnValue isRecording(bool &recording_enabled) override
Check if the recording has been enabled (e.g.
yarp::sig::AudioBufferSize size()
yarp::sig::AudioBufferSize getMaxSize()
@ return_value_error_not_ready
Method failed due to invalid internal status/invalid request.
@ return_value_error_method_failed
Method is deprecated.
A mini-server for performing network communication in the background.
A base class for nested structures that can be searched.
Definition Searchable.h:31
virtual bool check(const std::string &key) const =0
Check if there exists a property of the given name.
virtual std::string toString() const =0
Return a standard text representation of the content of the object.
static void delaySystem(double seconds)
A single value (typically within a Bottle).
Definition Value.h:43
Class for storing sounds See Audio in YARP for additional documentation on YARP audio.
Definition Sound.h:25
void setFrequency(int freq)
Set the frequency of the sound (i.e.
Definition Sound.cpp:361
std::vector< std::reference_wrapper< audio_sample > > getInterleavedAudioRawData() const
Returns a serialized version of the sound, in interleaved format, e.g.
Definition Sound.cpp:539
size_t getChannels() const
Get the number of channels of the sound.
Definition Sound.cpp:603
void amplify(double gain)
amplify a sound
Definition Sound.cpp:645
void resize(size_t samples, size_t channels=1)
Set the sound size.
Definition Sound.cpp:270
void set(audio_sample value, size_t sample, size_t channel=0)
Definition Sound.cpp:334
size_t getSamples() const
Get the number of samples contained in the sound.
Definition Sound.cpp:598
#define yCInfo(component,...)
#define yCError(component,...)
#define yCWarning(component,...)
#define yCDebug(component,...)
#define YARP_LOG_COMPONENT(name,...)
#define yCWarningThrottle(component, period,...)
For streams capable of holding different kinds of content, check what they actually have.
yarp::dev::CircularAudioBuffer< unsigned short int > CircularAudioBuffer_16t
double now()
Return the current time in seconds, relative to an arbitrary starting point.
Definition Time.cpp:121
An interface to the operating system, including Port based communication.