YARP
Yet Another Robot Platform
audioToFileDevice.cpp
Go to the documentation of this file.
1 /*
2  * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3  * SPDX-License-Identifier: LGPL-2.1-or-later
4  */
5 
6 #include "audioToFileDevice.h"
7 
8 #include <yarp/os/Thread.h>
9 #include <yarp/os/Time.h>
10 #include <yarp/os/Stamp.h>
11 #include <yarp/os/LogComponent.h>
12 #include <yarp/os/LogStream.h>
13 
14 #include <mutex>
15 #include <string>
16 
17 
18 using namespace yarp::os;
19 using namespace yarp::dev;
20 using namespace yarp::sig;
21 
22 namespace {
23 YARP_LOG_COMPONENT(AUDIOTOFILE, "yarp.device.audioToFileDevice")
24 }
25 
27  m_audio_filename("audio_out.wav")
28 {
29 }
30 
32 {
33  close();
34 }
35 
37 {
38  if (config.check("help"))
39  {
40  yCInfo(AUDIOTOFILE, "Some examples:");
41  yCInfo(AUDIOTOFILE, "yarpdev --device audioToFileDevice --help");
42  yCInfo(AUDIOTOFILE, "yarpdev --device AudioPlayerWrapper --subdevice audioToFileDevice --start");
43  yCInfo(AUDIOTOFILE, "yarpdev --device AudioPlayerWrapper --subdevice audioToFileDevice --start --audio_out.wav --save_mode overwrite_file");
44  return false;
45  }
46 
47  bool b = configurePlayerAudioDevice(config.findGroup("AUDIO_BASE"), "audioToFileDevice");
48  if (!b) { return false; }
49 
50  if (config.check("file_name"))
51  {
52  m_audio_filename=config.find("file_name").asString();
53  yCInfo(AUDIOTOFILE) << "Audio will be saved on exit to file:" << m_audio_filename;
54  return true;
55  }
56  else
57  {
58  yCInfo(AUDIOTOFILE) << "No `file_name` option specified. Audio will be saved on exit to default file:" << m_audio_filename;
59  }
60 
61  if (config.find("save_mode").toString() == "overwrite_file") { m_save_mode = save_mode_t::save_overwrite_file;}
62  else if (config.find("save_mode").toString() == "append_data") { m_save_mode = save_mode_t::save_append_data; }
63  else if (config.find("save_mode").toString() == "rename_file") { m_save_mode = save_mode_t::save_rename_file; }
64  else if (config.check("save_mode")) {yError() << "Unsupported value for save_mode parameter"; return false;}
65 
66  if (m_save_mode == save_mode_t::save_overwrite_file) { yCInfo(AUDIOTOFILE) << "overwrite_file mode selected. File will be saved both on exit and on stop"; }
67  else if (m_save_mode == save_mode_t::save_append_data) { yCInfo(AUDIOTOFILE) << "append_data mode selected. File will be saved on exit only"; }
68  else if (m_save_mode == save_mode_t::save_rename_file) { yCInfo(AUDIOTOFILE) << "rename_file mode selected. File will be saved both on exit and on stop"; }
69 
70  return true;
71 }
72 
73 void audioToFileDevice::save_to_file()
74 {
75  //of the buffer is empty, there is nothing to save
76  if (m_sounds.size() == 0) {
77  return;
78  }
79 
80  //we need to set the number of channels and the frequency before calling the
81  //concatenation operator
82  m_audioFile.setFrequency(m_sounds.front().getFrequency());
83  m_audioFile.resize(0, m_sounds.front().getChannels());
84  while (!m_sounds.empty())
85  {
86  m_audioFile += m_sounds.front();
87  m_sounds.pop_front();
88  }
89 
90  //remove the extension .wav from the filename
91  size_t lastindex = m_audio_filename.find_last_of(".");
92  std::string trunc_filename = m_audio_filename.substr(0, lastindex);
93  std::string trunc_extension =".wav";
94  if (lastindex!= std::string::npos)
95  {
96  trunc_extension = m_audio_filename.substr(lastindex, std::string::npos);
97  }
98 
99  if (m_save_mode == save_mode_t::save_rename_file)
100  {
101  trunc_filename = trunc_filename +std::to_string(m_filename_counter++);
102  }
103 
104  std::string complete_filename = trunc_filename + trunc_extension;
105  bool ok = yarp::sig::file::write(m_audioFile, complete_filename.c_str());
106  if (ok)
107  {
108  yCDebug(AUDIOTOFILE) << "Wrote audio to:" << complete_filename;
109  }
110 }
111 
113 {
114  save_to_file();
115  return true;
116 }
117 
119 {
120  std::lock_guard<std::recursive_mutex> lock(m_mutex);
121  yCDebug(AUDIOTOFILE) << "start";
122  m_playback_enabled = true;
123  if (m_save_mode != save_mode_t::save_append_data)
124  {
125  m_sounds.clear();
126  }
127  return true;
128 }
129 
131 {
132  std::lock_guard<std::recursive_mutex> lock(m_mutex);
133  yCDebug(AUDIOTOFILE) << "stop";
134  m_playback_enabled = false;
135  if (m_save_mode != save_mode_t::save_append_data)
136  {
137  save_to_file();
138  }
139  return true;
140 }
141 
143 {
144  std::lock_guard<std::recursive_mutex> lock(m_mutex);
145  if (m_playback_enabled)
146  {
147  m_sounds.push_back(sound);
148  }
149  return true;
150 }
151 
153 {
154  std::lock_guard<std::recursive_mutex> lock(m_mutex);
155  if (gain > 0)
156  {
157  m_hw_gain = gain;
158  return true;
159  }
160  return false;
161 }
162 
164 {
165  yCError(AUDIOTOFILE, "configureDeviceAndStart() Not yet implemented");
166  return true;
167 }
168 
170 {
171  yCError(AUDIOTOFILE, "interruptDeviceAndClose() Not yet implemented");
172  return true;
173 }
174 
176 {
177  yCError(AUDIOTOFILE, "waitUntilPlaybackStreamIsComplete() Not yet implemented");
178  return;
179 }
#define yError(...)
Definition: Log.h:279
bool open(yarp::os::Searchable &config) override
Open the DeviceDriver.
virtual bool renderSound(const yarp::sig::Sound &sound) override
Render a sound using a device (i.e.
virtual bool configureDeviceAndStart() override
virtual bool interruptDeviceAndClose() override
bool close() override
Close the DeviceDriver.
virtual void waitUntilPlaybackStreamIsComplete() override
virtual bool setHWGain(double gain) override
Sets the hardware gain of the playback device (if supported by the hardware)
virtual bool startPlayback() override
Start the playback.
virtual bool stopPlayback() override
Stop the playback.
~audioToFileDevice() override
bool configurePlayerAudioDevice(yarp::os::Searchable &config, std::string device_name)
A base class for nested structures that can be searched.
Definition: Searchable.h:66
virtual Value & find(const std::string &key) const =0
Gets a value corresponding to a given keyword.
virtual bool check(const std::string &key) const =0
Check if there exists a property of the given name.
virtual Bottle & findGroup(const std::string &key) const =0
Gets a list corresponding to a given keyword.
std::string toString() const override
Return a standard text representation of the content of the object.
Definition: Value.cpp:356
virtual std::string asString() const
Get string value.
Definition: Value.cpp:234
Class for storing sounds See Audio in YARP for additional documentation on YARP audio.
Definition: Sound.h:26
void setFrequency(int freq)
Set the frequency of the sound (i.e.
Definition: Sound.cpp:229
void resize(size_t samples, size_t channels=1)
Set the sound size.
Definition: Sound.cpp:168
#define yCInfo(component,...)
Definition: LogComponent.h:132
#define yCError(component,...)
Definition: LogComponent.h:154
#define yCDebug(component,...)
Definition: LogComponent.h:109
#define YARP_LOG_COMPONENT(name,...)
Definition: LogComponent.h:77
std::string to_string(IntegerType x)
Definition: numeric.h:115
An interface for the device drivers.
An interface to the operating system, including Port based communication.
bool write(const ImageOf< PixelRgb > &src, const std::string &dest, image_fileformat format=FORMAT_PPM)
Definition: ImageFile.cpp:1098
Signal processing.
Definition: Image.h:22