/
MuseOSC_EEG.h
127 lines (96 loc) · 3.73 KB
/
MuseOSC_EEG.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*
* MuseOSC_EEG.h
*
* Created on: 12.3.2024
* Author: Tomas
*
* NOTE: basic EEG sampling frequence in Muse headbands is 256 Hz,
* ICA/analytics sampling/computation frequency used is only 100 Hz.
*
* NOTE: This calculates *linear* ICA solution from the EEG measurements (makes some errors).
* FIXME: should calculate convolutional ICA instead with different time-delays to measurement points..
* FIXME: in practice you should also define possible time-delays of different measurement points and use
* one exact time delay which gives the best ICA solution.
*
*/
#ifndef MUSEOSC_EEG_H_
#define MUSEOSC_EEG_H_
#include "DataSource.h"
#include <vector>
#include <stdexcept>
#include <exception>
#include <thread>
#include <mutex>
#include <condition_variable>
namespace whiteice {
namespace resonanz {
/**
* Receives Muse OSC data from given UDP localhost port
* Currently outputs 8 values
*
* 0-4: delta, theta, alpha, beta, gamma absolute values fitted to [0,1] interval
* 5: total power: sum delta+theta+alpha+beta+gamma
* 6: spectral entropy of power signals [0,1]
* 7: average EEG phase difference between 4 measurement points (TP9, AF7, AF8, TP10)
* phase difference is computed from 250ms long history values
* (256 Hz sampling rate means 64 data points are saved to internal buffer)
*/
class MuseOSC_EEG: public DataSource {
public:
MuseOSC_EEG(const unsigned int port,
const float analyze_sampling_hz=100.0f,
const bool useICA = true); // throw(std::runtime_error)
virtual ~MuseOSC_EEG();
/*
* Returns unique DataSource name
*/
virtual std::string getDataSourceName() const;
/**
* Returns true if connection and data collection
* to device is currently working.
*/
virtual bool connectionOk() const;
/**
* returns current value
*/
virtual bool data(std::vector<float>& x) const;
virtual bool getSignalNames(std::vector<std::string>& names) const;
virtual unsigned int getNumberOfSignals() const;
virtual bool extradata(std::vector<float>& x) const;
virtual unsigned int getExtraNumberOfSignals() const;
private:
const unsigned int port;
void muse_loop(); // worker thread loop
// not implemented yet! reads 4 eeg values [TP9, TP10, AF7, AF8]
//bool read_eeg(std::vector< std::vector<float> >& EEG,
// const unsigned int numpoints);
std::thread* worker_thread = nullptr;
bool running;
bool hasConnection;
std::mutex connection_mutex;
std::condition_variable connection_cond;
float quality; // quality of connection [0,1]
mutable std::mutex data_mutex;
std::vector<float> value; // currently measured value
long long latest_sample_seen_t; // time of the latest measured value
// current EEG values
mutable std::mutex eeg_mutex;
float eegTP9 = 0.0f, eegAF7 = 0.0f, eegAF8 = 0.0f, eegTP10 = 0.0f;
std::thread* analyze_thread = nullptr;
float default_analyze_sampling_hz = 50.0f;
void sample_and_analyze_eeg_loop(); // another worker thread loop calculating extra values
mutable std::mutex extra_values_mutex;
float global_spectral_entropy = 0.0f;
float global_phase_difference = 0.0f;
float global_phase_slope_index = 0.0f;
bool calculate_ica_components = true;
float global_ica_spectral_entropy = 0.0f;
float global_ica_phase_difference = 0.0f;
float global_ica_phase_slope_index = 0.0f;
mutable std::mutex extra_data_mutex;
std::vector<float> extra_value;
std::vector<float> ica_extra_value; // not used extra values (power spectrum) calculated from ICA components..
};
} /* namespace resonanz */
} /* namespace whiteice */
#endif /* MUSEOSC_H_ */