@@ -28,24 +28,24 @@ void processNewData() {
2828 }
2929
3030 // update the data buffers
31- for (int Ichan = 0 ; Ichan < channelCount; Ichan ++ ) {
31+ for (int channel = 0 ; channel < channelCount; channel ++ ) {
3232 for (int i = 0 ; i < getCurrentBoardBufferSize(); i++ ) {
33- dataProcessingRawBuffer[Ichan ][i] = (float )currentData. get(i)[exgChannels[Ichan ]];
33+ dataProcessingRawBuffer[channel ][i] = (float )currentData. get(i)[exgChannels[channel ]];
3434 }
3535
36- dataProcessingFilteredBuffer[Ichan ] = dataProcessingRawBuffer[Ichan ]. clone();
36+ dataProcessingFilteredBuffer[channel ] = dataProcessingRawBuffer[channel ]. clone();
3737 }
3838
3939 // apply additional processing for the time-domain montage plot (ie, filtering)
4040 dataProcessing. process(dataProcessingFilteredBuffer, fftBuff);
4141
4242 // look to see if the latest data is railed so that we can notify the user on the GUI
43- for (int Ichan = 0 ; Ichan < globalChannelCount; Ichan ++ ) is_railed[Ichan ]. update(dataProcessingRawBuffer[Ichan ], Ichan );
43+ for (int channel = 0 ; channel < globalChannelCount; channel ++ ) is_railed[channel ]. update(dataProcessingRawBuffer[channel ], channel );
4444
4545 // compute the electrode impedance. Do it in a very simple way [rms to amplitude, then uVolt to Volt, then Volt/Amp to Ohm]
46- for (int Ichan = 0 ; Ichan < globalChannelCount; Ichan ++ ) {
46+ for (int channel = 0 ; channel < globalChannelCount; channel ++ ) {
4747 // Calculate the impedance
48- float impedance = (sqrt (2.0 )* dataProcessing. data_std_uV[Ichan ]* 1.0e-6 ) / BoardCytonConstants . leadOffDrive_amps;
48+ float impedance = (sqrt (2.0 )* dataProcessing. data_std_uV[channel ]* 1.0e-6 ) / BoardCytonConstants . leadOffDrive_amps;
4949 // Subtract the 2.2kOhm resistor
5050 impedance -= BoardCytonConstants . series_resistor_ohms;
5151 // Verify the impedance is not less than 0
@@ -54,25 +54,24 @@ void processNewData() {
5454 impedance = 0 ;
5555 }
5656 // Store to the global variable
57- data_elec_imp_ohm[Ichan ] = impedance;
57+ data_elec_imp_ohm[channel ] = impedance;
5858 }
5959}
6060
61- void initializeFFTObjects (ddf.minim.analysis.FFT [] fftBuff , float [][] dataProcessingRawBuffer , int Nfft , float fs_Hz ) {
62-
61+ void initializeFFTObjects (ddf.minim.analysis.FFT [] fftBuff , float [][] dataProcessingRawBuffer , int fftPointCount , float fs_Hz ) {
6362 float [] fooData;
64- for (int Ichan = 0 ; Ichan < globalChannelCount; Ichan ++ ) {
63+ for (int channel = 0 ; channel < globalChannelCount; channel ++ ) {
6564 // make the FFT objects...Following "SoundSpectrum" example that came with the Minim library
66- fftBuff[Ichan ]. window(ddf.minim.analysis. FFT . HAMMING );
65+ fftBuff[channel ]. window(ddf.minim.analysis. FFT . HAMMING );
6766
6867 // do the FFT on the initial data
69- if (isFFTFiltered == true ) {
70- fooData = dataProcessingFilteredBuffer[Ichan ]; // use the filtered data for the FFT
68+ if (globalFFTSettings . getDataIsFiltered() ) {
69+ fooData = dataProcessingFilteredBuffer[channel ]; // use the filtered data for the FFT
7170 } else {
72- fooData = dataProcessingRawBuffer[Ichan ]; // use the raw data for the FFT
71+ fooData = dataProcessingRawBuffer[channel ]; // use the raw data for the FFT
7372 }
74- fooData = Arrays . copyOfRange(fooData, fooData. length- Nfft , fooData. length);
75- fftBuff[Ichan ]. forward(fooData); // compute FFT on this channel of data
73+ fooData = Arrays . copyOfRange(fooData, fooData. length- fftPointCount , fooData. length);
74+ fftBuff[channel ]. forward(fooData); // compute FFT on this channel of data
7675 }
7776}
7877
@@ -112,37 +111,37 @@ class DataProcessing {
112111 }
113112
114113 // Process data on a channel-by-channel basis
115- private synchronized void processChannel (int Ichan , float [][] data_forDisplay_uV , float [] prevFFTdata ) {
116- int Nfft = getNfftSafe ();
114+ private synchronized void processChannel (int channel , float [][] data_forDisplay_uV , float [] prevFFTdata ) {
115+ int fftPointCount = getNumFFTPoints ();
117116 double foo;
118117
119118 // Filter the data in the time domain
120119 // TODO: Use double arrays here and convert to float only to plot data.
121120 // ^^^ This might not feasible or meaningful performance improvement. I looked into it a while ago and it seems we need floats for the FFT library also. -RW 2022)
122121 try {
123- double [] tempArray = floatToDoubleArray(data_forDisplay_uV[Ichan ]);
122+ double [] tempArray = floatToDoubleArray(data_forDisplay_uV[channel ]);
124123
125124 // Apply BandStop filter if the filter should be active on this channel
126- if (filterSettings. values. bandStopFilterActive[Ichan ]. isActive()) {
125+ if (filterSettings. values. bandStopFilterActive[channel ]. isActive()) {
127126 DataFilter . perform_bandstop(
128127 tempArray,
129128 currentBoard. getSampleRate(),
130- filterSettings. values. bandStopStartFreq[Ichan ],
131- filterSettings. values. bandStopStopFreq[Ichan ],
132- filterSettings. values. bandStopFilterOrder[Ichan ]. getValue(),
133- filterSettings. values. bandStopFilterType[Ichan ]. getValue(),
129+ filterSettings. values. bandStopStartFreq[channel ],
130+ filterSettings. values. bandStopStopFreq[channel ],
131+ filterSettings. values. bandStopFilterOrder[channel ]. getValue(),
132+ filterSettings. values. bandStopFilterType[channel ]. getValue(),
134133 1.0 );
135134 }
136135
137136 // Apply BandPass filter if the filter should be active on this channel
138- if (filterSettings. values. bandPassFilterActive[Ichan ]. isActive()) {
137+ if (filterSettings. values. bandPassFilterActive[channel ]. isActive()) {
139138 DataFilter . perform_bandpass(
140139 tempArray,
141140 currentBoard. getSampleRate(),
142- filterSettings. values. bandPassStartFreq[Ichan ],
143- filterSettings. values. bandPassStopFreq[Ichan ],
144- filterSettings. values. bandPassFilterOrder[Ichan ]. getValue(),
145- filterSettings. values. bandPassFilterType[Ichan ]. getValue(),
141+ filterSettings. values. bandPassStartFreq[channel ],
142+ filterSettings. values. bandPassStopFreq[channel ],
143+ filterSettings. values. bandPassFilterOrder[channel ]. getValue(),
144+ filterSettings. values. bandPassFilterType[channel ]. getValue(),
146145 1.0 );
147146 }
148147
@@ -190,66 +189,68 @@ class DataProcessing {
190189 break ;
191190 }
192191
193- doubleToFloatArray(tempArray, data_forDisplay_uV[Ichan ]);
192+ doubleToFloatArray(tempArray, data_forDisplay_uV[channel ]);
194193 } catch (BrainFlowError e) {
195194 e. printStackTrace();
196195 }
197196
198197 // compute the standard deviation of the filtered signal...this is for the head plot
199- float [] fooData_filt = dataProcessingFilteredBuffer[Ichan ]; // use the filtered data
198+ float [] fooData_filt = dataProcessingFilteredBuffer[channel ]; // use the filtered data
200199 fooData_filt = Arrays . copyOfRange(fooData_filt, fooData_filt. length- ((int )fs_Hz), fooData_filt. length); // just grab the most recent second of data
201- data_std_uV[Ichan ] = std(fooData_filt); // compute the standard deviation for the whole array "fooData_filt"
200+ data_std_uV[channel] = std(fooData_filt); // compute the standard deviation for the whole array "fooData_filt"
202201
203202 // copy the previous FFT data...enables us to apply some smoothing to the FFT data
204- for (int I = 0 ; I < fftBuff[Ichan ]. specSize(); I ++ ) {
205- prevFFTdata[I ] = fftBuff[Ichan ]. getBand(I ); // copy the old spectrum values
203+ for (int I = 0 ; I < fftBuff[channel ]. specSize(); I ++ ) {
204+ prevFFTdata[I ] = fftBuff[channel ]. getBand(I ); // copy the old spectrum values
206205 }
207206
208207 // prepare the data for the new FFT
209208 float [] fooData;
210- if (isFFTFiltered == true ) {
211- fooData = dataProcessingFilteredBuffer[Ichan ]; // use the filtered data for the FFT
209+ if (globalFFTSettings . getDataIsFiltered() ) {
210+ fooData = dataProcessingFilteredBuffer[channel ]; // use the filtered data for the FFT
212211 } else {
213- fooData = dataProcessingRawBuffer[Ichan ]; // use the raw data for the FFT
212+ fooData = dataProcessingRawBuffer[channel ]; // use the raw data for the FFT
214213 }
215- fooData = Arrays . copyOfRange(fooData, fooData. length- Nfft , fooData. length); // trim to grab just the most recent block of data
214+ fooData = Arrays . copyOfRange(fooData, fooData. length- fftPointCount , fooData. length); // trim to grab just the most recent block of data
216215 float meanData = mean(fooData); // compute the mean
217216 for (int I = 0 ; I < fooData. length; I ++ ) fooData[I ] -= meanData; // remove the mean (for a better looking FFT
218217
219218 // compute the FFT
220- fftBuff[Ichan ]. forward(fooData); // compute FFT on this channel of data
219+ fftBuff[channel ]. forward(fooData); // compute FFT on this channel of data
221220
222221 // FFT ref: https://www.mathworks.com/help/matlab/ref/fft.html
223222 // first calculate double-sided FFT amplitude spectrum
224- for (int I = 0 ; I <= Nfft / 2 ; I ++ ) {
225- fftBuff[Ichan ]. setBand(I , (float )(fftBuff[Ichan ]. getBand(I ) / Nfft ));
223+ for (int I = 0 ; I <= fftPointCount / 2 ; I ++ ) {
224+ fftBuff[channel ]. setBand(I , (float )(fftBuff[channel ]. getBand(I ) / fftPointCount ));
226225 }
227226 // then convert into single-sided FFT spectrum: DC & Nyquist (i=0 & i=N/2) remain the same, others multiply by two.
228- for (int I = 1 ; I < Nfft / 2 ; I ++ ) {
229- fftBuff[Ichan ]. setBand(I , (float )(fftBuff[Ichan ]. getBand(I ) * 2 ));
227+ for (int I = 1 ; I < fftPointCount / 2 ; I ++ ) {
228+ fftBuff[channel ]. setBand(I , (float )(fftBuff[channel ]. getBand(I ) * 2 ));
230229 }
231230
232231 // average the FFT with previous FFT data so that it makes it smoother in time
233232 double min_val = 0.01d ;
234- for (int I = 0 ; I < fftBuff[Ichan ]. specSize(); I ++ ) { // loop over each fft bin
233+ float smoothingFactor = globalFFTSettings. getSmoothingFactor(). getValue();
234+ for (int I = 0 ; I < fftBuff[channel]. specSize(); I ++ ) { // loop over each fft bin
235235 if (prevFFTdata[I ] < min_val) prevFFTdata[I ] = (float )min_val; // make sure we're not too small for the log calls
236- foo = fftBuff[Ichan ]. getBand(I );
236+ foo = fftBuff[channel ]. getBand(I );
237237 if (foo < min_val) foo = min_val; // make sure this value isn't too small
238238
239239 if (true ) {
240240 // smooth in dB power space
241- foo = (1.0d - smoothFac[smoothFac_ind] ) * java.lang. Math . log(java.lang. Math . pow(foo, 2 ));
242- foo += smoothFac[smoothFac_ind] * java.lang. Math . log(java.lang. Math . pow((double )prevFFTdata[I ], 2 ));
241+ foo = (1.0d - smoothingFactor ) * java.lang. Math . log(java.lang. Math . pow(foo, 2 ));
242+ foo += smoothingFactor * java.lang. Math . log(java.lang. Math . pow((double )prevFFTdata[I ], 2 ));
243243 foo = java.lang. Math . sqrt(java.lang. Math . exp(foo)); // average in dB space
244244 } else {
245+ // LEGACY CODE -- NOT USED
245246 // smooth (average) in linear power space
246- foo = (1.0d - smoothFac[smoothFac_ind] ) * java.lang. Math . pow(foo, 2 );
247- foo+= smoothFac[smoothFac_ind] * java.lang. Math . pow((double )prevFFTdata[I ], 2 );
247+ foo = (1.0d - smoothingFactor ) * java.lang. Math . pow(foo, 2 );
248+ foo+= smoothingFactor * java.lang. Math . pow((double )prevFFTdata[I ], 2 );
248249 // take sqrt to be back into uV_rtHz
249250 foo = java.lang. Math . sqrt(foo);
250251 }
251- fftBuff[Ichan ]. setBand(I , (float )foo); // put the smoothed data back into the fftBuff data holder for use by everyone else
252- // fftBuff[Ichan ].setBand(I, 1.0f); // test
252+ fftBuff[channel ]. setBand(I , (float )foo); // put the smoothed data back into the fftBuff data holder for use by everyone else
253+ // fftBuff[channel ].setBand(I, 1.0f); // test
253254 } // end loop over FFT bins
254255
255256 // calculate single-sided psd by single-sided FFT amplitude spectrum
@@ -260,22 +261,22 @@ class DataProcessing {
260261 for (int i = 0 ; i < processing_band_low_Hz. length; i++ ) {
261262 float sum = 0 ;
262263 // int binNum = 0;
263- for (int Ibin = 0 ; Ibin <= Nfft / 2 ; Ibin ++ ) { // loop over FFT bins
264- float FFT_freq_Hz = fftBuff[Ichan ]. indexToFreq(Ibin ); // center frequency of this bin
264+ for (int Ibin = 0 ; Ibin <= fftPointCount / 2 ; Ibin ++ ) { // loop over FFT bins
265+ float FFT_freq_Hz = fftBuff[channel ]. indexToFreq(Ibin ); // center frequency of this bin
265266 float psdx = 0 ;
266267 // if the frequency matches a band
267268 if (FFT_freq_Hz >= processing_band_low_Hz[i] && FFT_freq_Hz < processing_band_high_Hz[i]) {
268- if (Ibin != 0 && Ibin != Nfft / 2 ) {
269- psdx = fftBuff[Ichan ]. getBand(Ibin ) * fftBuff[Ichan ]. getBand(Ibin ) * Nfft / currentBoard. getSampleRate() / 4 ;
269+ if (Ibin != 0 && Ibin != fftPointCount / 2 ) {
270+ psdx = fftBuff[channel ]. getBand(Ibin ) * fftBuff[channel ]. getBand(Ibin ) * fftPointCount / currentBoard. getSampleRate() / 4 ;
270271 }
271272 else {
272- psdx = fftBuff[Ichan ]. getBand(Ibin ) * fftBuff[Ichan ]. getBand(Ibin ) * Nfft / currentBoard. getSampleRate();
273+ psdx = fftBuff[channel ]. getBand(Ibin ) * fftBuff[channel ]. getBand(Ibin ) * fftPointCount / currentBoard. getSampleRate();
273274 }
274275 sum += psdx;
275276 // binNum ++;
276277 }
277278 }
278- avgPowerInBins[Ichan ][i] = sum; // total power in a band
279+ avgPowerInBins[channel ][i] = sum; // total power in a band
279280 // println(i, binNum, sum);
280281 }
281282 }
@@ -284,8 +285,8 @@ class DataProcessing {
284285
285286 float prevFFTdata[] = new float [fftBuff[0 ].specSize()];
286287
287- for (int Ichan = 0 ; Ichan < globalChannelCount; Ichan ++ ) {
288- processChannel(Ichan , data_forDisplay_uV, prevFFTdata);
288+ for (int channel = 0 ; channel < globalChannelCount; channel ++ ) {
289+ processChannel(channel , data_forDisplay_uV, prevFFTdata);
289290 } // end the loop over channels.
290291
291292 for (int i = 0 ; i < processing_band_low_Hz. length; i++ ) {
@@ -304,14 +305,14 @@ class DataProcessing {
304305 float [] refData_uV = dataProcessingFilteredBuffer[refChanInd]; // use the filtered data
305306 refData_uV = Arrays . copyOfRange(refData_uV, refData_uV. length- ((int )fs_Hz), refData_uV. length); // just grab the most recent second of data
306307 // Compute polarity of each channel
307- for (int Ichan = 0 ; Ichan < globalChannelCount; Ichan ++ ) {
308- float [] fooData_filt = dataProcessingFilteredBuffer[Ichan ]; // use the filtered data
308+ for (int channel = 0 ; channel < globalChannelCount; channel ++ ) {
309+ float [] fooData_filt = dataProcessingFilteredBuffer[channel ]; // use the filtered data
309310 fooData_filt = Arrays . copyOfRange(fooData_filt, fooData_filt. length- ((int )fs_Hz), fooData_filt. length); // just grab the most recent second of data
310311 float dotProd = calcDotProduct(fooData_filt, refData_uV);
311312 if (dotProd >= 0.0f ) {
312- polarity[Ichan ]= 1.0 ;
313+ polarity[channel ]= 1.0 ;
313314 } else {
314- polarity[Ichan ]= - 1.0 ;
315+ polarity[channel ]= - 1.0 ;
315316 }
316317 }
317318
0 commit comments