Welcome to BrainAccess C/C++ API documentation!

This is the documentation of BrainAccess Core and BrainAccess BCI Library C/C++ interfaces.


BrainAccess Core library is structured in 2 main parts: BrainAccess Core API and BrainAccess Core Preprocessing API.

BrainAccess Core API is used for EEG data acquisiton, channel configuration and other functionalities.
BrainAccess Core Preprocessing API provides tools for signal processing and FFT calculations.

To jump right in, checkout the BrainAccess Core Usage Examples section.


If you want to use BrainAccess BCI algorithms, see BrainAccess BCI Library.
Each algorithm is listed in a separate section which you can look through on the sidebar.

BrainAccess Core API

BrainAccess Core Functions

This section describes BrainAcess Core functions defined in ba_core_api.h.

Below listed functions are used for signal data acquisition, channel configuring, data saving/loading and battery supervision.

Functions

int baCore_initialize()

Initializes BrainAccess Core library and attempts to connect to BrainAccess EEG hardware.

baCore_initialize() or baCore_loadConfig() need to be called before any further actions, that require connection to the BrainAccess EEG hardware, are done.

Return

0 for success or one of these error codes: [1, 2, 3].

See BA_ErrorCodes for error definitions.

int baCore_loadConfig(char *configPath)

Loads a configuration file with acquisition parameters from the provided path and (re)initializes the library.

When baCore_loadConfig() is used, baCore_initialize() is not necessary beforehand.

If the configuration is loaded successfully, it is saved to the library’s working directory and automatically reloaded on successive library runs.

Return

0 for success or one of these error codes: [1, 2, 3], see BA_ErrorCodes for error definitions.

Parameters
  • configPath: needs to be the full path to the documentation, including the final file name. Escaped back slashes (“\ \ “) or forward slashes (“/”) should be used.

void baCore_saveConfig(char *configPath)

Saves current acquisition parameters to configuration file.

This is only needed when it is wished to have multiple configurations ready for different experiments. Otherwise, all the values set throughout this API are automatically saved to the library’s working directory.

Parameters
  • configPath: can either be the full path to the documentation, including the final file name, OR an empty string. If an empty string is provided, the configuration will be saved to the same location it was loaded from. If the full path is provided, escaped back slashes (“\ \ “) or forward slashes (“/”) should be used.

BA_EEGSamples baCore_getData(int timeSpanInMilliseconds)

Requests data acquired (or acquire if not yet acquired) by BrainAccess EEG hardware. This function should be used for continuous acquisition.

Requires initialization and active acquisition.

Return

BA_EEGSamples structure that holds info on hardware status, eeg data, lead status and accelerometer data.

Parameters
  • timeSpanInMilliseconds: recording length to acquire in milliseconds.

BA_EEGSamples baCore_getCurrentData()

Requests all the data that is currently acquired by BrainAccess EEG hardware.

Requires initialization and active acquisition.

The number of samples returned will be different, depending on the time passed since the last call. For continuous acquisition we recommend using baCore_getData() or baCore_getDataSamples()

Return

BA_EEGSamples structure that holds info on hardware status, eeg data, lead status and accelerometer data.

Parameters
  • timeSpanInMilliseconds: recording length to acquire in milliseconds.

BA_EEGSamples baCore_getDataFromNow(int timeSpanInMilliseconds)

Requests data to acquire straightaway by BrainAccess EEG hardware. This function should be used for triggered acquisition.

Requires initialization and active acquisition.

Previously collected data is discarded.

Return

BA_EEGSamples structure that holds info on hardware status, eeg data, lead status and accelerometer data.

Parameters
  • timeSpanInMilliseconds: recording length to acquire in milliseconds.

BA_EEGSamples baCore_getDataSamples(int numSamples)

Requests a number of data samples. These are pulled from internal buffer or acquired from the hardware if data in the buffer is not sufficient. This function should be used for continuous acquisition.

Requires initialization and active acquisition.

Return

BA_EEGSamples structure that holds info on hardware status, eeg data, lead status and accelerometer data.

Parameters
  • numSamples: number of samples to acquire.

BA_EEGSamples baCore_getDataSamplesFromNow(int numSamples)

Requests a number of data samples to acquire straightaway by BrainAccess EEG hardware. This function should be used for triggered acquisition.

Requires initialization and active acquisition.

Return

BA_EEGSamples structure that holds info on hardware status, eeg data, lead status and accelerometer data.

Parameters
  • numSamples: number of samples to acquire.

void baCore_startAcquisition()

Starts acquiring data from BrainAccess EEG hardware and filling an internal buffer.

Requires initialization.

void baCore_stopAcquisition()

Stops acquiring data from BrainAccess EEG hardware.

