YARP
Yet Another Robot Platform
 
Loading...
Searching...
No Matches
yarphear.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3 * SPDX-FileCopyrightText: 2006-2010 RobotCub Consortium
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <deque>
8
9#include <cstdio>
10#include <cmath>
11#include <mutex>
12
13#include <yarp/os/Log.h>
14
15#include <yarp/dev/PolyDriver.h>
17
18#include <yarp/sig/SoundFile.h>
19
21
22using namespace yarp::os;
23using namespace yarp::sig;
24using namespace yarp::sig::file;
25using namespace yarp::dev;
26
27int padding = 0;
28
29class Echo : public TypedReaderCallback<Sound> {
30private:
31 PolyDriver poly;
32 IAudioRender *iAudioplay;
34 std::mutex mutex;
35 bool muted;
36 bool saving;
37 std::deque<Sound> sounds;
38 size_t samples;
39 size_t channels;
40
41public:
42 Echo() : mutex() {
43 iAudioplay = nullptr;
44 port.useCallback(*this);
45 port.setStrict();
46 muted = false;
47 saving = false;
48 samples = 0;
49 channels = 0;
50 }
51
52 bool open(Searchable& p) {
53 bool dev = true;
54 if (p.check("nodevice")) {
55 dev = false;
56 }
57 if (dev) {
58 poly.open(p);
59 if (!poly.isValid()) {
60 yError("cannot open driver\n");
61 return false;
62 }
63
64 if (!p.check("mute")) {
65 // Make sure we can write sound
66 poly.view(iAudioplay);
67 if (iAudioplay == nullptr) {
68 yError("cannot open interface\n");
69 return false;
70 }
71 }
72 }
73
74 port.setStrict(true);
75 if (!port.open(p.check("name",Value("/yarphear")).asString())) {
76 yError("Communication problem\n");
77 return false;
78 }
79
80 if (p.check("remote")) {
81 Network::connect(p.check("remote",Value("/remote")).asString(),
82 port.getName());
83 }
84
85 return true;
86 }
87
89 void onRead(Sound& sound) override
90 {
91 #ifdef TEST
92 //this block can be used to measure time elapsed between two sound packets
93 static double t1= yarp::os::Time::now();
94 static double t2= yarp::os::Time::now();
96 yDebug("onread %f\n", t2-t1);
98 #endif
99
100 int ct = port.getPendingReads();
101 //yDebug("pending reads %d\n", ct);
102 while (ct>padding) {
103 ct = port.getPendingReads();
104 yWarning("Dropping sound packet -- %d packet(s) behind\n", ct);
105 port.read();
106 }
107 mutex.lock();
108 /*
109 if (muted) {
110 for (int i=0; i<sound.getChannels(); i++) {
111 for (int j=0; j<sound.getSamples(); j++) {
112 sound.put(0,j,i);
113 }
114 }
115 }
116 */
117 if (!muted) {
118 if (iAudioplay != nullptr) {
119 iAudioplay->renderSound(sound);
120 }
121 }
122 if (saving) {
123 saveFrame(sound);
124 }
125
126 mutex.unlock();
127 Time::yield();
128 }
129
130 void mute(bool muteFlag=true) {
131 mutex.lock();
132 muted = muteFlag;
133 mutex.unlock();
134 }
135
136 void save(bool saveFlag=true) {
137 mutex.lock();
138 saving = saveFlag;
139 mutex.unlock();
140 }
141
142 void saveFrame(Sound& sound) {
143 sounds.push_back(sound);
144 samples += sound.getSamples();
145 channels = sound.getChannels();
146 yDebug(" %ld sound frames buffered in memory (%ld samples)\n",
147 (long int) sounds.size(),
148 (long int) samples);
149 }
150
151 bool saveFile(const char *name) {
152 mutex.lock();
153 saving = false;
154
155 Sound total;
156 total.resize(samples,channels);
157 long int at = 0;
158 while (!sounds.empty()) {
159 Sound& tmp = sounds.front();
160 for (size_t i=0; i<channels; i++) {
161 for (size_t j=0; j<tmp.getSamples(); j++) {
162 total.set(tmp.get(j,i),at+j,i);
163 }
164 }
165 total.setFrequency(tmp.getFrequency());
166 at += tmp.getSamples();
167 sounds.pop_front();
168 }
169 mutex.unlock();
170 bool ok = write(total,name);
171 if (ok) {
172 yDebug("Wrote audio to %s\n", name);
173 }
174 samples = 0;
175 channels = 0;
176 return ok;
177 }
178
179 bool close() {
180 port.close();
181 mutex.lock(); // onRead never gets called again once it finishes
182 return true;
183 }
184};
185
186int main(int argc, char *argv[]) {
188
189 // see if user has supplied audio device
190 Property p;
191 if (argc>1) {
192 p.fromCommand(argc,argv);
193 }
194
195 // otherwise default device is "portaudioPlayer"
196 if (!p.check("device")) {
197 p.put("device","portaudioPlayer");
198 p.put("delay",1);
199 }
200
201 // start the echo service running
202 Echo echo;
203 echo.open(p);
204
205 // process the keyboard
206 bool muted = false;
207 bool saving = false;
208 bool help = false;
209 std::string fname = "audio_%06d.wav";
210 int ct = 0;
211 bool done = false;
212 while (!done) {
213 if (help) {
214 yInfo(" Press return to mute/unmute\n");
215 yInfo(" Type \"s\" to set start/stop saving audio in memory\n");
216 yInfo(" Type \"write filename.wav\" to write saved audio to a file\n");
217 yInfo(" Type \"buf NUMBER\" to set buffering delay (default is 0)\n");
218 yInfo(" Type \"write\" or \"w\" to write saved audio with same/default name\n");
219 yInfo(" Type \"q\" to quit\n");
220 yInfo(" Type \"help\" to see this list again\n");
221 help = false;
222 } else {
223 yInfo("Type \"help\" for usage\n");
224 }
225
226 std::string keys = yarp::os::impl::Terminal::readString(nullptr);
227 Bottle b(keys);
228 std::string cmd = b.get(0).asString();
229 if (b.size()==0) {
230 muted = !muted;
231 echo.mute(muted);
232 yInfo("%s\n", muted ? "Muted" : "Audible again");
233 } else if (cmd=="help") {
234 help = true;
235 } else if (cmd=="s") {
236 saving = !saving;
237 echo.save(saving);
238 yInfo("%s\n", saving ? "Saving" : "Stopped saving");
239 if (saving) {
240 yInfo(" Type \"s\" again to stop saving\n");
241 }
242 } else if (cmd=="write"||cmd=="w") {
243 if (b.size()==2) {
244 fname = b.get(1).asString();
245 }
246 char buf[2560];
247 sprintf(buf, fname.c_str(), ct);
248 echo.saveFile(buf);
249 ct++;
250 } else if (cmd=="q"||cmd=="quit") {
251 done = true;
252 } else if (cmd=="buf"||cmd=="b") {
253 padding = b.get(1).asInt32();
254 yInfo("Buffering at %d\n", padding);
255 }
256 }
257
258 echo.close();
259
260 return 0;
261}
#define yInfo(...)
Definition Log.h:319
#define yError(...)
Definition Log.h:361
#define yDebug(...)
Definition Log.h:275
#define yWarning(...)
Definition Log.h:340
bool close()
Definition yarphear.cpp:179
void save(bool saveFlag=true)
Definition yarphear.cpp:136
void mute(bool muteFlag=true)
Definition yarphear.cpp:130
void saveFrame(Sound &sound)
Definition yarphear.cpp:142
bool saveFile(const char *name)
Definition yarphear.cpp:151
Echo()
Definition yarphear.cpp:42
void onRead(Sound &sound) override
Definition yarphear.cpp:89
bool open(Searchable &p)
Definition yarphear.cpp:52
bool view(T *&x)
Get an interface to the device driver.
Interface for rendering a YARP-format sound and controlling its reproduction ona device.
virtual yarp::dev::ReturnValue renderSound(const yarp::sig::Sound &sound)=0
Render a sound using a device (i.e.
A container for a device driver.
Definition PolyDriver.h:23
bool isValid() const
Check if device is valid.
bool open(const std::string &txt)
Construct and configure a device by its common name.
A simple collection of objects that can be described and transmitted in a portable way.
Definition Bottle.h:64
size_type size() const
Gets the number of elements in the bottle.
Definition Bottle.cpp:251
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
Definition Bottle.cpp:246
A mini-server for performing network communication in the background.
std::string getName() const override
Get name of port.
void close() override
Stop port activity.
bool open(const std::string &name) override
Start port operation, with a specific name, with automatically-chosen network parameters.
int getPendingReads() override
Get the number of objects ready to be read.
T * read(bool shouldWait=true) override
Read an available object from the port.
void useCallback(TypedReaderCallback< T > &callback) override
Set an object whose onRead method will be called when data is available.
void setStrict(bool strict=true) override
Call this to strictly keep all messages, or allow old ones to be quietly dropped.
Utilities for manipulating the YARP network, including initialization and shutdown.
Definition Network.h:706
A class for storing options and configuration information.
Definition Property.h:33
void put(const std::string &key, const std::string &value)
Associate the given key with the given string.
Definition Property.cpp:987
bool check(const std::string &key) const override
Check if there exists a property of the given name.
void fromCommand(int argc, char *argv[], bool skipFirst=true, bool wipe=true)
Interprets a list of command arguments as a list of properties.
A base class for nested structures that can be searched.
Definition Searchable.h:31
virtual bool check(const std::string &key) const =0
Check if there exists a property of the given name.
A callback for typed data from a port.
A single value (typically within a Bottle).
Definition Value.h:43
virtual std::int32_t asInt32() const
Get 32-bit integer value.
Definition Value.cpp:204
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:25
size_t getChannels() const
Get the number of channels of the sound.
Definition Sound.cpp:603
size_t getSamples() const
Get the number of samples contained in the sound.
Definition Sound.cpp:598
For streams capable of holding different kinds of content, check what they actually have.
void yield()
The calling thread releases its remaining quantum upon calling this function.
Definition Time.cpp:131
double now()
Return the current time in seconds, relative to an arbitrary starting point.
Definition Time.cpp:121
std::string readString(bool *eof)
Definition Terminal.cpp:76
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)
The main, catch-all namespace for YARP.
Definition dirs.h:16
int main(int argc, char *argv[])
Definition yarphear.cpp:186
int padding
Definition yarphear.cpp:27