YARP
Yet Another Robot Platform
 
Loading...
Searching...
No Matches
AudioRecorder_nws_yarp.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2023-2023 Istituto Italiano di Tecnologia (IIT)
3 * SPDX-License-Identifier: LGPL-2.1-or-later
4 */
5
7#include <yarp/os/LogStream.h>
9
10using namespace yarp::dev;
11using namespace yarp::os;
12
13namespace {
14YARP_LOG_COMPONENT(AUDIORECORDER_NWS_YARP, "yarp.device.audioRecorder_nws_yarp")
15}
16
17
22
27
29{
30 if (!this->parseParams(config)) { return false; }
31
32 //just info
33 yCDebug(AUDIORECORDER_NWS_YARP) << "Wrapper configured to produce packets with the following size (in samples): " <<
35 yCDebug(AUDIORECORDER_NWS_YARP) << "Wrapper configured with max_samples_timeout: " << m_getSound_timeout << "s";
36
37 // Set the streaming port
38 std::string portname = m_name;
39 if (m_streamingPort.open(portname + "/audio:o") == false)
40 {
41 yCError(AUDIORECORDER_NWS_YARP) << "Unable to open port" << portname + "/audio:o";
42 return false;
43 }
44 if (m_statusPort.open(portname + "/status:o") == false)
45 {
46 yCError(AUDIORECORDER_NWS_YARP) << "Unable to open port" << portname + "/status:o";
47 return false;
48 }
49 // Set the RPC port
50 if (m_rpcPort.open(portname + "/rpc") == false)
51 {
52 yCError(AUDIORECORDER_NWS_YARP) << "Unable to open port" << portname + "/rpc";
53 return false;
54 }
55 m_rpcPort.setReader(*this);
56
57 return true;
58}
59
61{
62 detach();
63
64 m_streamingPort.interrupt();
65 m_streamingPort.close();
66 m_rpcPort.interrupt();
67 m_rpcPort.close();
68 m_statusPort.interrupt();
69 m_statusPort.close();
70
71 return true;
72}
73
75{
76 bool b = m_RPC.read(connection);
77 if (b)
78 {
79 return true;
80 }
81 yCDebug(AUDIORECORDER_NWS_YARP) << "read() Command failed";
82 return false;
83}
84
86{
87 if (driver->isValid())
88 {
89 driver->view(m_mic);
90 }
91
92 if (nullptr == m_mic)
93 {
94 yCError(AUDIORECORDER_NWS_YARP, "Subdevice passed to attach method is invalid");
95 return false;
96 }
97
98 m_RPC.setInterface(m_mic);
99
100 m_dataThread = std::make_unique<AudioRecorderDataThread>(this);
101 m_statusThread = std::make_unique<AudioRecorderStatusThread>(this);
102 m_dataThread->setPeriod(m_period);
103 m_dataThread->start();
104 m_statusThread->start();
105
106 // Wait a little and then start if requested
107 if (m_start) {
108 yCDebug(AUDIORECORDER_NWS_YARP) << "Auto start requested";
110 m_mic->startRecording();
111 }
112
113 return true;
114}
115
117{
118 if (m_dataThread)
119 {
120 m_dataThread->stop();
121 }
122 if (m_statusThread)
123 {
124 m_statusThread->stop();
125 }
126
127 if (m_mic)
128 {
129 m_mic->stopRecording();
130 m_mic = nullptr;
131 }
132 return true;
133}
134
136{
141
142 if (m_ARW->m_debug_enabled)
143 {
144 static double printer_wdt = yarp::os::Time::now();
145 if (yarp::os::Time::now() - printer_wdt > 1.0)
146 {
147 yCDebug(AUDIORECORDER_NWS_YARP) << device_buffer_current_size.getSamples() << "/" << device_buffer_max_size.getSamples() << "samples";
149 }
150 }
151
152
153 bool isRecording;
154 m_ARW->m_mic->isRecording(isRecording);
155
156 //status port
158 status.enabled = isRecording;
160 status.max_buffer_size = device_buffer_max_size.getSamples();
161 m_ARW->m_statusPort.write(status);
162}
163
165{
166 if (0)
167 {
168 //debug: print the duration of the thread
170 yCDebug(AUDIORECORDER_NWS_YARP) << (current_time - m_ARW->m_debug_last_time);
171 m_ARW->m_debug_last_time = current_time;
172 }
173
174 if (m_ARW->m_mic == nullptr)
175 {
176 yCError(AUDIORECORDER_NWS_YARP) << "The IAudioGrabberSound interface is not available yet!";
177 return;
178 }
179
180#ifdef PRINT_DEBUG_MESSAGES
181 {
184 mic->getRecordingAudioBufferMaxSize(buf_max);
185 mic->getRecordingAudioBufferCurrentSize(buf_cur);
186 yCDebug(AUDIORECORDERWRAPPER) << "BEFORE Buffer status:" << buf_cur.getBytes() << "/" << buf_max.getBytes() << "bytes";
187 }
188#endif
189
190
191 bool isRecording;
192 m_ARW->m_mic->isRecording(isRecording);
193 if (isRecording)
194 {
195 //acquire sound data from attached device
197 m_ARW->m_mic->getSound(current_sound, m_ARW->m_min_samples_over_network, m_ARW->m_max_samples_over_network, m_ARW->m_getSound_timeout);
198 if (current_sound.getSamples() < m_ARW->m_min_samples_over_network ||
199 current_sound.getSamples() > m_ARW->m_max_samples_over_network)
200 {
201 yCWarning(AUDIORECORDER_NWS_YARP) << "subdevice->getSound() is not producing sounds of the requested size ("
202 << m_ARW->m_min_samples_over_network << "<"
203 << current_sound.getSamples() << "<"
204 << m_ARW->m_max_samples_over_network << ") failed";
205 }
206 #ifdef PRINT_DEBUG_MESSAGES
207 {
210 mic->getRecordingAudioBufferMaxSize(buf_max);
211 mic->getRecordingAudioBufferCurrentSize(buf_cur);
212 yCDebug(AUDIORECORDERWRAPPER) << "AFTER Buffer status:" << buf_cur.getBytes() << "/" << buf_max.getBytes() << "bytes";
213 }
214 #endif
215 #ifdef PRINT_DEBUG_MESSAGES
216 yCDebug(AUDIORECORDERWRAPPER) << "Sound size:" << current_sound.getSamples() * current_sound.getChannels() * current_sound.getBytesPerSample() << " bytes";
218 #endif
219
220 //when recording: accumulate data or send data
221 if (current_sound.getSamples() > 0)
222 {
223 if (m_ARW->m_send_sound_on_stop)
224 {
225 m_ARW->m_listofsnds.push_back(current_sound);
226 }
227 else
228 {
229 sendSound(current_sound);
230 }
231 }
232 }
233 else //when the recording is stopped: send accumulated data all at one
234 {
235 if (m_ARW->m_listofsnds.size()>0)
236 {
237 //create the sound s with the appropriate size
239 s.setFrequency(m_ARW->m_listofsnds.begin()->getFrequency());
240 size_t total_size = 0;
241 for (auto it= m_ARW->m_listofsnds.begin(); it!= m_ARW->m_listofsnds.end(); it++)
242 {
243 total_size += (*it).getSamples();
244 }
245 s.resize(total_size, m_ARW->m_listofsnds.begin()->getChannels());
246
247 //fill the sound s with the sound contained in the list
248 size_t offset = 0;
249 for (auto it = m_ARW->m_listofsnds.begin(); it != m_ARW->m_listofsnds.end(); it++)
250 {
251 s.overwrite(*it,offset);
252 offset+=it->getSamples();
253 }
254 sendSound(s);
255 m_ARW->m_listofsnds.clear();
256 }
257 }
258}
259
261{
262 //check before sending data
263 if (s.getSamples() == 0)
264 {
265 yCError(AUDIORECORDER_NWS_YARP) << "Subdevice produced sound of 0 samples!";
266 return false;
267 }
268 if (s.getChannels() == 0)
269 {
270 yCError(AUDIORECORDER_NWS_YARP) << "Subdevice produced sound of 0 channels!";
271 return false;
272 }
273 if (s.getFrequency() == 0)
274 {
275 yCError(AUDIORECORDER_NWS_YARP) << "Subdevice produced sound with 0 frequency!";
276 return false;
277 }
278
279 //prepare the timestamp
280 m_ARW->m_stamp.update();
281 m_ARW->m_streamingPort.setEnvelope(m_ARW->m_stamp);
282
283 //send data
284 if (m_ARW->m_streamingPort.getOutputCount()>0)
285 {
286 m_ARW->m_streamingPort.write(s);
287 }
288
289 return true;
290}
bool parseParams(const yarp::os::Searchable &config) override
Parse the DeviceDriver parameters.
bool close() override
Close the DeviceDriver.
bool detach() override
Detach the object (you must have first called attach).
bool attach(yarp::dev::PolyDriver *driver) override
Attach to another object.
bool read(yarp::os::ConnectionReader &connection) override
Read this object from a network connection.
bool open(yarp::os::Searchable &config) override
Open the DeviceDriver.
bool read(yarp::os::ConnectionReader &connection) override
Read this object from a network connection.
void setInterface(yarp::dev::IAudioGrabberSound *_iaudiograb)
bool view(T *&x)
Get an interface to the device driver.
virtual yarp::dev::ReturnValue getRecordingAudioBufferCurrentSize(yarp::sig::AudioBufferSize &size)=0
virtual yarp::dev::ReturnValue stopRecording()=0
Stop the recording.
virtual yarp::dev::ReturnValue isRecording(bool &recording_enabled)=0
Check if the recording has been enabled (e.g.
virtual yarp::dev::ReturnValue startRecording()=0
Start the recording.
virtual yarp::dev::ReturnValue getRecordingAudioBufferMaxSize(yarp::sig::AudioBufferSize &size)=0
A container for a device driver.
Definition PolyDriver.h:23
bool isValid() const
Check if device is valid.
A mini-server for performing network communication in the background.
bool setEnvelope(PortWriter &envelope) override
Set an envelope (e.g., a timestamp) to the next message which will be sent.
void write(bool forceStrict=false)
Write the current object being returned by BufferedPort::prepare.
An interface for reading from a network connection.
bool write(const PortWriter &writer, const PortWriter *callback=nullptr) const override
Write an object to the port.
Definition Port.cpp:436
void setReader(PortReader &reader) override
Set an external reader for port data.
Definition Port.cpp:511
void interrupt() override
Interrupt any current reads or writes attached to the port.
Definition Port.cpp:383
void close() override
Stop port activity.
Definition Port.cpp:363
bool open(const std::string &name) override
Start port operation, with a specific name, with automatically-chosen network parameters.
Definition Port.cpp:79
A base class for nested structures that can be searched.
Definition Searchable.h:31
void update()
Set the timestamp to the current time, and increment the sequence number (wrapping to 0 if the sequen...
Definition Stamp.cpp:124
static void delaySystem(double seconds)
AudioRecorderStatus: A class used to describe the status of an audio recorder device.
size_t current_buffer_size
the size of the audio buffer [samples]
size_t max_buffer_size
the max_size of the audio buffer [samples]
bool enabled
true if the playback is currently enabled
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
size_t getChannels() const
Get the number of channels of the sound.
Definition Sound.cpp:603
void resize(size_t samples, size_t channels=1)
Set the sound size.
Definition Sound.cpp:270
int getFrequency() const
Get the frequency of the sound (i.e.
Definition Sound.cpp:356
void overwrite(const Sound &alt, size_t offset=0, size_t len=0)
It overwrites the sound with another sound, starting from a specified offset.
Definition Sound.cpp:87
size_t getSamples() const
Get the number of samples contained in the sound.
Definition Sound.cpp:598
std::string current_time()
Definition utils.h:24
#define yCError(component,...)
#define yCWarning(component,...)
#define yCDebug(component,...)
#define YARP_LOG_COMPONENT(name,...)
For streams capable of holding different kinds of content, check what they actually have.
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.