YARP
Yet Another Robot Platform
audioFromFileDevice.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 "audioFromFileDevice.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 #include <string>
17 
18 
19 using namespace yarp::os;
20 using namespace yarp::dev;
21 using namespace yarp::sig;
22 
23 constexpr double c_DEFAULT_PERIOD=0.01; //s
24 
25 namespace {
26 YARP_LOG_COMPONENT(AUDIOFROMFILE, "yarp.device.audioFromFileDevice")
27 }
28 
29 typedef unsigned short int audio_sample_16t;
30 
33 {
34 }
35 
37 {
38  delete m_inputBuffer;
39 }
40 
42 {
43  yCInfo(AUDIOFROMFILE) << "Not yet implemented";
44  return false;
45 }
46 
48 {
49  if (config.check("help"))
50  {
51  yCInfo(AUDIOFROMFILE, "Some examples:");
52  yCInfo(AUDIOFROMFILE, "yarpdev --device audioFromFileDevice --help");
53  yCInfo(AUDIOFROMFILE, "yarpdev --device AudioRecorderWrapper --subdevice audioFromFileDevice --start");
54  yCInfo(AUDIOFROMFILE, "yarpdev --device AudioRecorderWrapper --subdevice audioFromFileDevice --start --file_name myaudio.wav");
55  return false;
56  }
57 
58  bool b = configureRecorderAudioDevice(config.findGroup("AUDIO_BASE"), "audioFromFileDevice");
59  if (!b) { return false; }
60 
61  //sets the thread period
62  if(config.check("period"))
63  {
64  double period = config.find("period").asFloat64();
65  setPeriod(period);
66  yCInfo(AUDIOFROMFILE) << "Using chosen period of " << period << " s";
67  }
68  else
69  {
70  yCInfo(AUDIOFROMFILE) << "Using default period of " << c_DEFAULT_PERIOD << " s";
71  }
72 
73  //sets the number of samples processed atomically every thread iteration
74  if (config.check("driver_frame_size"))
75  {
76  m_samples_to_be_copied = config.find("driver_frame_size").asFloat64();
77  }
78  yCDebug(AUDIOFROMFILE) << m_samples_to_be_copied << " will be processed every iteration";
79 
80  //sets the filename
81  if (config.check("file_name"))
82  {
83  m_audio_filename = config.find("file_name").asString();
84  yCInfo(AUDIOFROMFILE) << "Audio will loaded from file:" << m_audio_filename;
85  }
86  else
87  {
88  yCInfo(AUDIOFROMFILE) << "No `file_name` option specified. Audio will be loaded from default file:" << m_audio_filename;
89  }
90 
91  //opens the file
92  bool ret = yarp::sig::file::read(m_audioFile, m_audio_filename.c_str());
93  if (ret == false)
94  {
95  yCError(AUDIOFROMFILE) << "Unable to open file" << m_audio_filename.c_str();
96  return false;
97  }
98  yCInfo(AUDIOFROMFILE) << "Loaded file has the following properties: samples:" << m_audioFile.getSamples() << " channels:"<< m_audioFile.getChannels() << " bytes per samples:" << m_audioFile.getBytesPerSample();
99  if (m_audioFile.getChannels() != this->m_audiorecorder_cfg.numChannels)
100  {
101  yCInfo(AUDIOFROMFILE) << "Number of channels mismatch!";
102  return false;
103  }
104 
105  //sets the audio configuration equal to the audio file
106  //constexpr size_t c_EXTRA_SPACE = 2;
107  //AudioBufferSize buffer_size(m_audiorecorder_cfg.numSamples* c_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_datap = m_audioFile.getInterleavedAudioRawData();
111  m_fsize_in_samples = m_audioFile.getSamples();
112 
113  //start the capture thread
114  start();
115  return true;
116 }
117 
119 {
121  return true;
122 }
123 
124 
125 bool audioFromFileDevice::threadInit()
126 {
127  return true;
128 }
129 
130 
131 void audioFromFileDevice::run()
132 {
133  // when not recording, do nothing
134  if (!m_recording_enabled)
135  {
136  return;
137  }
138 
139  // Just acquire raw data and put them in the buffer
140  //each iteration, which occurs every xxx ms (thread period), I copy a fixed amount of
141  //samples (m_samples_to_be_copied) in the buffer. This operation cannot be interrupted by stopping the device
142  //with m_recording_enabled=false. When the pointer reaches the end of the sound (audioFile),
143  //just restart from the beginning in an endless loop
144  size_t chan_num = m_audioFile.getChannels();
145  for (size_t i = 0; i < m_samples_to_be_copied; i++)
146  {
147  if (m_bpnt >= m_fsize_in_samples)
148  {
149  m_bpnt = 0;
150  }
151  for (size_t c=0; c< chan_num; c++)
152  {
153  m_inputBuffer->write((unsigned short)(m_datap.at(m_bpnt* chan_num +c).get()));
154  }
155  m_bpnt++;
156  }
157 
158  if (m_audiobase_debug)
159  {
160  yCDebug(AUDIOFROMFILE) << "b_pnt" << m_bpnt << "/" << m_fsize_in_samples << " samples";
161  }
162 }
bool ret
constexpr double c_DEFAULT_PERIOD
unsigned short int audio_sample_16t
bool close() override
Close the DeviceDriver.
bool open(yarp::os::Searchable &config) override
Open the DeviceDriver.
bool setHWGain(double gain) override
Sets the hardware gain of the grabbing device (if supported by the hardware)
yarp::dev::CircularAudioBuffer_16t * m_inputBuffer
bool configureRecorderAudioDevice(yarp::os::Searchable &config, std::string device_name)
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::string asString() const
Get string value.
Definition: Value.cpp:234
size_t getBytesPerSample() const
Get the number of bytes per sample.
Definition: Sound.cpp:414
std::vector< std::reference_wrapper< audio_sample > > getInterleavedAudioRawData() const
Returns a serialized version of the sound, in interleaved format, e.g.
Definition: Sound.cpp:358
size_t getChannels() const
Get the number of channels of the sound.
Definition: Sound.cpp:424
size_t getSamples() const
Get the number of samples contained in the sound.
Definition: Sound.cpp:419
#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
An interface for the device drivers.
An interface to the operating system, including Port based communication.
bool read(ImageOf< PixelRgb > &dest, const std::string &src, image_fileformat format=FORMAT_ANY)
Definition: ImageFile.cpp:922
Signal processing.
Definition: Image.h:22