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+
1340int 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