Requires initialization.

int baCore_setChannels(int *channelIdx, int channelIdxLen, int *biasChannelIdx, int biasChannelIdxLen)

Turns on the specified channels in BrainAccess EEG hardware.

Requires initialization and inactive acquisition.

Return

0 for success or one of these error codes: [3, 4], see BA_ErrorCodes for error definitions.

Parameters
  • channelIdx: a list containing channel numbers to turn on. BrainAccess Core always handles and holds channel indices in ascending order based on index integer value. This includes acquisition data (obtained from baCore_getData() methods) which is always provided in the ascending order of channel indices. We recommend users to have indices in ascending order in their code as well, in order to prevent confusion and mishaps.

  • channelIdxLen: length of the channelIdx list.

  • biasChannelIdx: a list containing channel numbers that should be used in bias feedback. Similarly to channelIdx, we recommend providing indices in ascending order.

  • biasChannelIdxLen: length fo the biasChannelidx list

void baCore_setChannelLabels(int *indices, char **labels, int len)

Updates the labels for certain channels.

Requires initialization.

Parameters
  • indices: A list of channel numbers for which the labels should be updated.

  • labels: A list of null-terminated labels corresponding to the indices. A label might be an empty string.

  • len: length of the indices and labels lists (they must be of the same length).

BA_ChannelList baCore_getActiveChannels()

Gets a list of channels that are turned on in BrainAccess EEG hardware.

Requires initialization.

Return

BA_ChannelList containing the list of active channels, their labels and bias channels. BA_ChannelList structure is freed on the next baCore_getActiveChannels() request, so make sure to copy the data if calling this method more than once.

int baCore_getNumChannels()

Gets the number of available channels in connected BrainAccess EEG hardware.

Requires initialization.

Return

Number of channels.

double baCore_setSamplingFrequency(double frequency)

Sets the sampling frequency for the BrainAccess EEG hardware.

Requires initialization and inactive acquisition.

Return

The actual frequency that has been set in the hardware in Hz.

Parameters
  • frequency: sampling frequency in Hz. It can either be 250.0 Hz or 125.0 Hz.

double baCore_getSamplingFrequency()

Gets the sampling frequency currently used by BrainAccess EEG hardware.

Return

sampling frequency in Hz.

void baCore_setBufferSize(int bufferSize)

Sets the size of internal buffer used in acquisition.

Requires initialization.

Parameters
  • bufferSize: buffer length (min 1, max 400000), the maximum number of samples that could be stored in the internal buffer.

int baCore_hasConnection()

Checks if BrainAccess core library still has connection with BrainAccess EEG hardware.

Requires initialization.

Return

1 if library can communicate, 0 if connection is broken.

void baCore_discardData()

Discards data in the internal buffer of baCore.

Requires initialization.

int baCore_batteryLevel()

Gets battery charge level. It is a rough estimate determined from the battery voltage.

Requires initialization.

Return

battery level in percentage

int baCore_isChargingOn()

Gets battery charging status.

Requires initialization.

Return

1 if battery charger is plugged in, 0 otherwise.

int baCore_batteryVoltage()

Gets voltage of the integrated LiPo battery.

Requires initialization.

Return

battery voltage in mV. Approximately, 4200mV for fully charged battery and 3600mV for fully depleted.

void baCore_configureLogging(int verbosity, char *outputFile)

Configures BrainAccess Core library logging.

Parameters
  • verbosity: an integer between 0 and 4, which describes what information is logged.

    0 = nothing is logged,

    1 = only error messages are logged,

    2 = warnings and error messages,

    3 = information messages designed to briefly reflect the library status + everything above,

    4 = debug messages, thoroughly describing actions performed by the library + everything above.

  • outputFile: might be either an empty string or a full path.

    If outputFile is an empty string, logging will be done to stdout.

    If the output file already exists, log output is appended to the existing file.

int baCore_saveData(BA_DataDescription request)

Saves data to a csv file.

Return

0 if the data was successfully saved, 5 if an error occured.

Parameters

BA_DataDescription baCore_loadData(char *filePath, char separator)

Loads data from a csv file.

Return

BA_DataDescription containing EEG data, accelerometer data and other relevant info. Returns empty eeg and accelerometer data arrays (see object attributes) if loading was unsuccessful.

Parameters
  • filePath: a full path including the file name. Escaped back slashes (“\ \ “) or forward slashes (“/”) should be used.

  • separator: a separator character used to separate columns in the csv file.

int baCore_getDeviceType()

Gets the type of EEG hardware.

Return

Device type identifier:

0 if device is BrainAccess Modular 1 if device is BrainAccess MINI -1 if the device type could not be read

void baCore_shutdown()

