Skip to content

Commit b044b49

Browse files
committed
More options in the cpp Receive/Send DataInChunks for testing.
1 parent b11ebd0 commit b044b49

File tree

2 files changed

+87
-27
lines changed

2 files changed

+87
-27
lines changed

examples/ReceiveDataInChunks.cpp

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,33 @@
33
#include <stdint.h>
44

55

6-
// define a packed sample struct (here a stereo sample).
7-
#pragma pack(1)
8-
struct stereo_sample {
9-
int16_t l, r;
10-
};
11-
12-
int main(int, char *[]) {
6+
int main(int argc, char **argv) {
137
try {
148

9+
std::string name{argc > 1 ? argv[1] : "MyAudioStream"};
1510
// resolve the stream of interest & make an inlet
16-
lsl::stream_inlet inlet(lsl::resolve_stream("name", "MyAudioStream").at(0));
11+
lsl::stream_inlet inlet(lsl::resolve_stream("name", name).at(0));
12+
13+
inlet.flush();
1714

18-
// and retrieve the chunks (note: this can of course also be done with pure std::vectors
19-
// instead of stereo_samples)
15+
double starttime = lsl::local_clock(), next_display = starttime + 1;
16+
17+
// and retrieve the chunks
18+
uint64_t k = 0, num_samples = 0;
2019
while (true) {
21-
std::vector<stereo_sample> result;
22-
if (double timestamp = inlet.pull_chunk_numeric_structs(result))
23-
std::cout << timestamp << std::endl; // only showing the time stamps here
20+
std::vector < std::vector<int16_t> > result;
21+
if (double timestamp = inlet.pull_chunk(result))
22+
num_samples += result.size();
23+
k++;
24+
25+
// display code
26+
if (k % 50 == 0) {
27+
double now = lsl::local_clock();
28+
if (now > next_display) {
29+
std::cout << num_samples / (now - starttime) << " samples/sec" << std::endl;
30+
next_display = now + 1;
31+
}
32+
}
2433
}
2534

2635
} catch (std::exception &e) { std::cerr << "Got an exception: " << e.what() << std::endl; }

examples/SendDataInChunks.cpp

Lines changed: 65 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
#include <cmath>
22
#include <iostream>
3+
#include <map>
34
#include <lsl_cpp.h>
45
#include <thread>
6+
#include <algorithm>
7+
#include <random>
58

69

710
// define a packed sample struct (here: a 16 bit stereo sample).
@@ -10,31 +13,79 @@ struct stereo_sample {
1013
int16_t l, r;
1114
};
1215

16+
// fill buffer with data from device -- Normally your device SDK would provide such a function. Here we use a random number generator.
17+
void get_data_from_device(std::vector<std::vector<int16_t>> buffer, uint64_t &sample_counter) {
18+
static std::uniform_int_distribution<int16_t> distribution(
19+
std::numeric_limits<int16_t>::min(), std::numeric_limits<int16_t>::max());
20+
static std::default_random_engine generator;
21+
22+
if (buffer[0].size() == 2) {
23+
// If there are only 2 channels then we'll do a sine wave, pretending this is an audio device.
24+
for (auto &frame : buffer) {
25+
frame[0] = static_cast<int16_t>(100 * sin(sample_counter / 200.));
26+
frame[1] = static_cast<int16_t>(120 * sin(sample_counter / 400.));
27+
sample_counter++;
28+
}
29+
}
30+
else {
31+
for (auto &frame : buffer) {
32+
for (std::size_t chan_idx = 0; chan_idx < frame.size(); ++chan_idx) {
33+
frame[chan_idx] = distribution(generator);
34+
}
35+
sample_counter++;
36+
}
37+
}
38+
}
39+
1340
int main(int argc, char **argv) {
41+
std::cout << "SendDataInChunks" << std::endl;
42+
std::cout << "SendDataInChunks StreamName StreamType samplerate n_channels max_buffered chunk_rate" << std::endl;
43+
std::cout << "- max_buffered -- duration in sec (or x100 samples if samplerate is 0) to buffer for each outlet" << std::endl;
44+
std::cout << "- chunk_rate -- number of chunks pushed per second. For this example, make it a common factor of samplingrate and 1000." << std::endl;
45+
1446
std::string name{argc > 1 ? argv[1] : "MyAudioStream"}, type{argc > 2 ? argv[2] : "Audio"};
1547
int samplingrate = argc > 3 ? std::stol(argv[3]) : 44100;
48+
int n_channels = argc > 4 ? std::stol(argv[4]) : 2;
49+
int32_t max_buffered = argc > 5 ? std::stol(argv[5]) : 360;
50+
int32_t chunk_rate = argc > 6 ? std::stol(argv[6]) : 10; // Chunks per second.
51+
int32_t chunk_samples = samplingrate > 0 ? std::max((samplingrate / chunk_rate), 1) : 100; // Samples per chunk.
52+
int32_t chunk_duration = 1000 / chunk_rate; // Milliseconds per chunk
53+
1654
try {
17-
// make a new stream_info (44.1Khz, 16bit, audio, 2 channels) and open an outlet with it
18-
lsl::stream_info info(name, type, 2, samplingrate, lsl::cf_int16);
19-
lsl::stream_outlet outlet(info);
55+
lsl::stream_info info(name, type, n_channels, samplingrate, lsl::cf_int16);
56+
lsl::stream_outlet outlet(info, 0, max_buffered);
57+
lsl::xml_element desc = info.desc();
58+
desc.append_child_value("manufacturer", "LSL");
59+
lsl::xml_element chns = desc.append_child("channels");
60+
for (int c = 0; c < n_channels; c++) {
61+
lsl::xml_element chn = chns.append_child("channel");
62+
chn.append_child_value("label", "Chan-" + std::to_string(c));
63+
chn.append_child_value("unit", "microvolts");
64+
chn.append_child_value("type", "EEG");
65+
}
66+
67+
// Prepare buffer to get data from 'device'
68+
std::vector<std::vector<int16_t>> chunk_buffer(
69+
chunk_samples,
70+
std::vector<int16_t>(n_channels));
2071

2172
std::cout << "Now sending data..." << std::endl;
73+
74+
// Your device might have its own timer. Or you can decide how often to poll
75+
// your device, as we do here.
2276
auto nextsample = std::chrono::high_resolution_clock::now();
23-
std::vector<stereo_sample> mychunk(info.nominal_srate() / 10);
24-
int phase = 0;
77+
uint64_t sample_counter = 0;
2578
for (unsigned c = 0;; c++) {
26-
// wait a bit and generate a chunk of random data
27-
nextsample += std::chrono::milliseconds(100);
79+
80+
// wait a bit
81+
nextsample += std::chrono::milliseconds(chunk_duration);
2882
std::this_thread::sleep_until(nextsample);
2983

30-
for (stereo_sample &sample : mychunk) {
31-
sample.l = static_cast<int16_t>(100 * sin(phase / 200.));
32-
sample.r = static_cast<int16_t>(120 * sin(phase / 400.));
33-
phase++;
34-
}
84+
// Get data from device
85+
get_data_from_device(chunk_buffer, sample_counter);
3586

36-
// send it
37-
outlet.push_chunk_numeric_structs(mychunk);
87+
// send it to the outlet
88+
outlet.push_chunk(chunk_buffer);
3889
}
3990

4091
} catch (std::exception &e) { std::cerr << "Got an exception: " << e.what() << std::endl; }

0 commit comments

Comments
 (0)