YARP
Yet Another Robot Platform
fakeMicrophone.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 
6 #include "fakeMicrophone.h"
7 
8 #include <yarp/os/Thread.h>
9 #include <yarp/os/Time.h>
10 #include <yarp/os/Semaphore.h>
11 #include <yarp/os/Stamp.h>
12 #include <yarp/os/LogComponent.h>
13 #include <yarp/os/LogStream.h>
14 
15 #include <mutex>
16 #define _USE_MATH_DEFINES
17 #include <math.h>
18 #include <string>
19 
20 
21 using namespace yarp::os;
22 using namespace yarp::dev;
23 using namespace yarp::sig;
24 
25 constexpr double c_DEFAULT_PERIOD=0.01; //s
26 
27 namespace {
28 YARP_LOG_COMPONENT(FAKEMICROPHONE, "yarp.device.fakeMicrophone")
29 }
30 
31 typedef unsigned short int audio_sample_16t;
32 
35 {
36 }
37 
39 {
40  close();
41 }
42 
44 {
45  if (config.check("help"))
46  {
47  yCInfo(FAKEMICROPHONE, "Some examples:");
48  yCInfo(FAKEMICROPHONE, "yarpdev --device fakeMicrophone --help");
49  yCInfo(FAKEMICROPHONE, "yarpdev --device AudioRecorderWrapper --subdevice fakeMicrophone --start");
50  yCInfo(FAKEMICROPHONE, "yarpdev --device AudioRecorderWrapper --subdevice fakeMicrophone --start --signal_frequency 400 --waveform sine");
51  yCInfo(FAKEMICROPHONE, "yarpdev --device AudioRecorderWrapper --subdevice fakeMicrophone --start --signal_frequency 400 --waveform sawtooth");
52  yCInfo(FAKEMICROPHONE, "yarpdev --device AudioRecorderWrapper --subdevice fakeMicrophone --start --signal_frequency 400 --waveform square");
53  yCInfo(FAKEMICROPHONE, "yarpdev --device AudioRecorderWrapper --subdevice fakeMicrophone --start --waveform constant");
54  return false;
55  }
56 
57  bool b = configureRecorderAudioDevice(config.findGroup("AUDIO_BASE"), "fakeMicrophone");
58  if (!b) { return false; }
59 
60  //sets the thread period
61  if(config.check("period"))
62  {
63  double period = config.find("period").asFloat64();
64  setPeriod(period);
65  yCInfo(FAKEMICROPHONE) << "Using chosen period of " << period << " s";
66  }
67  else
68  {
69  yCInfo(FAKEMICROPHONE) << "Using default period of " << c_DEFAULT_PERIOD << " s";
70  }
71 
72  if (config.check("signal_frequency"))
73  {
74  m_sig_freq = config.find("signal_frequency").asInt32();
75  }
76 
77  if (config.check("amplitude"))
78  {
79  m_wave_amplitude = config.find("amplitude").asInt32();
80  }
81 
82  //sets the number of samples processed atomically every thread iteration
83  if (config.check("driver_frame_size"))
84  {
85  m_samples_to_be_copied = config.find("driver_frame_size").asFloat64();
86  }
87  yCDebug(FAKEMICROPHONE) << m_samples_to_be_copied << " will be processed every iteration";
88 
89  if (config.check("waveform"))
90  {
91  std::string waveform = config.find("waveform").asString();
92  if (config.find("waveform").toString() == "sine") { m_waveform = waveform_t::sine; }
93  else if (config.find("waveform").toString() == "sawtooth") { m_waveform = waveform_t::sawtooth; }
94  else if (config.find("waveform").toString() == "square") { m_waveform = waveform_t::square; }
95  else if (config.find("waveform").toString() == "constant") { m_waveform = waveform_t::constant; }
96  else if (config.check("waveform")) { yError() << "Unsupported value for waveform parameter"; return false; }
97 
98  if (m_waveform == waveform_t::sine) { yCInfo(FAKEMICROPHONE) << "Using sine waveform, signal amplitude=" << m_wave_amplitude << ", signal frequency=" << m_sig_freq; }
99  else if (m_waveform == waveform_t::sawtooth) { yCInfo(FAKEMICROPHONE) << "Using sawtooth waveform, signal amplitude=" << m_wave_amplitude << ", signal frequency=" << m_sig_freq; }
100  else if (m_waveform == waveform_t::square) { yCInfo(FAKEMICROPHONE) << "Using square waveform, signal amplitude=" << m_wave_amplitude << ", signal frequency=" << m_sig_freq; }
101  else if (m_waveform == waveform_t::constant) { yCInfo(FAKEMICROPHONE) << "Using constant waveform, signal amplitude="<< m_wave_amplitude << ", signal frequency=" << m_sig_freq; }
102  }
103 
104  //data structure initialization
105  //m_audiorecorder_cfg.numSamples = tmp_freq * 5; //5sec
106  //const size_t EXTRA_SPACE = 2;
107  //AudioBufferSize buffer_size(m_audiorecorder_cfg.numSamples*EXTRA_SPACE, m_audiorecorder_cfg.numChannels, m_audiorecorder_cfg.bytesPerSample);
108  //m_inputBuffer = new yarp::dev::CircularAudioBuffer_16t("fake_mic_buffer", buffer_size);
109 
110  m_max_count.resize(m_audiorecorder_cfg.numChannels);
111  m_counter.resize(m_audiorecorder_cfg.numChannels);
112 
113  //start the capture thread
114  start();
115  return true;
116 }
117 
119 {
121 
122  //wait until the thread is stopped...
123 
124  return true;
125 }
126 
127 bool fakeMicrophone::setHWGain(double gain)
128 {
129  std::lock_guard<std::mutex> lock(m_mutex);
130  if (gain > 0)
131  {
132  m_hw_gain = gain;
133  return true;
134  }
135  return false;
136 }
137 
138 bool fakeMicrophone::threadInit()
139 {
140  return true;
141 }
142 
143 
144 void fakeMicrophone::run()
145 {
146  // when not recording, do nothing
147  if (!m_recording_enabled)
148  {
149  return;
150  }
151 
152  //fill the buffer with a generated tone.
153  //each iteration, which occurs every xxx ms (thread period), I copy a fixed amount of
154  //samples (m_samples_to_be_copied) in the buffer. This operation cannot be interrupted by stopping the device
155  //with m_recording_enabled=false.
156  for (size_t i = 0; i < m_samples_to_be_copied; i++)
157  {
158  // Default values:
159  // this signal has amplitude (-32000,32000)
160  // the first channel has frequency 440Hz (A4 note)
161  // the second channel has frequency 220Hz etc.
162  // and so on..
163  if (m_waveform == waveform_t::sine)
164  {
165  for (size_t i = 0; i < m_audiorecorder_cfg.numChannels; i++)
166  {
167  m_max_count[i] = double(m_audiorecorder_cfg.frequency) / m_sig_freq / double(i + 1);
168  double elem1 = double(m_wave_amplitude * sin(double(m_counter[i]) / m_max_count[i] * 2 * M_PI));
169  m_inputBuffer->write(elem1 * m_hw_gain);
170  m_counter[i]++;
171  if (m_counter[i] >= m_max_count[i]) {
172  m_counter[i] = 0;
173  }
174  }
175  }
176  else if(m_waveform == waveform_t::sawtooth)
177  {
178  for (size_t i = 0; i < m_audiorecorder_cfg.numChannels; i++)
179  {
180  m_max_count[i] = double(m_audiorecorder_cfg.frequency) / m_sig_freq / double(i + 1);
181  double elem1 = m_wave_amplitude * 2 * (double(m_counter[i])/ m_max_count[i]) - m_wave_amplitude;
182  m_inputBuffer->write(elem1 * m_hw_gain);
183  m_counter[i]++;
184  if (m_counter[i] >= m_max_count[i]) {
185  m_counter[i] = 0;
186  }
187  }
188  }
189  else if (m_waveform == waveform_t::square)
190  {
191  for (size_t i = 0; i < m_audiorecorder_cfg.numChannels; i++)
192  {
193  m_max_count[i] = double(m_audiorecorder_cfg.frequency) / m_sig_freq / double(i + 1);
194  double elem1 = m_counter[i] < m_max_count[i]/2 ? m_wave_amplitude : 0;
195  m_inputBuffer->write(elem1 * m_hw_gain);
196  m_counter[i]++;
197  if (m_counter[i] >= m_max_count[i]) {
198  m_counter[i] = 0;
199  }
200  }
201  }
202  else if (m_waveform == waveform_t::constant)
203  {
204  for (size_t i = 0; i < m_audiorecorder_cfg.numChannels; i++)
205  {
206  m_inputBuffer->write(m_wave_amplitude * m_hw_gain / double(i + 1));
207  m_counter[i]++;
208  if (m_counter[i] >= m_max_count[i]) {
209  m_counter[i] = 0;
210  }
211  }
212  }
213  else
214  {
215  yCInfo(FAKEMICROPHONE) << "Not implemented/unreachable code";
216  }
217  }
218 }
#define yError(...)
Definition: Log.h:279
bool setHWGain(double gain) override
Sets the hardware gain of the grabbing device (if supported by the hardware)
bool close() override
Close the DeviceDriver.
bool open(yarp::os::Searchable &config) override
Open the DeviceDriver.
~fakeMicrophone() override
yarp::dev::CircularAudioBuffer_16t * m_inputBuffer
bool configureRecorderAudioDevice(yarp::os::Searchable &config, std::string device_name)
AudioDeviceDriverSettings m_audiorecorder_cfg
An abstraction for a periodic thread.
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...
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.
virtual yarp::conf::float64_t asFloat64() const
Get 64-bit floating point value.
Definition: Value.cpp:222
virtual std::int32_t asInt32() const
Get 32-bit integer value.
Definition: Value.cpp:204
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
#define M_PI
constexpr double c_DEFAULT_PERIOD
unsigned short int audio_sample_16t
#define yCInfo(component,...)
Definition: LogComponent.h:132
#define yCDebug(component,...)
Definition: LogComponent.h:109
#define YARP_LOG_COMPONENT(name,...)
Definition: LogComponent.h:77
An interface for the device drivers.
An interface to the operating system, including Port based communication.
Signal processing.
Definition: Image.h:22