This function can be called after finishing work with BrainAccess hardware.

It turns off all active channels in order to save battery life.

void baCore_setAutosaveDir(char *dirPath)

BrainAccess Core Models

Describes structs that are used in the BrainAccess Core API.

struct BA_AccelerometerData
#include <ba_core_models.h>

Defines a single accelerometer data sample.

Here measurements are in g (i.e. 9.8 m/s^2 )

Public Members

double x = 0

X axis measurement.

double y = 0

Y axis measurement.

double z = 0

Z axis measurement.

struct BA_EEGSamples
#include <ba_core_models.h>

Defines a collection of BrainAccess EEG hardware measurement samples and stream status information.

Public Members

int numSamples = 0

Number of acquired data samples.

int numChannels = 0

Number of channels the returned samples include.

int streamDisrupted = 0

1 if data stream with Brain Access EEG hardware was disrupted and some samples might be lost, 0 otherwise.

int readingIsTooSlow = 0

1 if data is read too slowly (i.e. baCore_getData functions are called too infrequently). In this case internal BrainAccess Core buffer gets full and some data might be lost.

int connectionLost = 0

1 if wifi connection with Brain Access EEG hardware has been lost, 0 if everything is ok.

int **leadStatus = nullptr

Lead statuses of active channels for each sample, values: 0-connected, 1-not connected. Size of (numChannels X numSamples). Note that channel order in leadStatus is always in ascending order based on channel indices. We recommend users to store channel indices in ascending order in their code as well, to prevent confusion and mishaps.

double **measurements = nullptr

EEG data (numChannels X numSamples), values in uV. Note that channel order in measurements is always in ascending order based on channel indices. We recommend users to store channel indices in ascending order in their code as well, to prevent confusion and mishaps.

BA_AccelerometerData *accelerometerData = nullptr

Accelerometer data, values in fraction of g . Size of numSamples.

struct BA_ChannelList
#include <ba_core_models.h>

Defines active and bias channels and their labels.

Public Members

int numChannels = 0

Number of active channels.

int *indices = nullptr

List of active channel indices (size of numChannels).

char **labels = nullptr

List of null-terminated labels (size of numChannels).

int numBiasChannels = 0

Number of bias channels.

int *biasIndices = nullptr

List of bias channel indices (size of numBiasChannels).

struct BA_DataDescription
#include <ba_core_models.h>

Defines data saving or loading information.

Public Members

char *filePath

full path, including the file name.

Escaped back slashes (“\\ \\ “) or forward slashes (“/”) should be used.

char separator

CSV column separator.

int numChannels = 0

Number of channels described by the labels and measurements arrays.

int numSamples = 0

Number of samples in the measurements arrays.

char **labels = nullptr

An array of null terminated strings (size of numChannels)

double **measurements = nullptr

2 dimensional EEG measurement array (size of numChannels X numSamples)

BA_AccelerometerData *accelerometerData = nullptr

An array of accelerometer measurements (size of numSamples)

double samplingFrequency = 0

Sampling frequency.

BrainAccess Core Preprocessing API

BrainAccess Core Preprocessing Functions

Describes BrainAccess Core Preprocessing API functions.

This API is useful when wanting to do signal processing (to remove data trend, reduce noise or focus on specific frequency range), calculating FFT or wanting to estimate signal quality.

Functions

double *baCore_preprocess(double *measurements, int len)

Processes an EEG signal with given preprocessing parameters.

Measurements array values are updated in-place. If the provided values are needed for later, make sure to make a copy of them before calling this method.

Return

Preprocessed signal (of length len).

Parameters
  • measurements: 1D array containing an EEG signal. Updated in-place!

  • len: Length of measurements.

double baCore_estimateSignalQuality(double *signal, int len)

Estimates EEG signal quality.

Return

A number in range 0-1, 1 for good quality, 0 for worst quality

Parameters
  • signal: 1D array containing an EEG signal. The signal should be detrended before supplying it to this function.

  • len: Length of the signal.

void baCore_configurePreprocessing(BA_PreprocessingSettings settings)

Sets parameters for signal preprocessing.

Parameters
  • settings: Preprocessing settings.

void baCore_configureFiltering(BA_FilteringSettings settings)

Sets parameters for signal filtering.

Parameters
  • settings: (Possibly multiple) filter settings.

void baCore_configureDetrending(BA_DetrendingSettings settings)

Sets parameters for signal detrending algorithm.

Parameters
  • settings: detrending settings.

void baCore_configureWindowFunction(BA_WindowSettings settings)

Sets parameters for temporal window.

The window is applied as the last preprocessing step.

Parameters
  • settings: Temporal window settings.

void baCore_setPreprocessingSamplingFrequency(double samplingFrequency)

