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 if (m_dataThread)
72 {
73 delete m_dataThread;
74 m_dataThread = nullptr;
75 }
76 if (m_statusThread)
77 {
78 delete m_statusThread;
79 m_statusThread = nullptr;
80 }
81 return true;
82}
83
85{
86 bool b = m_RPC.read(connection);
87 if (b)
88 {
89 return true;
90 }
91 yCDebug(AUDIORECORDER_NWS_YARP) << "read() Command failed";
92 return false;
93}
94
96{
97 if (driver->isValid())
98 {
99 driver->view(m_mic);
100 }
101
102 if (nullptr == m_mic)
103 {
104 yCError(AUDIORECORDER_NWS_YARP, "Subdevice passed to attach method is invalid");
105 return false;
106 }
107
108 m_RPC.setInterface(m_mic);
109
110 m_dataThread = new AudioRecorderDataThread(this);
111 m_statusThread = new AudioRecorderStatusThread(this);
112 m_dataThread->setPeriod(m_period);
113 m_dataThread->start();
114 m_statusThread->start();
115
116 // Wait a little and then start if requested
117 if (m_start) {
118 yCDebug(AUDIORECORDER_NWS_YARP) << "Auto start requested";
120 m_mic->startRecording();
121 }
122
123 return true;
124}
125
127{
128 if (m_dataThread)
129 {
130 m_dataThread->stop();
131 }
132 if (m_statusThread)
133 {
134 m_statusThread->stop();
135 }
136
137 if (m_mic)
138 {
139 m_mic->stopRecording();
140 m_mic = nullptr;
141 }
142 return true;
143}
144
146{
151
152 if (m_ARW->m_debug_enabled)
153 {
154 static double printer_wdt = yarp::os::Time::now();
155 if (yarp::os::Time::now() - printer_wdt > 1.0)
156 {
157 yCDebug(AUDIORECORDER_NWS_YARP) << device_buffer_current_size.getSamples() << "/" << device_buffer_max_size.getSamples() << "samples";
159 }
160 }
161
162
163 bool isRecording;
164 m_ARW->m_mic->isRecording(isRecording);
165
166 //status port
168 status.enabled = isRecording;
170 status.max_buffer_size = device_buffer_max_size.getSamples();
171 m_ARW->m_statusPort.write(status);
172}
173
175{
176 if (0)
177 {
178 //debug: print the duration of the thread
180 yCDebug(AUDIORECORDER_NWS_YARP) << (current_time - m_ARW->m_debug_last_time);
181 m_ARW->m_debug_last_time = current_time;
182 }
183
184 if (m_ARW->m_mic == nullptr)
185 {
186 yCError(AUDIORECORDER_NWS_YARP) << "The IAudioGrabberSound interface is not available yet!";
187 return;
188 }
189
190#ifdef PRINT_DEBUG_MESSAGES
191 {
194 mic->getRecordingAudioBufferMaxSize(buf_max);
195 mic->getRecordingAudioBufferCurrentSize(buf_cur);
196 yCDebug(AUDIORECORDERWRAPPER) << "BEFORE Buffer status:" << buf_cur.getBytes() << "/" << buf_max.getBytes() << "bytes";
197 }
198#endif
199
200
201 bool isRecording;
202 m_ARW->m_mic->isRecording(isRecording);
203 if (isRecording)
204 {
205 //acquire sound data from attached device
208 if (current_sound.getSamples() < m_ARW->m_min_samples_over_network ||
210 {
211 yCWarning(AUDIORECORDER_NWS_YARP) << "subdevice->getSound() is not producing sounds of the requested size ("
213 << current_sound.getSamples() << "<"
214 << m_ARW->m_max_samples_over_network << ") failed";
215 }
216 #ifdef PRINT_DEBUG_MESSAGES
217 {
220 mic->getRecordingAudioBufferMaxSize(buf_max);
221 mic->getRecordingAudioBufferCurrentSize(buf_cur);
222 yCDebug(AUDIORECORDERWRAPPER) << "AFTER Buffer status:" << buf_cur.getBytes() << "/" << buf_max.getBytes() << "bytes";
223 }
224 #endif
225 #ifdef PRINT_DEBUG_MESSAGES
226 yCDebug(AUDIORECORDERWRAPPER) << "Sound size:" << current_sound.getSamples() * current_sound.getChannels() * current_sound.getBytesPerSample() << " bytes";
228 #endif
229
230 //when recording: accumulate data or send data
231 if (current_sound.getSamples() > 0)
232 {
234 {
235 m_ARW->m_listofsnds.push_back(current_sound);
236 }
237 else
238 {
240 }
241 }
242 }
243 else //when the recording is stopped: send accumulated data all at one
244 {
245 if (m_ARW->m_listofsnds.size()>0)
246 {
247 //create the sound s with the appropriate size
249 s.setFrequency(m_ARW->m_listofsnds.begin()->getFrequency());
250 size_t total_size = 0;
251 for (auto it= m_ARW->m_listofsnds.begin(); it!= m_ARW->m_listofsnds.end(); it++)
252 {
253 total_size += (*it).getSamples();
254 }
255 s.resize(total_size, m_ARW->m_listofsnds.begin()->getChannels());
256
257 //fill the sound s with the sound contained in the list
258 size_t offset = 0;
259 for (auto it = m_ARW->m_listofsnds.begin(); it != m_ARW->m_listofsnds.end(); it++)
260 {
261 s.overwrite(*it,offset);
262 offset+=it->getSamples();
263 }
264 sendSound(s);
265 m_ARW->m_listofsnds.clear();
266 }
267 }
268}
269
271{
272 //check before sending data
273 if (s.getSamples() == 0)
274 {
275 yCError(AUDIORECORDER_NWS_YARP) << "Subdevice produced sound of 0 samples!";
276 return false;
277 }
278 if (s.getChannels() == 0)
279 {
280 yCError(AUDIORECORDER_NWS_YARP) << "Subdevice produced sound of 0 channels!";
281 return false;
282 }
283 if (s.getFrequency() == 0)
284 {
285 yCError(AUDIORECORDER_NWS_YARP) << "Subdevice produced sound with 0 frequency!";
286 return false;
287 }
288
289 //prepare the timestamp
290 m_ARW->m_stamp.update();
291 m_ARW->m_streamingPort.setEnvelope(m_ARW->m_stamp);
292
293 //send data
294 if (m_ARW->m_streamingPort.getOutputCount()>0)
295 {
296 m_ARW->m_streamingPort.write(s);
297 }
298
299 return true;
300}
void run() override
Loop function.
AudioRecorder_nws_yarp * m_ARW
bool sendSound(yarp::sig::Sound &s)
AudioRecorder_nws_yarp * m_ARW
void run() override
Loop function.
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 bool getSound(yarp::sig::Sound &sound, size_t min_number_of_samples, size_t max_number_of_samples, double max_samples_timeout_s)=0
Get a sound from a device.
virtual bool getRecordingAudioBufferCurrentSize(yarp::sig::AudioBufferSize &size)=0
virtual bool getRecordingAudioBufferMaxSize(yarp::sig::AudioBufferSize &size)=0
virtual bool stopRecording()=0
Stop the recording.
virtual bool startRecording()=0
Start the recording.
virtual bool isRecording(bool &recording_enabled)=0
Check if the recording has been enabled (e.g.
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.
An interface for reading from a network connection.
bool setPeriod(double period)
Set the (new) period of the thread.
bool start()
Call this to start the thread.
void stop()
Call this to stop the thread, this call blocks until the thread is terminated (and releaseThread() ca...
int getOutputCount() override
Determine how many output connections this port has.
Definition Port.cpp:567
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
bool setEnvelope(PortWriter &envelope) override
Set an envelope (e.g., a timestamp) to the next message which will be sent.
Definition Port.cpp:547
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
#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.
Definition jointData.cpp:13
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.