Sets sampling frequency for preprocessing functions.

Parameters
  • samplingFrequency: sampling frequency in Hz.

BA_PreprocessingSettings baCore_getPreprocessingSettings()

Gets the current parameters for signal processing.

Return

BA_PreprocessingSettings struct holding the preprocessing settings.

BA_FourierTransform baCore_fourierTransform(double *signal, int len)

Calculates FFT for a given signal.

Return

BA_FourierTransform struct holding the results of FFT.

Parameters
  • signal: 1D array containing an EEG signal.

  • len: Length of the signal.

void baCore_loadPreprocessingConfig(char *configPath)

Loads configuration file with signal preprocessing parameters.

If the configuration is loaded successfully, it is saved to the library’s working directory and automatically reloaded on successive library runs.

Parameters
  • configPath: a full path including the configuration file name. Escaped back slashes (“\ \ “) or forward slashes (“/”) should be used.

void baCore_savePreprocessingConfig(char *configPath)

Saves signal preprocessing parameters to a configuration file.

Parameters
  • configPath: a full path including the configuration file name OR an empty string.

    If a full path is provided, escaped back slashes (“\ \ “) or forward slashes (“/”) should be used. If an empty string is provided, configuration will be saved to the same location it was loaded from.

BrainAccess Core Preprocessing Models

Defines structs that are used in the BrainAccess Core Preprocessing API.

struct BA_DetrendingSettings
#include <ba_core_preprocessing_models.h>

Contains parameters for signal detrend algorithm.

Public Members

int isActive = 0

1 if is used, 0 otherwise.

int polynomialDegree = 1

Order of polynomial curve used to remove data trend.

struct BA_SingleFilterSettings
#include <ba_core_preprocessing_models.h>

Contains parameters for a single signal filter.

Public Members

int isActive = 0

1 if used, 0 otherwise.

int type = 0

Filter type. Possible filters: BandPass = 0, BandStop = 1, LowPass = 2, HighPass = 3.

int order = 2

Filter order.

double minFrequency = 1

low cut-off frequency for band filters and cut-off frequency for highpass filter

double maxFrequency = 35

high cut-off frequency for band filters and cut-off frequency for lowpass filter..

struct BA_FilteringSettings
#include <ba_core_preprocessing_models.h>

Contains parameters for signal filters.

Public Members

int numFilters = 0

Number of signal filters.

BA_SingleFilterSettings *filters = nullptr

Each filter settings.

struct BA_WindowSettings
#include <ba_core_preprocessing_models.h>

Contains temporal window parameteres.

Public Members

int isActive = 0

1 if used, 0 otherwise.

int type = 0

Window type. Possible windows: Tukey = 0, Hann = 1.

double tukeyAlpha = 0.2

Tukey window parameter.

struct BA_PreprocessingSettings
#include <ba_core_preprocessing_models.h>

Contains all of the possible preprocessing steps settings.

Public Members

double samplingFrequency

Data sampling frequency (required for FFT and filtering).

BA_DetrendingSettings detrendingSettings

Detrending algorithm settings.

BA_FilteringSettings filteringSettings

Signal filter settings.

BA_WindowSettings windowSettings

Temporal Window function settings.

struct BA_FourierTransform
#include <ba_core_preprocessing_models.h>

Struct containing spectrum data calculated using FFT.

Public Members

int len

Length of the arrays in this ojbect.

double *spectrum_real

Real parts of the spectrum.

double *spectrum_imaginary

Imaginary parts of the spectrum.

double *frequencies

Frequencies in Hz (derived from spectrum values).

double *magnitudes

Magnitudes normalized by len (derived from spectrum values).

double *phases

Phases in degrees (derived from spectrum values).

BrainAccess Core Error Codes

Enums

enum BA_ErrorCodes

Error codes returned from the BrainAccess Core library.

Values:

enumerator connectionCouldNotBeMade = 1

Connection could not be made due to network issues.

enumerator masterSlotIsEmpty = 2

The first board slot is empty.

enumerator disallowedDuringAcquisition = 3

Not allowed during acquisition.

enumerator libraryNotInitialized = 4

The library was not (successfully) initialized.

enumerator ioError = 5

Error while reading or writing to a file.

BrainAccess Core Usage Examples

Continuous data acquisition demo

Functions

void continuousAcquisition()


#include <iostream>
#include <vector>
#include "samples.h"
#include "ba_core.h"  // import all API functions

/*
Demo of continuous acquisition of EEG data using BrainAccess Core library.

It demonstrates how to set up acquisition and how to pass a continuous stream of
data into a local buffer. It also demonstrates some preprocessing capabilities
of the module.

Connect to BrainAccess EEG hardware over WIFI before running this script.
*/

void continuousAcquisition() {
    // Initialize the BrainAccess Core library
    int res = baCore_initialize();

    if (res != 0) {
        std::cout << "Could not initialize BrainAccess Core library. " << std::endl;
        std::cout << "Please see library logs for details." << std::endl;
        return;
    }
    std::cout << "BrainAccess Core library initialized!" << std::endl;

    // Get some info on the hardware status
    // Check the batterry level:
    int batteryLevel = baCore_batteryLevel();
    std::cout << "Battery level is: " << batteryLevel << "%" << std::endl;
    if (batteryLevel < 20) {
        std::cout << "Please charge the battery, it is getting low." << std::endl;
    }
        

    // get total number of available channels in the connected BrainAccess EEG hardware.
    int totalNumChannels = baCore_getNumChannels();
    std::cout << "Total number of available channels: " << totalNumChannels << std::endl;

    // Acquisition parameters

    // Note: these can also be saved and loaded from configuration file using baCore_saveConfig and baCore_loadConfig.
    // Look for configuration file BA_core_config.json located in the same directory where BACore.dll is.
    // It stores the current state of acquisition parameters.
    
    // channel numbers corresponding to channels used in acquisition
    int* channelNumbers = new int[2] { 0, 1 };
    int numActiveChannels = 2;

    // channels used in bias feedback
    int* biasChannelNumbers = new int[1]{ 0 };
    int lenBiasChannels = 1;

    // set the channels
    baCore_setChannels(channelNumbers, numActiveChannels, biasChannelNumbers, lenBiasChannels);

    // get the default sampling frequency, it is also possible to set the sampling frequency. See BrainAccess Core documentation.
    int samplingFrequency = baCore_getSamplingFrequency();
    std::cout << "Sampling frequency is: " << samplingFrequency << std::endl;
        
    // Create buffers to store EEG and Accelerometer data

    // Create numActiveChannels number of vectors to store raw EEG signal data
    std::vector<std::vector<double>> rawSignals = std::vector<std::vector<double>>(numActiveChannels, std::vector<double>());
    // Create vector to store Accelerometer data
    std::vector<BA_AccelerometerData> accData = std::vector<BA_AccelerometerData>();


    // Signal preprocessing parameters

    // Note: these can also be saved and loaded from configuration file using save_preprocessing_config
    // and load_config.Look for configuration file BA_prepr_config.json located in the same directory
    // where BACore.dll is.It stores the current state of acquisition parameters.

    // set sampling frequency for preprocessor
    baCore_setSamplingFrequency(samplingFrequency);

    // add trend remover to remove DC offset and drift from EEG signals
    BA_DetrendingSettings detrendingSettings;
    detrendingSettings.isActive = 1;
    detrendingSettings.polynomialDegree = 1;
    baCore_configureDetrending(detrendingSettings);
            
    // add band pass filter (more filters can be added to the preprocessor as necessary)
    BA_FilteringSettings filterSettings;
    BA_SingleFilterSettings filter;
    filter.isActive = true;
    filter.order = 2;
    filter.minFrequency = 1;
    filter.maxFrequency = 40;
    filterSettings.filters = new BA_SingleFilterSettings[1]{ filter };
    baCore_configureFiltering(filterSettings);


    // DATA ACQUISITION
    // ================
    
    // Start Acquisition (the library will start pulling samples from the BrainAccessEEG hardware)
    baCore_startAcquisition();

    // Note: continuous acquisition loop would be typically run in a separate thread and
    // data buffers would be shared with the main or other threads. Main thread can
    // then continuously access data and use for different purposes such as plotting,
    // signal processing, BCI inference, etc.

    // number of samples to pull per single acquisition
    int numSamplesPerAcq = 5;
    // number of acquisitions to perform
    int numAcq = 5;
    for (int i = 0; i < numAcq; i++) {
        // ask for certain number of samples 
        BA_EEGSamples eegSamples = baCore_getDataSamples(numSamplesPerAcq);
        std::cout << "Acquired " << eegSamples.numSamples << " samples" << std::endl;

        // check connection and stream status
        if (eegSamples.connectionLost) {
            std::cout << "Connection Lost!" << std::endl;
            break;
        }
        if (eegSamples.streamDisrupted) {
            std::cout << "BrainAccess Core library missed some samples from the EEG hardware, ";
            std::cout << "check if there is a good WIFI connection with the device." << std::endl;
        }
        if (eegSamples.readingIsTooSlow) {
            std::cout << "Acquire data quicker as the internal buffer of BrainAccess Core has filled up." << std::endl;
        }
            
        // store measurements
        for (int sample = 0; sample < eegSamples.numSamples; sample++) {
            // get signal measurements
            for (int ch = 0; ch < numActiveChannels; ch++) {
                rawSignals[ch].push_back(eegSamples.measurements[ch][sample]);
            }

            // get accelerometer values
            accData.push_back(eegSamples.accelerometerData[sample]);
        }
    }

    // stop acquisition
    baCore_stopAcquisition();


    // PREPROCESSING
    // ===============

    // Note: preprocessing could be done during acquisition as well,
    //       in cases where preprocessed data is needed live.

    // create empty vector for preprocessed data
    std::vector<std::vector<double>> preprSignals = std::vector<std::vector<double>>();

    // preprocess the signals
    for (int i = 0; i < numActiveChannels; i++) {
        // get a preprocessed
        // preprocessing uses the configuration we have set up above
        double* preprocessed = baCore_preprocess(rawSignals[i].data(), rawSignals[i].size());
        // copy the data to preprSignals
        preprSignals.push_back(std::vector<double>(preprocessed, preprocessed + rawSignals[i].size()));

        std::cout << i + 1 << "/" << numActiveChannels << " signals preprocessed" << std::endl;
    }

    // inspect the data, visualize it, or do anything that is needed.
}

Single data acquisitions demo

Functions

void singleAcquisition()


#include <iostream>
#include <vector>
#include <string>
#include "samples.h"
#include "ba_core.h"  // import all API functions

/*
Demo of single acquisitions of EEG data using ba_core module.

It demonstrates how to make time critical single acquisitions. Time critical means
that data is recorded from the time point of the request. This is useful, for example,
when it is needed to make a record straight after the visual or audio stimulus. It
also shows how the library can be used to save recorded data in csv format.

Connect to BrainAccess EEG hardware over WIFI before running this script.
*/

void singleAcquisition() {
    // Initialize the BrainAccess Core library
    int res = baCore_initialize();

    if (res != 0) {
        std::cout << "Could not initialize BrainAccess Core library. " << std::endl;
        std::cout << "Please see library logs for details." << std::endl;
        return;
    }
    std::cout << "BrainAccess Core library initialized!" << std::endl;

    // Get some info on the hardware status
    // Check the batterry level:
    int batteryLevel = baCore_batteryLevel();
    std::cout << "Battery level is: " << batteryLevel << "%" << std::endl;
    if (batteryLevel < 20) {
        std::cout << "Please charge the battery, it is getting low." << std::endl;
    }


    // get total number of available channels in the connected BrainAccess EEG hardware.
    int totalNumChannels = baCore_getNumChannels();
    std::cout << "Total number of available channels: " << totalNumChannels << std::endl;

    // Acquisition parameters

    // Note: these can also be saved and loaded from configuration file using baCore_saveConfig and baCore_loadConfig.
    // Look for configuration file BA_core_config.json located in the same directory where BACore.dll is.
    // It stores the current state of acquisition parameters.

    // channel numbers corresponding to channels used in acquisition
    int* channelNumbers = new int[2]{ 0, 1 };
    int numActiveChannels = 2;

    // channels used in bias feedback
    int* biasChannelNumbers = new int[1]{ 0 };
    int lenBiasChannels = 1;

    // set the channels
    baCore_setChannels(channelNumbers, numActiveChannels, biasChannelNumbers, lenBiasChannels);

    // set labels for the channels
    char** electrodeLabels = new char*[2]{ "O1", "O2" };
    baCore_setChannelLabels(channelNumbers, electrodeLabels, numActiveChannels);

    // get the default sampling frequency, it is also possible to set the sampling frequency. See BrainAccess Core documentation.
    int samplingFrequency = baCore_getSamplingFrequency();
    std::cout << "Sampling frequency is: " << samplingFrequency << std::endl;


    // Record parameters

    // record length in miliseconds
    int trecord = 500;

    // number of acquisitions
    int numAcquisitions = 5;

    // initialize data structure required for data saving
    BA_DataDescription data;
    data.samplingFrequency = samplingFrequency;
    data.labels = electrodeLabels;
    data.separator = ' ';
    data.numChannels = numActiveChannels;

    // Start acquisition  (the library will start pulling samples from the BrainAccessEEG hardware)
    baCore_startAcquisition();

    // make requested time critical acquisitions for numAcquisitions number of times
    for (int i = 0; i < numAcquisitions; i++) {
        // Note: here should be a call for stimulus. After executing the stimulus call,
        // the data request should be made straight away

        // request data('from now' means that all the data already in the internal buffer
        // will be discarded and only data from this time moment will be recorded).
        // this call blocks until the required number of samples are collected
        BA_EEGSamples samples = baCore_getDataFromNow(trecord);

        // Save the record to current working directory in csv format

        // generate file name
        std::string filename = "record" + std::to_string(i) + ".csv";

        // pass data for saving
        data.measurements = samples.measurements;
        data.accelerometerData = samples.accelerometerData;
        data.numSamples = samples.numSamples;
        
        // set the file path
        // length of the array can also be dynamic but do not forget to free the memory after you use it
        data.filePath = new char[15];
        // unfortunately we have to copy the string content as it cannot be assigned to non const char*
        std::copy(filename.begin(), filename.end(), data.filePath);
        // do not forget to null-terminate !
        data.filePath[filename.size()] = '\0';

        // save data
        baCore_saveData(data);

        std::cout << "Acquisition " << i << " saved to " << filename << std::endl;
    }

    // stop acquisition(the library will stop pulling data)
    baCore_stopAcquisition();
    std::cout << "Acquisition stopped" << std::endl;
}

BrainAccess BCI Library

Motion Classifier

This section describes functions available to control the Motion Classifier algorithm.

Motion Classifier recognizes facial motions performed by the user:
calm state (when no action is pefromed),
single eye blink,
double eye blink,
eye movement up,
eye movement down,
teeth grind.
These motions can then be mapped to any software for different kinds of control actions.
(See Motion Classifier Browser Controller demo for an example).

The algorithm expects exactly 2 EEG channels placed at Fp1 and Fp2 positions.

The workflow of using Motion Classifier is as follows:
1. Call baBCILibrary_initializeMotionClassifier(), ensure it was successful.
2. Call baBCILibrary_startMotionClassifier() to start collecting data.
3. Whenever a prediction is needed call baBCILibrary_predictMotionClassifier().
4. Optionally call baBCILibrary_discardMotionClassifierData() (see description).
5. When the algorithm is no longer needed call baBCILibrary_stopMotionClassifier().

See all function descriptions for more information.

Functions

int baBCILibrary_initializeMotionClassifier(int fp1Idx, int fp2Idx)

Initializes Motion Classifier’s internal structures, intializes BrainAccess Core library and attempts to connect to BrainAccess EEG hardware.

Note that only Fp1 and Fp2 channels are suitable for this algorithm.

Return

0 on success and -1 on failure.

Parameters
  • fp1Idx: index of the channel that is in the Fp1 position.

  • fp2Idx: index of the channel that is in the Fp2 position.

void baBCILibrary_startMotionClassifier()

Starts EEG data collection.

Should be called before baBCILibrary_predictMotionClassifier()

void baBCILibrary_stopMotionClassifier()

Stops EEG data collection.

Should be called when Motion Classifier is no longer needed.

double *baBCILibrary_predictMotionClassifier()

Predicts which motion was performed by the user.

The prediction is made from the last 2.5 seconds of data. If not enough data is available for a prediction, this function waits for the required data and only then predicts.

When calling baBCILibrary_predictMotionClassifier() consequently, the previously collected data is reused, meaning that predictions can be made as often as needed.

Note that the accuracy of the algorithm depends if the collected EEG data captures the whole motion. This means that if Motion Classifier predicts on data that only has the start of the motion recorded, the prediction will not be accurate.

To counteract this, we suggest predicting often and accepting the prediction as trustworthy only when the prediction is the same for some number of times in a row. See Motion Classifier Browser Controller demo for an example.

Return

Probabilities that each of the possible motions were performed. Probabilities are given in such order:

Calm (no action was performed), Blink (single blink), Double Blink, Teeth (teeth grind), Eyes Up (quick eye movement upwards), Eyes Down (eye movement downwards).

The returned pointer is invalidated on the next request, so copy the predictions if needed.

void baBCILibrary_discardMotionClassifierData()

Discards currently collected data, data collection continues from scratch.

This can be useful when a pause between predictions is needed. For example, it can be used after the user performs some action and it triggers a response in GUI. Then discarding data would allow to remove data that was collected while the user was waiting for the GUI response.

Alpha Detector

This section describes functions available to control the Alpha Detector algorithm.

Alpha detector can specify the magnitude of alpha brainwaves currently produced by the user.

Alpha brainwaves are most pronounced when a person is completely relaxed and has his/her eyes closed. This means that alpha wave detection can serve as an approximate measure of how relaxed a person is.

The algorithm expects 1-3 electrodes in the oxipital region. We suggest using electrodes placed in O1 and O2 positions.

The workflow of using Alpha Detector is as follows:
1. Call baBCILibrary_initializeAlphaDetector(), ensure it was successful.
2. Call baBCILibrary_startAlphaDetector() to start collecting data.
3. Estimate alpha frequency by calling baBCILibrary_estimateAlphaFrequency().
4. Whenever a prediction is needed call baBCILibrary_predictAlpha() or baBCILibrary_predictAlphaFromNow().
5. When the algorithm is no longer needed call baBCILibrary_stopAlphaDetector().

See all function descriptions for more information.

Functions

int baBCILibrary_initializeAlphaDetector(int *channelIdx, int channelIdxLen)

Initializes Alpha Detector’s internal structures, intializes BrainAccess Core library and attempts to connect to BrainAccess EEG hardware.

Return

0 on success and -1 on failure.

Parameters
  • channelIdx: indices of channels that should be used by the algorithm (we recommend using channels placed in oxipital region). Maximum allowed number of channels is 3.

  • channelIdxLen: number of channels in channelIdx.

int baBCILibrary_startAlphaDetector()

Starts EEG data collection.

Should be called before baBCILibrary_predictAlpha() or baBCILibrary_predictAlphaFromNow()

Return

0 if successful, -1 otherwise

int baBCILibrary_stopAlphaDetector()

Stops EEG data collection.

Should be called when Alpha Detector is no longer needed.

Return

0 if successful, -1 otherwise

int baBCILibrary_estimateAlphaFrequency()

Estimates the alpha frequency for the user.

Each person has a slightly different alpha brainwave frequency, although it is usually in the range of 8-12Hz. This algorithm works best by firstly estimating the frequency for the current user. When this method is called, user should sit still, with his/her eyes closed for 3 seconds.

Return

0 if successful, -1 otherwise

double baBCILibrary_predictAlpha()

Predicts alpha wave intensity from the latest EEG data.

The data used in the previous predictions is reused if needed. If not enough data is available, this function firstly waits for the data and only then predicts.

Return

Estimation of alpha wave intensity as a measure between 0 and 1.

For small alpha wave activities expect the value to be around 0.05

For strong alpha waves expect the value to be up to 0.5 (larger values are less common).

double baBCILibrary_predictAlphaFromNow()

Predicts alpha wave intensity from EEG data collected from the moment this function is called.

Previously collected data is discarded and the algorithm collects the required number of measurements before predicting. This can be useful if prediction should be made with data collected after some kind of event.

Return

The same alpha intensity evaluation as baSDK_predictAlpha().

SSVEP Detector

This section describes functions available to control the SSVEP Detector algorithm.

SSVEP Detector can recognize steady-state visual evoked potentials (SSVEP). Meaning that given a visual stimulus flickering at a constant frequency, SSVEP Detector can determine if the user is currently looking at it.
This can be used as motionless control, where the user chooses an option by looking at the corresponding visual stimulus.

The algorithm expects 1-3 electrodes in the occipital region. We recommend using 2-3 electordes in the O1, O2 and optionally Oz positions

The workflow of using SSVEP Detector is as follows:

  1. Call baBCILibrary_initializeSSVEPDetector(), ensure it was successful.

  2. Call baBCILibrary_startSSVEPDetector() to start collecting data.

  3. Whenever a prediction is needed call baBCILibrary_predictSSVEP().

  4. When the algorithm is no longer needed call baBCILibrary_stopSSVEPDetector().

See all function descriptions for more information.

Functions

int baBCILibrary_initializeSSVEPDetector(int *channelIdx, int channelIdxLen, double *ssvepFrequencies, int ssvepFrequenciesLen)

Initializes SSVEP Detector’s internal structures, intializes BrainAccess Core library and attempts to connect to BrainAccess EEG hardware.

Return

0 on success and -1 on failure.

Parameters
  • channelIdx: indices of channels that should be used by the algorithm. Electrodes should be placed in oxipital region (we suggest O1, O2, Oz).

  • channelIdxLen: number of channels in channelIdx.

  • ssvepFrequencies: flicker frequencies that are provided as visual stimuli for the user. For best results, frequencies should be roughly in 8 - 15Hz range and distance between them should be at least 1Hz. Each frequency is associated with a class that the algorithm later predicts.

  • ssvepFrequenciesLen: number of ssvepFrequencies provided.

int baBCILibrary_startSSVEPDetector()

Starts EEG data collection.

Should be called before baBCILibrary_predictSSVEP()

Return

0 if successful, -1 otherwise

int baBCILibrary_stopSSVEPDetector()

Stops EEG data collection.

Should be called when SSVEP Detector is no longer needed.

Return

0 if successful, -1 otherwise

int baBCILibrary_predictSSVEP()

Predicts class (frequency) on which user is concentrated.

Note that EEG data does not instantly reflect the flicker frequencies once the user switches focus to it. Rather, it takes a few seconds for it to happen.

Return

Predicted class index or -1 if an error occured. Class indices correspond to frequencies provided in baBCILibrary_initializeSSVEPDetector() function (using the same ordering as was provided).