From a944b799f7da840f51dfb4cddb3ebf38dff4ce52 Mon Sep 17 00:00:00 2001 From: Septen <gammerxpower@gmail.com> Date: Mon, 6 Jun 2016 01:40:01 +0400 Subject: [PATCH] Almost all plugins' processors refactoring and stylystic fixes. * Refactoring applied mostly because we need to satisfy the new state of GenericProcessor after refactoring; * Also there were a lot of stylystic fixes applied, some minor improvements using C++11. --- .../Plugins/ArduinoOutput/ArduinoOutput.cpp | 118 ++-- Source/Plugins/ArduinoOutput/ArduinoOutput.h | 46 +- .../SpikeDetector/SpikeDetector.cpp | 579 +++++++--------- .../SpikeDetector/SpikeDetector.h | 142 ++-- .../SpikeDisplayNode/SpikeDisplayNode.cpp | 155 ++--- .../SpikeDisplayNode/SpikeDisplayNode.h | 71 +- .../ChannelMappingNode/ChannelMappingNode.cpp | 174 ++--- .../ChannelMappingNode/ChannelMappingNode.h | 35 +- Source/Plugins/EcubeSource/EcubeThread.h | 46 +- .../EventBroadcaster/EventBroadcaster.h | 1 + .../Plugins/EventDetector/EventDetector.cpp | 38 +- Source/Plugins/EventDetector/EventDetector.h | 23 +- Source/Plugins/EventNode/EventNode.cpp | 52 +- Source/Plugins/EventNode/EventNode.h | 30 +- Source/Plugins/FilterNode/FilterNode.cpp | 188 +++-- Source/Plugins/FilterNode/FilterNode.h | 54 +- .../Plugins/LfpDisplayNode/LfpDisplayNode.cpp | 287 ++++---- .../Plugins/LfpDisplayNode/LfpDisplayNode.h | 47 +- .../LfpDisplayNodeBeta/LfpDisplayNode.cpp | 292 ++++---- .../LfpDisplayNodeBeta/LfpDisplayNode.h | 47 +- .../LfpTriggeredAverageNode.cpp | 273 +++----- .../LfpTriggeredAverageNode.h | 45 +- .../Plugins/NetworkEvents/NetworkEvents.cpp | 651 +++++++++--------- Source/Plugins/NetworkEvents/NetworkEvents.h | 152 ++-- .../Plugins/PhaseDetector/PhaseDetector.cpp | 126 ++-- Source/Plugins/PhaseDetector/PhaseDetector.h | 49 +- .../Plugins/PulsePalOutput/PulsePalOutput.cpp | 72 +- .../Plugins/PulsePalOutput/PulsePalOutput.h | 33 +- .../Plugins/RecordControl/RecordControl.cpp | 46 +- Source/Plugins/RecordControl/RecordControl.h | 36 +- Source/Plugins/Rectifier/Rectifier.cpp | 81 +-- Source/Plugins/Rectifier/Rectifier.h | 88 +-- Source/Plugins/SerialInput/SerialInput.cpp | 100 +-- Source/Plugins/SerialInput/SerialInput.h | 109 ++- .../SignalGenerator/SignalGenerator.cpp | 207 ++---- .../Plugins/SignalGenerator/SignalGenerator.h | 55 +- Source/Plugins/SpikeSorter/SpikeSorter.cpp | 2 + Source/Processors/FileReader/FileReader.cpp | 6 +- Source/Processors/FileReader/FileReader.h | 5 +- .../GenericProcessor/GenericProcessor.cpp | 2 +- .../GenericProcessor/GenericProcessor.h | 2 +- .../PlaceholderProcessor.cpp | 2 +- .../PlaceholderProcessor.h | 6 +- Source/Processors/SourceNode/SourceNode.cpp | 306 ++++---- Source/Processors/SourceNode/SourceNode.h | 94 ++- 45 files changed, 2252 insertions(+), 2721 deletions(-) diff --git a/Source/Plugins/ArduinoOutput/ArduinoOutput.cpp b/Source/Plugins/ArduinoOutput/ArduinoOutput.cpp index 95c911543..02d490686 100644 --- a/Source/Plugins/ArduinoOutput/ArduinoOutput.cpp +++ b/Source/Plugins/ArduinoOutput/ArduinoOutput.cpp @@ -2,7 +2,7 @@ ------------------------------------------------------------------ This file is part of the Open Ephys GUI - Copyright (C) 2014 Open Ephys + Copyright (C) 2016 Open Ephys ------------------------------------------------------------------ @@ -26,94 +26,97 @@ #include <stdio.h> + ArduinoOutput::ArduinoOutput() - : GenericProcessor("Arduino Output"), outputChannel(13), inputChannel(-1), state(true), acquisitionIsActive(false), deviceSelected(false) + : GenericProcessor ("Arduino Output") + , outputChannel (13) + , inputChannel (-1) + , state (true) + , acquisitionIsActive (false) + , deviceSelected (false) { + setProcessorType (PROCESSOR_TYPE_SINK); } + ArduinoOutput::~ArduinoOutput() { - if (arduino.isInitialized()) - arduino.disconnect(); + if (arduino.isInitialized()) + arduino.disconnect(); } + AudioProcessorEditor* ArduinoOutput::createEditor() { - editor = new ArduinoOutputEditor(this, true); + editor = new ArduinoOutputEditor (this, true); return editor; } -void ArduinoOutput::setDevice(String devName) -{ - if (!acquisitionIsActive) +void ArduinoOutput::setDevice (String devName) +{ + if (! acquisitionIsActive) { - Time timer; - arduino.connect(devName.toStdString()); + arduino.connect (devName.toStdString()); if (arduino.isArduinoReady()) { - uint32 currentTime = timer.getMillisecondCounter(); arduino.sendProtocolVersionRequest(); - timer.waitForMillisecondCounter(currentTime + 2000); + timer.waitForMillisecondCounter (currentTime + 2000); arduino.update(); arduino.sendFirmwareVersionRequest(); - timer.waitForMillisecondCounter(currentTime + 4000); + timer.waitForMillisecondCounter (currentTime + 4000); arduino.update(); std::cout << "firmata v" << arduino.getMajorFirmwareVersion() << "." << arduino.getMinorFirmwareVersion() << std::endl; - } if (arduino.isInitialized()) { - std::cout << "Arduino is initialized." << std::endl; - arduino.sendDigitalPinMode(outputChannel, ARD_OUTPUT); - CoreServices::sendStatusMessage(("Arduino initialized at" + devName)); + arduino.sendDigitalPinMode (outputChannel, ARD_OUTPUT); + CoreServices::sendStatusMessage (("Arduino initialized at" + devName)); deviceSelected = true; } else { std::cout << "Arduino is NOT initialized." << std::endl; - CoreServices::sendStatusMessage(("Arduino could not be initialized at" + devName)); + CoreServices::sendStatusMessage (("Arduino could not be initialized at" + devName)); } - } else { - CoreServices::sendStatusMessage("Cannot change device while acquisition is active."); } - - + else + { + CoreServices::sendStatusMessage ("Cannot change device while acquisition is active."); + } } -void ArduinoOutput::handleEvent(int eventType, MidiMessage& event, int sampleNum) +void ArduinoOutput::handleEvent (int eventType, MidiMessage& event, int sampleNum) { if (eventType == TTL) { const uint8* dataptr = event.getRawData(); //int eventNodeId = *(dataptr+1); - int eventId = *(dataptr+2); - int eventChannel = *(dataptr+3); + const int eventId = *(dataptr + 2); + const int eventChannel = *(dataptr + 3); - // std::cout << "Received event from " << eventNodeId << - // " on channel " << eventChannel << - // " with value " << eventId << std::endl; + // std::cout << "Received event from " << eventNodeId + // << " on channel " << eventChannel + // << " with value " << eventId << std::endl; if (eventChannel == gateChannel) { if (eventId == 1) - { state = true; - } else { + else state = false; - } } if (state) @@ -122,22 +125,19 @@ void ArduinoOutput::handleEvent(int eventType, MidiMessage& event, int sampleNum { if (eventId == 0) { - arduino.sendDigital(outputChannel, ARD_LOW); + arduino.sendDigital (outputChannel, ARD_LOW); } else { - arduino.sendDigital(outputChannel, ARD_HIGH); + arduino.sendDigital (outputChannel, ARD_HIGH); } } } - - //ArduinoOutputEditor* ed = (ArduinoOutputEditor*) getEditor(); - //ed->receivedEvent(); } - } -void ArduinoOutput::setParameter(int parameterIndex, float newValue) + +void ArduinoOutput::setParameter (int parameterIndex, float newValue) { // make sure current output channel is off: arduino.sendDigital(outputChannel, ARD_LOW); @@ -145,12 +145,15 @@ void ArduinoOutput::setParameter(int parameterIndex, float newValue) if (parameterIndex == 0) { outputChannel = (int) newValue; - } else if (parameterIndex == 1) + } + else if (parameterIndex == 1) { inputChannel = (int) newValue; - } else if (parameterIndex == 2) + } + else if (parameterIndex == 2) { gateChannel = (int) newValue; + if (gateChannel == -1) state = true; else @@ -158,40 +161,43 @@ void ArduinoOutput::setParameter(int parameterIndex, float newValue) } } -void ArduinoOutput::setOutputChannel(int chan) + +void ArduinoOutput::setOutputChannel (int chan) { - setParameter(0, chan); + setParameter (0, chan); } -void ArduinoOutput::setInputChannel(int chan) + +void ArduinoOutput::setInputChannel (int chan) { - setParameter(1, chan-1); + setParameter (1, chan - 1); } -void ArduinoOutput::setGateChannel(int chan) + +void ArduinoOutput::setGateChannel (int chan) { - setParameter(2, chan-1); + setParameter (2, chan - 1); } + bool ArduinoOutput::enable() { acquisitionIsActive = true; - return deviceSelected; + + return deviceSelected; } + bool ArduinoOutput::disable() { - arduino.sendDigital(outputChannel, ARD_LOW); + arduino.sendDigital (outputChannel, ARD_LOW); acquisitionIsActive = false; - return true; -} - -void ArduinoOutput::process(AudioSampleBuffer& buffer, - MidiBuffer& events) -{ - - checkForEvents(events); + return true; +} +void ArduinoOutput::process (AudioSampleBuffer& buffer, MidiBuffer& events) +{ + checkForEvents (events); } diff --git a/Source/Plugins/ArduinoOutput/ArduinoOutput.h b/Source/Plugins/ArduinoOutput/ArduinoOutput.h index 5dec3b259..822143f79 100644 --- a/Source/Plugins/ArduinoOutput/ArduinoOutput.h +++ b/Source/Plugins/ArduinoOutput/ArduinoOutput.h @@ -2,7 +2,7 @@ ------------------------------------------------------------------ This file is part of the Open Ephys GUI - Copyright (C) 2014 Open Ephys + Copyright (C) 2016 Open Ephys ------------------------------------------------------------------ @@ -31,60 +31,51 @@ /** + *UNDER CONSTRUCTION* - *UNDER CONSTRUCTION* + Provides a serial interface to an Arduino board. - Provides a serial interface to an Arduino board. - - Based on Open Frameworks ofArduino class. - - @see GenericProcessor - -*/ + Based on Open Frameworks ofArduino class. + @see GenericProcessor + */ class ArduinoOutput : public GenericProcessor { public: - ArduinoOutput(); ~ArduinoOutput(); /** Searches for events and triggers the Arduino output when appropriate. */ - void process(AudioSampleBuffer& buffer, MidiBuffer& events); + void process (AudioSampleBuffer& buffer, MidiBuffer& events) override; /** Currently unused. Future uses may include changing the TTL trigger channel or the output channel of the Arduino. */ - void setParameter(int parameterIndex, float newValue); + void setParameter (int parameterIndex, float newValue) override; /** Convenient interface for responding to incoming events. */ - void handleEvent(int eventType, MidiMessage& event, int sampleNum); + void handleEvent (int eventType, MidiMessage& event, int sampleNum) override; /** Called immediately prior to the start of data acquisition. */ - bool enable(); + bool enable() override; /** Called immediately after the end of data acquisition. */ - bool disable(); + bool disable() override; /** Creates the ArduinoOutputEditor. */ - AudioProcessorEditor* createEditor(); + AudioProcessorEditor* createEditor() override; - /** Defines the ArduinoOutput processor as a sink. */ - bool isSink() - { - return true; - } + void setOutputChannel (int); + void setInputChannel (int); + void setGateChannel (int); - void setOutputChannel(int); - void setInputChannel(int); - void setGateChannel(int); - void setDevice(String deviceString); + void setDevice (String deviceString); int outputChannel; int inputChannel; int gateChannel; -private: +private: /** An open-frameworks Arduino object. */ ofArduino arduino; @@ -92,8 +83,7 @@ private: bool acquisitionIsActive; bool deviceSelected; - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ArduinoOutput); - + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ArduinoOutput); }; diff --git a/Source/Plugins/BasicSpikeDisplay/SpikeDetector/SpikeDetector.cpp b/Source/Plugins/BasicSpikeDisplay/SpikeDetector/SpikeDetector.cpp index cf8d348a4..865e0aa85 100644 --- a/Source/Plugins/BasicSpikeDisplay/SpikeDetector/SpikeDetector.cpp +++ b/Source/Plugins/BasicSpikeDisplay/SpikeDetector/SpikeDetector.cpp @@ -2,7 +2,7 @@ ------------------------------------------------------------------ This file is part of the Open Ephys GUI - Copyright (C) 2014 Open Ephys + Copyright (C) 2016 Open Ephys ------------------------------------------------------------------ @@ -24,16 +24,21 @@ #include <stdio.h> #include "SpikeDetector.h" + SpikeDetector::SpikeDetector() - : GenericProcessor("Spike Detector"), - overflowBuffer(2,100), dataBuffer(nullptr), - overflowBufferSize(100), currentElectrode(-1), - uniqueID(0) + : GenericProcessor ("Spike Detector") + , overflowBuffer (2, 100) + , dataBuffer (nullptr), + overflowBufferSize (100) + , currentElectrode (-1) + , uniqueID (0) { + setProcessorType (PROCESSOR_TYPE_FILTER); + //// the standard form: - electrodeTypes.add("single electrode"); - electrodeTypes.add("stereotrode"); - electrodeTypes.add("tetrode"); + electrodeTypes.add ("single electrode"); + electrodeTypes.add ("stereotrode"); + electrodeTypes.add ("tetrode"); //// the technically correct form (Greek cardinal prefixes): // electrodeTypes.add("hentrode"); @@ -57,49 +62,46 @@ SpikeDetector::SpikeDetector() // electrodeTypes.add("enneakaidecatrode"); // electrodeTypes.add("icosatrode"); - for (int i = 0; i < electrodeTypes.size()+1; i++) + for (int i = 0; i < electrodeTypes.size() + 1; ++i) { - electrodeCounter.add(0); + electrodeCounter.add (0); } //spikeBuffer = new uint8_t[MAX_SPIKE_BUFFER_LEN]; // MAX_SPIKE_BUFFER_LEN defined in SpikeObject.h - spikeBuffer.malloc(MAX_SPIKE_BUFFER_LEN); - + spikeBuffer.malloc (MAX_SPIKE_BUFFER_LEN); } + SpikeDetector::~SpikeDetector() { - } AudioProcessorEditor* SpikeDetector::createEditor() { - editor = new SpikeDetectorEditor(this, true); + editor = new SpikeDetectorEditor (this, true); return editor; } + void SpikeDetector::updateSettings() { - if (getNumInputs() > 0) - overflowBuffer.setSize(getNumInputs(), overflowBufferSize); + overflowBuffer.setSize (getNumInputs(), overflowBufferSize); - for (int i = 0; i < electrodes.size(); i++) + for (int i = 0; i < electrodes.size(); ++i) { - - Channel* ch = new Channel(this,i,ELECTRODE_CHANNEL); - ch->name = generateSpikeElectrodeName(electrodes[i]->numChannels, ch->index); - SpikeChannel* spk = new SpikeChannel(SpikeChannel::Plain, electrodes[i]->numChannels, NULL, 0); - ch->extraData = spk; - eventChannels.add(ch); + Channel* ch = new Channel (this,i,ELECTRODE_CHANNEL); + ch->name = generateSpikeElectrodeName (electrodes[i]->numChannels, ch->index); + SpikeChannel* spk = new SpikeChannel (SpikeChannel::Plain, electrodes[i]->numChannels, NULL, 0); + ch->extraData = spk; + eventChannels.add (ch); } - } -bool SpikeDetector::addElectrode(int nChans, int electrodeID) -{ +bool SpikeDetector::addElectrode (int nChans, int electrodeID) +{ std::cout << "Adding electrode with " << nChans << " channels." << std::endl; int firstChan; @@ -111,7 +113,7 @@ bool SpikeDetector::addElectrode(int nChans, int electrodeID) else { SimpleElectrode* e = electrodes.getLast(); - firstChan = *(e->channels+(e->numChannels-1))+1; + firstChan = *(e->channels + (e->numChannels - 1)) + 1; } if (firstChan + nChans > getNumInputs()) @@ -120,135 +122,146 @@ bool SpikeDetector::addElectrode(int nChans, int electrodeID) } int currentVal = electrodeCounter[nChans]; - electrodeCounter.set(nChans,++currentVal); + electrodeCounter.set (nChans, ++currentVal); String electrodeName; // hard-coded for tetrode configuration if (nChans < 3) - electrodeName = electrodeTypes[nChans-1]; + electrodeName = electrodeTypes[nChans - 1]; else - electrodeName = electrodeTypes[nChans-2]; + electrodeName = electrodeTypes[nChans - 2]; - String newName = electrodeName.substring(0,1); + String newName = electrodeName.substring (0,1); newName = newName.toUpperCase(); - electrodeName = electrodeName.substring(1,electrodeName.length()); + electrodeName = electrodeName.substring (1, electrodeName.length()); newName += electrodeName; newName += " "; newName += electrodeCounter[nChans]; - SimpleElectrode* newElectrode = new SimpleElectrode(); + SimpleElectrode* newElectrode = new SimpleElectrode; newElectrode->name = newName; newElectrode->numChannels = nChans; newElectrode->prePeakSamples = 8; newElectrode->postPeakSamples = 32; - newElectrode->thresholds.malloc(nChans); - newElectrode->isActive.malloc(nChans); - newElectrode->channels.malloc(nChans); + newElectrode->thresholds.malloc (nChans); + newElectrode->isActive.malloc (nChans); + newElectrode->channels.malloc (nChans); newElectrode->isMonitored = false; - for (int i = 0; i < nChans; i++) + for (int i = 0; i < nChans; ++i) { - *(newElectrode->channels+i) = firstChan+i; - *(newElectrode->thresholds+i) = getDefaultThreshold(); - *(newElectrode->isActive+i) = true; + *(newElectrode->channels + i) = firstChan+i; + *(newElectrode->thresholds + i) = getDefaultThreshold(); + *(newElectrode->isActive + i) = true; } - if (electrodeID > 0) { + if (electrodeID > 0) + { newElectrode->electrodeID = electrodeID; - uniqueID = std::max(uniqueID, electrodeID); - } else { + uniqueID = std::max (uniqueID, electrodeID); + } + else + { newElectrode->electrodeID = ++uniqueID; } - + newElectrode->sourceNodeId = channels[*newElectrode->channels]->sourceNodeId; - resetElectrode(newElectrode); + resetElectrode (newElectrode); - electrodes.add(newElectrode); + electrodes.add (newElectrode); - currentElectrode = electrodes.size()-1; + currentElectrode = electrodes.size() - 1; return true; - } -float SpikeDetector::getDefaultThreshold() + +float SpikeDetector::getDefaultThreshold() const { return 50.0f; } -StringArray SpikeDetector::getElectrodeNames() + +StringArray SpikeDetector::getElectrodeNames() const { StringArray names; - for (int i = 0; i < electrodes.size(); i++) + for (int i = 0; i < electrodes.size(); ++i) { - names.add(electrodes[i]->name); + names.add (electrodes[i]->name); } return names; } -void SpikeDetector::resetElectrode(SimpleElectrode* e) + +void SpikeDetector::resetElectrode (SimpleElectrode* e) { e->lastBufferIndex = 0; } -bool SpikeDetector::removeElectrode(int index) -{ +bool SpikeDetector::removeElectrode (int index) +{ // std::cout << "Spike detector removing electrode" << std::endl; if (index > electrodes.size() || index < 0) return false; - electrodes.remove(index); + electrodes.remove (index); return true; } -void SpikeDetector::setElectrodeName(int index, String newName) + +void SpikeDetector::setElectrodeName (int index, String newName) { - electrodes[index-1]->name = newName; + electrodes[index - 1]->name = newName; } -void SpikeDetector::setChannel(int electrodeIndex, int channelNum, int newChannel) -{ - std::cout << "Setting electrode " << electrodeIndex << " channel " << channelNum << - " to " << newChannel << std::endl; +void SpikeDetector::setChannel (int electrodeIndex, int channelNum, int newChannel) +{ + std::cout << "Setting electrode " << electrodeIndex << " channel " << channelNum + << " to " << newChannel << std::endl; - *(electrodes[electrodeIndex]->channels+channelNum) = newChannel; + *(electrodes[electrodeIndex]->channels + channelNum) = newChannel; } -int SpikeDetector::getNumChannels(int index) -{ +int SpikeDetector::getNumChannels (int index) const +{ if (index < electrodes.size()) return electrodes[index]->numChannels; else return 0; } -int SpikeDetector::getChannel(int index, int i) + +int SpikeDetector::getChannel (int index, int i) const { - return *(electrodes[index]->channels+i); + return *(electrodes[index]->channels + i); } -void SpikeDetector::getElectrodes(Array<SimpleElectrode*>& electrodeArray) + +void SpikeDetector::getElectrodes (Array<SimpleElectrode*>& electrodeArray) { - electrodeArray.addArray(electrodes); + electrodeArray.addArray (electrodes); } -SimpleElectrode* SpikeDetector::setCurrentElectrodeIndex(int i) + +SimpleElectrode* SpikeDetector::setCurrentElectrodeIndex (int i) { - jassert(i >= 0 & i < electrodes.size()); + jassert (i >= 0 & i < electrodes.size()); currentElectrode = i; + return electrodes[i]; } -SimpleElectrode* SpikeDetector::getActiveElectrode() + +SimpleElectrode* SpikeDetector::getActiveElectrode() const { if (electrodes.size() == 0) return nullptr; @@ -256,201 +269,190 @@ SimpleElectrode* SpikeDetector::getActiveElectrode() return electrodes[currentElectrode]; } -void SpikeDetector::setChannelActive(int electrodeIndex, int subChannel, bool active) -{ - +void SpikeDetector::setChannelActive (int electrodeIndex, int subChannel, bool active) +{ currentElectrode = electrodeIndex; currentChannelIndex = subChannel; std::cout << "Setting channel active to " << active << std::endl; if (active) - setParameter(98, 1); + setParameter (98, 1); else - setParameter(98, 0); - + setParameter (98, 0); } -bool SpikeDetector::isChannelActive(int electrodeIndex, int i) + +bool SpikeDetector::isChannelActive (int electrodeIndex, int i) { - return *(electrodes[electrodeIndex]->isActive+i); + return *(electrodes[electrodeIndex]->isActive + i); } -void SpikeDetector::setChannelThreshold(int electrodeNum, int channelNum, float thresh) +void SpikeDetector::setChannelThreshold (int electrodeNum, int channelNum, float thresh) { currentElectrode = electrodeNum; currentChannelIndex = channelNum; + std::cout << "Setting electrode " << electrodeNum << " channel threshold " << channelNum << " to " << thresh << std::endl; - setParameter(99, thresh); + + setParameter (99, thresh); } -double SpikeDetector::getChannelThreshold(int electrodeNum, int channelNum) + +double SpikeDetector::getChannelThreshold(int electrodeNum, int channelNum) const { - return *(electrodes[electrodeNum]->thresholds+channelNum); + return *(electrodes[electrodeNum]->thresholds + channelNum); } -void SpikeDetector::setParameter(int parameterIndex, float newValue) + +void SpikeDetector::setParameter (int parameterIndex, float newValue) { //editor->updateParameterButtons(parameterIndex); if (parameterIndex == 99 && currentElectrode > -1) { - *(electrodes[currentElectrode]->thresholds+currentChannelIndex) = newValue; + *(electrodes[currentElectrode]->thresholds + currentChannelIndex) = newValue; } else if (parameterIndex == 98 && currentElectrode > -1) { if (newValue == 0.0f) - *(electrodes[currentElectrode]->isActive+currentChannelIndex) = false; + *(electrodes[currentElectrode]->isActive + currentChannelIndex) = false; else - *(electrodes[currentElectrode]->isActive+currentChannelIndex) = true; + *(electrodes[currentElectrode]->isActive + currentChannelIndex) = true; } } bool SpikeDetector::enable() { - sampleRateForElectrode = (uint16_t) getSampleRate(); - useOverflowBuffer.clear(); - for (int i = 0; i < electrodes.size(); i++) - useOverflowBuffer.add(false); + for (int i = 0; i < electrodes.size(); ++i) + useOverflowBuffer.add (false); return true; } + bool SpikeDetector::disable() { - - for (int n = 0; n < electrodes.size(); n++) + for (int n = 0; n < electrodes.size(); ++n) { - resetElectrode(electrodes[n]); + resetElectrode (electrodes[n]); } return true; } -void SpikeDetector::addSpikeEvent(SpikeObject* s, MidiBuffer& eventBuffer, int peakIndex) -{ +void SpikeDetector::addSpikeEvent (SpikeObject* s, MidiBuffer& eventBuffer, int peakIndex) +{ // std::cout << "Adding spike event for index " << peakIndex << std::endl; s->eventType = SPIKE_EVENT_CODE; - int numBytes = packSpike(s, // SpikeObject - spikeBuffer, // uint8_t* - MAX_SPIKE_BUFFER_LEN); // int + int numBytes = packSpike (s, // SpikeObject + spikeBuffer, // uint8_t* + MAX_SPIKE_BUFFER_LEN); // int if (numBytes > 0) - eventBuffer.addEvent(spikeBuffer, numBytes, peakIndex); + eventBuffer.addEvent (spikeBuffer, numBytes, peakIndex); //std::cout << "Adding spike" << std::endl; } -void SpikeDetector::addWaveformToSpikeObject(SpikeObject* s, - int& peakIndex, - int& electrodeNumber, - int& currentChannel) + +void SpikeDetector::addWaveformToSpikeObject (SpikeObject* s, + int& peakIndex, + int& electrodeNumber, + int& currentChannel) { - int spikeLength = electrodes[electrodeNumber]->prePeakSamples + + int spikeLength = electrodes[electrodeNumber]->prePeakSamples + electrodes[electrodeNumber]->postPeakSamples; -// uint8_t eventType; -// int64_t timestamp; -// int64_t timestamp_software; -// uint16_t source; // used internally, the index of the electrode in the electrode array -// uint16_t nChannels; -// uint16_t nSamples; -// uint16_t sortedId; // sorted unit ID (or 0 if unsorted) -// uint16_t electrodeID; // unique electrode ID (regardless electrode position in the array) -// uint16_t channel; // the channel in which threshold crossing was detected (index in channel array, not absolute channel number). -// uint8_t color[3]; -// float pcProj[2]; -// uint16_t samplingFrequencyHz; -// uint16_t data[MAX_NUMBER_OF_SPIKE_CHANNELS* MAX_NUMBER_OF_SPIKE_CHANNEL_SAMPLES]; -// float gain[MAX_NUMBER_OF_SPIKE_CHANNELS]; -// uint16_t threshold[MAX_NUMBER_OF_SPIKE_CHANNELS]; - - s->timestamp = getTimestamp(currentChannel) + peakIndex; - - s->nSamples = spikeLength; - - int chan = *(electrodes[electrodeNumber]->channels+currentChannel); - - s->gain[currentChannel] = (int)(1.0f / channels[chan]->bitVolts)*1000; + // uint8_t eventType; + // int64_t timestamp; + // int64_t timestamp_software; + // uint16_t source; // used internally, the index of the electrode in the electrode array + // uint16_t nChannels; + // uint16_t nSamples; + // uint16_t sortedId; // sorted unit ID (or 0 if unsorted) + // uint16_t electrodeID; // unique electrode ID (regardless electrode position in the array) + // uint16_t channel; // the channel in which threshold crossing was detected (index in channel array, not absolute channel number). + // uint8_t color[3]; + // float pcProj[2]; + // uint16_t samplingFrequencyHz; + // uint16_t data[MAX_NUMBER_OF_SPIKE_CHANNELS* MAX_NUMBER_OF_SPIKE_CHANNEL_SAMPLES]; + // float gain[MAX_NUMBER_OF_SPIKE_CHANNELS]; + // uint16_t threshold[MAX_NUMBER_OF_SPIKE_CHANNELS]; + + s->timestamp = getTimestamp (currentChannel) + peakIndex; + s->nSamples = spikeLength; + + const int chan = *(electrodes[electrodeNumber]->channels + currentChannel); + + s->gain[currentChannel] = (int) (1.0f / channels[chan]->bitVolts) * 1000; s->threshold[currentChannel] = (int) *(electrodes[electrodeNumber]->thresholds+currentChannel); // / channels[chan]->bitVolts * 1000; // cycle through buffer - if (isChannelActive(electrodeNumber, currentChannel)) + if (isChannelActive (electrodeNumber, currentChannel)) { - - for (int sample = 0; sample < spikeLength; sample++) + for (int sample = 0; sample < spikeLength; ++sample) { - // warning -- be careful of bitvolts conversion - s->data[currentIndex] = uint16(getNextSample(*(electrodes[electrodeNumber]->channels+currentChannel)) / channels[chan]->bitVolts + 32768); + s->data[currentIndex] = uint16 (getNextSample (*(electrodes[electrodeNumber]->channels+currentChannel)) + / channels[chan]->bitVolts + 32768); - currentIndex++; - sampleIndex++; + ++currentIndex; + ++sampleIndex; //std::cout << currentIndex << std::endl; - } } else { - for (int sample = 0; sample < spikeLength; sample++) + for (int sample = 0; sample < spikeLength; ++sample) { - // insert a blank spike if the s->data[currentIndex] = 0; - currentIndex++; - sampleIndex++; - + ++currentIndex; + ++sampleIndex; //std::cout << currentIndex << std::endl; - } } - sampleIndex -= spikeLength; // reset sample index - - } -void SpikeDetector::handleEvent(int eventType, MidiMessage& event, int sampleNum) -{ +void SpikeDetector::handleEvent (int eventType, MidiMessage& event, int sampleNum) +{ if (eventType == TIMESTAMP) { const uint8* dataptr = event.getRawData(); - memcpy(×tamp, dataptr + 4, 8); // remember to skip first four bytes + memcpy (×tamp, dataptr + 4, 8); // remember to skip first four bytes } - - } -void SpikeDetector::process(AudioSampleBuffer& buffer, - MidiBuffer& events) -{ +void SpikeDetector::process (AudioSampleBuffer& buffer, MidiBuffer& events) +{ // cycle through electrodes SimpleElectrode* electrode; dataBuffer = &buffer; - checkForEvents(events); // need to find any timestamp events before extracting spikes + checkForEvents (events); // need to find any timestamp events before extracting spikes //std::cout << dataBuffer.getMagnitude(0,nSamples) << std::endl; - for (int i = 0; i < electrodes.size(); i++) + for (int i = 0; i < electrodes.size(); ++i) { - // std::cout << "ELECTRODE " << i << std::endl; electrode = electrodes[i]; @@ -459,208 +461,157 @@ void SpikeDetector::process(AudioSampleBuffer& buffer, sampleIndex = electrode->lastBufferIndex - 1; // subtract 1 to account for // increment at start of getNextSample() - int nSamples = getNumSamples(*electrode->channels); + const int nSamples = getNumSamples (*electrode->channels); // cycle through samples - while (samplesAvailable(nSamples)) + while (samplesAvailable (nSamples)) { + ++sampleIndex; - sampleIndex++; // cycle through channels - for (int chan = 0; chan < electrode->numChannels; chan++) + for (int chan = 0; chan < electrode->numChannels; ++chan) { // std::cout << " channel " << chan << std::endl; - if (*(electrode->isActive+chan)) + if (*(electrode->isActive + chan)) { - int currentChannel = *(electrode->channels+chan); + int currentChannel = *(electrode->channels + chan); - if (-getNextSample(currentChannel) > *(electrode->thresholds+chan)) // trigger spike + if (-getNextSample (currentChannel) > *(electrode->thresholds + chan)) // trigger spike { //std::cout << "Spike detected on electrode " << i << std::endl; // find the peak int peakIndex = sampleIndex; - while (-getCurrentSample(currentChannel) < - -getNextSample(currentChannel) && - sampleIndex < peakIndex + electrode->postPeakSamples) + while (-getCurrentSample(currentChannel) < -getNextSample(currentChannel) + && sampleIndex < peakIndex + electrode->postPeakSamples) { - sampleIndex++; + ++sampleIndex; } peakIndex = sampleIndex; - sampleIndex -= (electrode->prePeakSamples+1); - -// uint8_t eventType; -// int64_t timestamp; -// int64_t timestamp_software; -// uint16_t source; // used internally, the index of the electrode in the electrode array -// uint16_t nChannels; -// uint16_t nSamples; -// uint16_t sortedId; // sorted unit ID (or 0 if unsorted) -// uint16_t electrodeID; // unique electrode ID (regardless electrode position in the array) -// uint16_t channel; // the channel in which threshold crossing was detected (index in channel array, not absolute channel number). -// uint8_t color[3]; -// float pcProj[2]; -// uint16_t samplingFrequencyHz; -// uint16_t data[MAX_NUMBER_OF_SPIKE_CHANNELS* MAX_NUMBER_OF_SPIKE_CHANNEL_SAMPLES]; -// float gain[MAX_NUMBER_OF_SPIKE_CHANNELS]; -// uint16_t threshold[MAX_NUMBER_OF_SPIKE_CHANNELS]; + sampleIndex -= (electrode->prePeakSamples + 1); + + //uint8_t eventType; + //int64_t timestamp; + //int64_t timestamp_software; + //uint16_t source; // used internally, the index of the electrode in the electrode array + //uint16_t nChannels; + //uint16_t nSamples; + //uint16_t sortedId; // sorted unit ID (or 0 if unsorted) + //uint16_t electrodeID; // unique electrode ID (regardless electrode position in the array) + //uint16_t channel; // the channel in which threshold crossing was detected (index in channel array, not absolute channel number). + //uint8_t color[3]; + //float pcProj[2]; + //uint16_t samplingFrequencyHz; + //uint16_t data[MAX_NUMBER_OF_SPIKE_CHANNELS* MAX_NUMBER_OF_SPIKE_CHANNEL_SAMPLES]; + //float gain[MAX_NUMBER_OF_SPIKE_CHANNELS]; + //uint16_t threshold[MAX_NUMBER_OF_SPIKE_CHANNELS]; SpikeObject newSpike; - newSpike.timestamp = 0; //getTimestamp(currentChannel) + peakIndex; - newSpike.timestamp_software = -1; - newSpike.source = i; - newSpike.nChannels = electrode->numChannels; - newSpike.sortedId = 0; - newSpike.electrodeID = electrode->electrodeID; - newSpike.channel = 0; + newSpike.timestamp = 0; //getTimestamp(currentChannel) + peakIndex; + newSpike.timestamp_software = -1; + newSpike.source = i; + newSpike.nChannels = electrode->numChannels; + newSpike.sortedId = 0; + newSpike.electrodeID = electrode->electrodeID; + newSpike.channel = 0; newSpike.samplingFrequencyHz = sampleRateForElectrode; currentIndex = 0; // package spikes; - for (int channel = 0; channel < electrode->numChannels; channel++) + for (int channel = 0; channel < electrode->numChannels; ++channel) { - - addWaveformToSpikeObject(&newSpike, - peakIndex, - i, - channel); - - // if (*(electrode->isActive+currentChannel)) - // { - - // createSpikeEvent(peakIndex, // peak index - // i, // electrodeNumber - // currentChannel, // channel number - // events); // event buffer - - - // } // end if channel is active - + addWaveformToSpikeObject (&newSpike, + peakIndex, + i, + channel); } //for (int xxx = 0; xxx < 1000; xxx++) // overload with spikes for testing purposes - addSpikeEvent(&newSpike, events, peakIndex); + addSpikeEvent (&newSpike, events, peakIndex); // advance the sample index sampleIndex = peakIndex + electrode->postPeakSamples; - break; // quit spike "for" loop - } // end spike trigger + // quit spike "for" loop + break; - } // end if channel is active - } // end cycle through channels on electrode + // end spike trigger + } - } // end cycle through samples + // end if channel is active + } - electrode->lastBufferIndex = sampleIndex - nSamples; // should be negative + // end cycle through channels on electrode + } - //jassert(electrode->lastBufferIndex < 0); + // end cycle through samples + } + + electrode->lastBufferIndex = sampleIndex - nSamples; // should be negative if (nSamples > overflowBufferSize) { - - for (int j = 0; j < electrode->numChannels; j++) + for (int j = 0; j < electrode->numChannels; ++j) { - - overflowBuffer.copyFrom(*electrode->channels+j, 0, - buffer, *electrode->channels+j, - nSamples-overflowBufferSize, - overflowBufferSize); - + overflowBuffer.copyFrom (*electrode->channels+j, + 0, + buffer, + *electrode->channels + j, + nSamples-overflowBufferSize, + overflowBufferSize); } - useOverflowBuffer.set(i, true); - + useOverflowBuffer.set (i, true); } else { - useOverflowBuffer.set(i, false); + useOverflowBuffer.set (i, false); } - } // end cycle through electrodes - - // copy end of this buffer into the overflow buffer - - //std::cout << "Copying buffer" << std::endl; - // std::cout << "nSamples: " << nSamples; - //std::cout << "overflowBufferSize:" << overflowBufferSize; - - //std::cout << "sourceStartSample = " << nSamples-overflowBufferSize << std::endl; - // std::cout << "numSamples = " << overflowBufferSize << std::endl; - // std::cout << "buffer size = " << buffer.getNumSamples() << std::endl; - - - - - + // end cycle through electrodes + } } -float SpikeDetector::getNextSample(int& chan) -{ - - - //if (useOverflowBuffer) - //{ +float SpikeDetector::getNextSample (int& chan) +{ if (sampleIndex < 0) { - // std::cout << " sample index " << sampleIndex << "from overflowBuffer" << std::endl; - int ind = overflowBufferSize + sampleIndex; + const int ind = overflowBufferSize + sampleIndex; if (ind < overflowBuffer.getNumSamples()) - return *overflowBuffer.getWritePointer(chan, ind); + return *overflowBuffer.getWritePointer (chan, ind); else return 0; } else { - // useOverflowBuffer = false; - // std::cout << " sample index " << sampleIndex << "from regular buffer" << std::endl; - if (sampleIndex < dataBuffer->getNumSamples()) - return *dataBuffer->getWritePointer(chan, sampleIndex); + return *dataBuffer->getWritePointer (chan, sampleIndex); else return 0; } - //} else { - // std::cout << " sample index " << sampleIndex << "from regular buffer" << std::endl; - // return *dataBuffer.getWritePointer(chan, sampleIndex); - //} - } -float SpikeDetector::getCurrentSample(int& chan) -{ - - // if (useOverflowBuffer) - // { - // return *overflowBuffer.getWritePointer(chan, overflowBufferSize + sampleIndex - 1); - // } else { - // return *dataBuffer.getWritePointer(chan, sampleIndex - 1); - // } +float SpikeDetector::getCurrentSample (int& chan) +{ if (sampleIndex < 1) { - //std::cout << " sample index " << sampleIndex << "from overflowBuffer" << std::endl; - return *overflowBuffer.getWritePointer(chan, overflowBufferSize + sampleIndex - 1); + return *overflowBuffer.getWritePointer (chan, overflowBufferSize + sampleIndex - 1); } else { - // useOverflowBuffer = false; - // std::cout << " sample index " << sampleIndex << "from regular buffer" << std::endl; - return *dataBuffer->getWritePointer(chan, sampleIndex - 1); + return *dataBuffer->getWritePointer (chan, sampleIndex - 1); } - //} else { - } -bool SpikeDetector::samplesAvailable(int nSamples) +bool SpikeDetector::samplesAvailable (int nSamples) { - if (sampleIndex > nSamples - overflowBufferSize/2) { return false; @@ -669,39 +620,33 @@ bool SpikeDetector::samplesAvailable(int nSamples) { return true; } - } -void SpikeDetector::saveCustomParametersToXml(XmlElement* parentElement) +void SpikeDetector::saveCustomParametersToXml (XmlElement* parentElement) { - - for (int i = 0; i < electrodes.size(); i++) + for (int i = 0; i < electrodes.size(); ++i) { - XmlElement* electrodeNode = parentElement->createNewChildElement("ELECTRODE"); - electrodeNode->setAttribute("name", electrodes[i]->name); - electrodeNode->setAttribute("numChannels", electrodes[i]->numChannels); - electrodeNode->setAttribute("prePeakSamples", electrodes[i]->prePeakSamples); - electrodeNode->setAttribute("postPeakSamples", electrodes[i]->postPeakSamples); - electrodeNode->setAttribute("electrodeID", electrodes[i]->electrodeID); - - for (int j = 0; j < electrodes[i]->numChannels; j++) + XmlElement* electrodeNode = parentElement->createNewChildElement ("ELECTRODE"); + electrodeNode->setAttribute ("name", electrodes[i]->name); + electrodeNode->setAttribute ("numChannels", electrodes[i]->numChannels); + electrodeNode->setAttribute ("prePeakSamples", electrodes[i]->prePeakSamples); + electrodeNode->setAttribute ("postPeakSamples", electrodes[i]->postPeakSamples); + electrodeNode->setAttribute ("electrodeID", electrodes[i]->electrodeID); + + for (int j = 0; j < electrodes[i]->numChannels; ++j) { - XmlElement* channelNode = electrodeNode->createNewChildElement("SUBCHANNEL"); - channelNode->setAttribute("ch",*(electrodes[i]->channels+j)); - channelNode->setAttribute("thresh",*(electrodes[i]->thresholds+j)); - channelNode->setAttribute("isActive",*(electrodes[i]->isActive+j)); - + XmlElement* channelNode = electrodeNode->createNewChildElement ("SUBCHANNEL"); + channelNode->setAttribute ("ch", *(electrodes[i]->channels + j)); + channelNode->setAttribute ("thresh", *(electrodes[i]->thresholds + j)); + channelNode->setAttribute ("isActive", *(electrodes[i]->isActive + j)); } } - - } + void SpikeDetector::loadCustomParametersFromXml() { - - if (parametersAsXml != nullptr) // prevent double-loading { // use parametersAsXml to restore state @@ -710,45 +655,41 @@ void SpikeDetector::loadCustomParametersFromXml() int electrodeIndex = -1; - forEachXmlChildElement(*parametersAsXml, xmlNode) + forEachXmlChildElement (*parametersAsXml, xmlNode) { - if (xmlNode->hasTagName("ELECTRODE")) + if (xmlNode->hasTagName ("ELECTRODE")) { - - electrodeIndex++; + ++electrodeIndex; std::cout << "ELECTRODE>>>" << std::endl; - int channelsPerElectrode = xmlNode->getIntAttribute("numChannels"); - int electrodeID = xmlNode->getIntAttribute("electrodeID"); + const int channelsPerElectrode = xmlNode->getIntAttribute ("numChannels"); + const int electrodeID = xmlNode->getIntAttribute ("electrodeID"); - sde->addElectrode(channelsPerElectrode, electrodeID); + sde->addElectrode (channelsPerElectrode, electrodeID); - setElectrodeName(electrodeIndex+1, xmlNode->getStringAttribute("name")); + setElectrodeName (electrodeIndex + 1, xmlNode->getStringAttribute ("name")); sde->refreshElectrodeList(); int channelIndex = -1; - forEachXmlChildElement(*xmlNode, channelNode) + forEachXmlChildElement (*xmlNode, channelNode) { - if (channelNode->hasTagName("SUBCHANNEL")) + if (channelNode->hasTagName ("SUBCHANNEL")) { - channelIndex++; + ++channelIndex; std::cout << "Subchannel " << channelIndex << std::endl; - setChannel(electrodeIndex, channelIndex, channelNode->getIntAttribute("ch")); - setChannelThreshold(electrodeIndex, channelIndex, channelNode->getDoubleAttribute("thresh")); - setChannelActive(electrodeIndex, channelIndex, channelNode->getBoolAttribute("isActive")); + setChannel (electrodeIndex, channelIndex, channelNode->getIntAttribute ("ch")); + setChannelThreshold (electrodeIndex, channelIndex, channelNode->getDoubleAttribute ("thresh")); + setChannelActive (electrodeIndex, channelIndex, channelNode->getBoolAttribute ("isActive")); } } - - } } sde->checkSettings(); } - } diff --git a/Source/Plugins/BasicSpikeDisplay/SpikeDetector/SpikeDetector.h b/Source/Plugins/BasicSpikeDisplay/SpikeDetector/SpikeDetector.h index 62d4eff2f..5f9bd865a 100644 --- a/Source/Plugins/BasicSpikeDisplay/SpikeDetector/SpikeDetector.h +++ b/Source/Plugins/BasicSpikeDisplay/SpikeDetector/SpikeDetector.h @@ -2,7 +2,7 @@ ------------------------------------------------------------------ This file is part of the Open Ephys GUI - Copyright (C) 2014 Open Ephys + Copyright (C) 2016 Open Ephys ------------------------------------------------------------------ @@ -29,155 +29,154 @@ #include <SpikeLib.h> +class SpikeDetectorEditor; + struct SimpleElectrode { - String name; int numChannels; int prePeakSamples, postPeakSamples; int lastBufferIndex; - bool isMonitored; int electrodeID; int sourceNodeId; + bool isMonitored; + HeapBlock<int> channels; HeapBlock<double> thresholds; HeapBlock<bool> isActive; - }; -class SpikeDetectorEditor; /** + Detects spikes in a continuous signal and outputs events containing the spike data. - Detects spikes in a continuous signal and outputs events containing the spike data. - - @see GenericProcessor, SpikeDetectorEditor - + @see GenericProcessor, SpikeDetectorEditor */ - class SpikeDetector : public GenericProcessor - { public: - - // CONSTRUCTOR AND DESTRUCTOR // - - /** constructor */ SpikeDetector(); - - /** destructor */ ~SpikeDetector(); - - // PROCESSOR METHODS // - - /** Processes an incoming continuous buffer and places new - spikes into the event buffer. */ - void process(AudioSampleBuffer& buffer, MidiBuffer& events); + /** Processes an incoming continuous buffer and places new spikes into the event buffer. */ + void process (AudioSampleBuffer& buffer, MidiBuffer& events) override; /** Used to alter parameters of data acquisition. */ - void setParameter(int parameterIndex, float newValue); + void setParameter (int parameterIndex, float newValue) override; /** Called whenever the signal chain is altered. */ - void updateSettings(); + void updateSettings() override; /** Called prior to start of acquisition. */ - bool enable(); + bool enable() override; /** Called after acquisition is finished. */ - bool disable(); + bool disable() override; /** Creates the SpikeDetectorEditor. */ - AudioProcessorEditor* createEditor(); + AudioProcessorEditor* createEditor() override; + void saveCustomParametersToXml (XmlElement* parentElement) override; + void loadCustomParametersFromXml() override; - // INTERNAL BUFFERS // + // INTERNAL BUFFERS + // ===================================================================== /** Extra samples are placed in this buffer to allow seamless transitions between callbacks. */ AudioSampleBuffer overflowBuffer; + // ===================================================================== - // CREATE AND DELETE ELECTRODES // - + // CREATE AND DELETE ELECTRODES + // ===================================================================== /** Adds an electrode with n channels to be processed. */ - bool addElectrode(int nChans, int electrodeID = 0); + bool addElectrode (int nChans, int electrodeID = 0); /** Removes an electrode with a given index. */ - bool removeElectrode(int index); - + bool removeElectrode (int index); + // ===================================================================== - // EDIT AND QUERY ELECTRODE SETTINGS // + // EDIT AND QUERY ELECTRODE SETTINGS/ + // ===================================================================== /** Returns the number of channels for a given electrode. */ - int getNumChannels(int index); + int getNumChannels (int index) const; - /** Edits the mapping between input channels and electrode channels. */ - void setChannel(int electrodeIndex, int channelNum, int newChannel); + /** Returns the continuous channel that maps to a given electrode channel. */ + int getChannel (int index, int chan) const; - /** Returns the continuous channel that maps to a given - electrode channel. */ - int getChannel(int index, int chan); + bool isChannelActive (int electrodeIndex, int channelNum); - /** Sets the name of a given electrode. */ - void setElectrodeName(int index, String newName); + /** Edits the mapping between input channels and electrode channels. */ + void setChannel (int electrodeIndex, int channelNum, int newChannel); - /** */ - void setChannelActive(int electrodeIndex, int channelNum, bool active); + /** Sets the name of a given electrode. */ + void setElectrodeName (int index, String newName); - /** */ - bool isChannelActive(int electrodeIndex, int channelNum); + void setChannelActive (int electrodeIndex, int channelNum, bool active); + // ===================================================================== - // RETURN STRING ARRAYS // + // RETURN STRING ARRAYS + // ===================================================================== /** Returns a StringArray containing the names of all electrodes */ - StringArray getElectrodeNames(); + StringArray getElectrodeNames() const; + // TODO: now it returns nothing. Need to double-check it. /** Returns array of electrodes. */ - void getElectrodes(Array<SimpleElectrode*>& electrodeArray); + void getElectrodes (Array<SimpleElectrode*>& electrodeArray); /** Returns array of electrodes. */ - SimpleElectrode* getActiveElectrode(); + SimpleElectrode* getActiveElectrode() const; /** Sets the current electrode index */ - SimpleElectrode* setCurrentElectrodeIndex(int); + SimpleElectrode* setCurrentElectrodeIndex (int); /** Returns a list of possible electrode types (e.g., stereotrode, tetrode). */ StringArray electrodeTypes; + // ===================================================================== - void setChannelThreshold(int electrodeNum, int channelNum, float threshold); + void setChannelThreshold (int electrodeNum, int channelNum, float threshold); - double getChannelThreshold(int electrodeNum, int channelNum); + double getChannelThreshold (int electrodeNum, int channelNum) const; - void saveCustomParametersToXml(XmlElement* parentElement); - void loadCustomParametersFromXml(); private: + void handleEvent (int eventType, MidiMessage& event, int sampleNum) override; + + float getDefaultThreshold() const; + + float getNextSample (int& chan); + float getCurrentSample (int& chan); + bool samplesAvailable (int nSamples); + + void addSpikeEvent (SpikeObject* s, MidiBuffer& eventBuffer, int peakIndex); + void addWaveformToSpikeObject (SpikeObject* s, + int& peakIndex, + int& electrodeNumber, + int& currentChannel); + + void resetElectrode (SimpleElectrode*); + /** Pointer to a continuous buffer. */ AudioSampleBuffer* dataBuffer; - float getDefaultThreshold(); - int overflowBufferSize; - int sampleIndex; Array<int> electrodeCounter; - float getNextSample(int& chan); - float getCurrentSample(int& chan); - bool samplesAvailable(int nSamples); - Array<bool> useOverflowBuffer; int currentElectrode; int currentChannelIndex; int currentIndex; - // uint8_t* spikeBuffer;///[256]; - HeapBlock<uint8_t> spikeBuffer; + // uint8_t* spikeBuffer;///[256]; + HeapBlock<uint8_t> spikeBuffer; int64 timestamp; OwnedArray<SimpleElectrode> electrodes; @@ -188,20 +187,9 @@ private: // int& currentChannel, // MidiBuffer& eventBuffer); - void handleEvent(int eventType, MidiMessage& event, int sampleNum); - - void addSpikeEvent(SpikeObject* s, MidiBuffer& eventBuffer, int peakIndex); - void addWaveformToSpikeObject(SpikeObject* s, - int& peakIndex, - int& electrodeNumber, - int& currentChannel); - - void resetElectrode(SimpleElectrode*); - uint16_t sampleRateForElectrode; - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SpikeDetector); - + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SpikeDetector); }; diff --git a/Source/Plugins/BasicSpikeDisplay/SpikeDisplayNode/SpikeDisplayNode.cpp b/Source/Plugins/BasicSpikeDisplay/SpikeDisplayNode/SpikeDisplayNode.cpp index 41dce7d4a..d02db159d 100644 --- a/Source/Plugins/BasicSpikeDisplay/SpikeDisplayNode/SpikeDisplayNode.cpp +++ b/Source/Plugins/BasicSpikeDisplay/SpikeDisplayNode/SpikeDisplayNode.cpp @@ -2,7 +2,7 @@ ------------------------------------------------------------------ This file is part of the Open Ephys GUI - Copyright (C) 2014 Open Ephys + Copyright (C) 2016 Open Ephys ------------------------------------------------------------------ @@ -28,94 +28,91 @@ SpikeDisplayNode::SpikeDisplayNode() - : GenericProcessor("Spike Viewer"), displayBufferSize(5), redrawRequested(false), - isRecording(false) + : GenericProcessor ("Spike Viewer") + , displayBufferSize (5) + , redrawRequested (false) + , isRecording (false) { - - + setProcessorType (PROCESSOR_TYPE_SINK); } + SpikeDisplayNode::~SpikeDisplayNode() { - } + AudioProcessorEditor* SpikeDisplayNode::createEditor() { - //std::cout<<"Creating SpikeDisplayCanvas."<<std::endl; - - editor = new SpikeDisplayEditor(this); + editor = new SpikeDisplayEditor (this); return editor; - } + void SpikeDisplayNode::updateSettings() { //std::cout << "Setting num inputs on SpikeDisplayNode to " << getNumInputs() << std::endl; electrodes.clear(); - for (int i = 0; i < eventChannels.size(); i++) + for (int i = 0; i < eventChannels.size(); ++i) { ChannelType type = eventChannels[i]->getType(); if (type == ELECTRODE_CHANNEL) { - Electrode elec; - elec.numChannels = static_cast<SpikeChannel*>(eventChannels[i]->extraData.get())->numChannels; + elec.numChannels = static_cast<SpikeChannel*> (eventChannels[i]->extraData.get())->numChannels; elec.name = eventChannels[i]->getName(); elec.currentSpikeIndex = 0; - elec.mostRecentSpikes.ensureStorageAllocated(displayBufferSize); + elec.mostRecentSpikes.ensureStorageAllocated (displayBufferSize); - for (int j = 0; j < elec.numChannels; j++) + for (int j = 0; j < elec.numChannels; ++j) { - elec.displayThresholds.add(0); - elec.detectorThresholds.add(0); + elec.displayThresholds.add (0); + elec.detectorThresholds.add (0); } - electrodes.add(elec); - + electrodes.add (elec); } } - } -// void SpikeDisplayNode::updateVisualizer() -// { - -// } bool SpikeDisplayNode::enable() { std::cout << "SpikeDisplayNode::enable()" << std::endl; SpikeDisplayEditor* editor = (SpikeDisplayEditor*) getEditor(); - CoreServices::RecordNode::registerSpikeSource(this); - for (int i = 0; i < electrodes.size(); i ++) - { - Electrode& elec = electrodes.getReference(i); - SpikeRecordInfo *recElec = new SpikeRecordInfo(); - recElec->name = elec.name; - recElec->numChannels = elec.numChannels; - recElec->sampleRate = settings.sampleRate; - elec.recordIndex = CoreServices::RecordNode::addSpikeElectrode(recElec); - } + CoreServices::RecordNode::registerSpikeSource(this); + for (int i = 0; i < electrodes.size(); ++i) + { + Electrode& elec = electrodes.getReference (i); + + SpikeRecordInfo* recElec = new SpikeRecordInfo(); + recElec->name = elec.name; + recElec->numChannels = elec.numChannels; + recElec->sampleRate = settings.sampleRate; + elec.recordIndex = CoreServices::RecordNode::addSpikeElectrode (recElec); + } editor->enable(); return true; - } + bool SpikeDisplayNode::disable() { std::cout << "SpikeDisplayNode disabled!" << std::endl; + SpikeDisplayEditor* editor = (SpikeDisplayEditor*) getEditor(); editor->disable(); + return true; } -int SpikeDisplayNode::getNumberOfChannelsForElectrode(int i) + +int SpikeDisplayNode::getNumberOfChannelsForElectrode (int i) const { if (i > -1 && i < electrodes.size()) { @@ -127,9 +124,9 @@ int SpikeDisplayNode::getNumberOfChannelsForElectrode(int i) } } -String SpikeDisplayNode::getNameForElectrode(int i) -{ +String SpikeDisplayNode::getNameForElectrode (int i) const +{ if (i > -1 && i < electrodes.size()) { return electrodes[i].name; @@ -140,170 +137,156 @@ String SpikeDisplayNode::getNameForElectrode(int i) } } -void SpikeDisplayNode::addSpikePlotForElectrode(SpikePlot* sp, int i) + +void SpikeDisplayNode::addSpikePlotForElectrode (SpikePlot* sp, int i) { Electrode& e = electrodes.getReference(i); e.spikePlot = sp; - } + void SpikeDisplayNode::removeSpikePlots() { - for (int i = 0; i < getNumElectrodes(); i++) + for (int i = 0; i < getNumElectrodes(); ++i) { - Electrode& e = electrodes.getReference(i); + Electrode& e = electrodes.getReference (i); e.spikePlot = nullptr; } } -int SpikeDisplayNode::getNumElectrodes() + +int SpikeDisplayNode::getNumElectrodes() const { return electrodes.size(); - } + void SpikeDisplayNode::startRecording() { - - setParameter(1, 0.0f); // need to use the 'setParameter' method to interact with 'process' + setParameter (1, 0.0f); // need to use the 'setParameter' method to interact with 'process' } + void SpikeDisplayNode::stopRecording() { - setParameter(0, 0.0f); // need to use the 'setParameter' method to interact with 'process' + setParameter (0, 0.0f); // need to use the 'setParameter' method to interact with 'process' } -void SpikeDisplayNode::setParameter(int param, float val) +void SpikeDisplayNode::setParameter (int param, float val) { //std::cout<<"SpikeDisplayNode got Param:"<< param<< " with value:"<<val<<std::endl; if (param == 0) // stop recording { isRecording = false; - } else if (param == 1) // start recording { isRecording = true; - } else if (param == 2) // redraw { redrawRequested = true; - } - } - -void SpikeDisplayNode::process(AudioSampleBuffer& buffer, MidiBuffer& events) +void SpikeDisplayNode::process (AudioSampleBuffer& buffer, MidiBuffer& events) { - - checkForEvents(events); // automatically calls 'handleEvent + checkForEvents (events); // automatically calls 'handleEvent if (redrawRequested) { // update incoming thresholds - for (int i = 0; i < getNumElectrodes(); i++) + for (int i = 0; i < getNumElectrodes(); ++i) { - Electrode& e = electrodes.getReference(i); // update thresholds - for (int j = 0; j < e.numChannels; j++) + for (int j = 0; j < e.numChannels; ++j) { - e.displayThresholds.set(j, - e.spikePlot->getDisplayThresholdForChannel(j)); + e.displayThresholds.set (j, + e.spikePlot->getDisplayThresholdForChannel (j)); - e.spikePlot->setDetectorThresholdForChannel(j, e.detectorThresholds[j]); + e.spikePlot->setDetectorThresholdForChannel (j, e.detectorThresholds[j]); } // transfer buffered spikes to spike plot - for (int j = 0; j < e.currentSpikeIndex; j++) + for (int j = 0; j < e.currentSpikeIndex; ++j) { //std::cout << "Transferring spikes." << std::endl; - e.spikePlot->processSpikeObject(e.mostRecentSpikes[j]); + e.spikePlot->processSpikeObject (e.mostRecentSpikes[j]); e.currentSpikeIndex = 0; } - } redrawRequested = false; } - } -void SpikeDisplayNode::handleEvent(int eventType, MidiMessage& event, int samplePosition) -{ +void SpikeDisplayNode::handleEvent (int eventType, MidiMessage& event, int samplePosition) +{ //std::cout << "Received event of type " << eventType << std::endl; if (eventType == SPIKE) { - const uint8_t* dataptr = event.getRawData(); int bufferSize = event.getRawDataSize(); if (bufferSize > 0) { - SpikeObject newSpike; - bool isValid = unpackSpike(&newSpike, dataptr, bufferSize); + bool isValid = unpackSpike (&newSpike, dataptr, bufferSize); if (isValid) { int electrodeNum = newSpike.source; - Electrode& e = electrodes.getReference(electrodeNum); + Electrode& e = electrodes.getReference (electrodeNum); // std::cout << electrodeNum << std::endl; bool aboveThreshold = false; // update threshold / check threshold - for (int i = 0; i < e.numChannels; i++) + for (int i = 0; i < e.numChannels; ++i) { - e.detectorThresholds.set(i, float(newSpike.threshold[i])); // / float(newSpike.gain[i])); + e.detectorThresholds.set (i, float (newSpike.threshold[i])); // / float(newSpike.gain[i])); - aboveThreshold = aboveThreshold | checkThreshold(i, e.displayThresholds[i], newSpike); + aboveThreshold = aboveThreshold | checkThreshold (i, e.displayThresholds[i], newSpike); } if (aboveThreshold) { - // add to buffer if (e.currentSpikeIndex < displayBufferSize) { // std::cout << "Adding spike " << e.currentSpikeIndex + 1 << std::endl; - e.mostRecentSpikes.set(e.currentSpikeIndex, newSpike); + e.mostRecentSpikes.set (e.currentSpikeIndex, newSpike); e.currentSpikeIndex++; } // save spike if (isRecording) { - CoreServices::RecordNode::writeSpike(newSpike,e.recordIndex); + CoreServices::RecordNode::writeSpike (newSpike, e.recordIndex); } } - } - } - } - } -bool SpikeDisplayNode::checkThreshold(int chan, float thresh, SpikeObject& s) + +bool SpikeDisplayNode::checkThreshold (int chan, float thresh, SpikeObject& s) { int sampIdx = s.nSamples*chan; - for (int i = 0; i < s.nSamples-1; i++) + for (int i = 0; i < s.nSamples-1; ++i) { - - if (float(s.data[sampIdx]-32768)/float(*s.gain)*1000.0f > thresh) + if (float (s.data[sampIdx]-32768) / float (*s.gain) * 1000.0f > thresh) { return true; } diff --git a/Source/Plugins/BasicSpikeDisplay/SpikeDisplayNode/SpikeDisplayNode.h b/Source/Plugins/BasicSpikeDisplay/SpikeDisplayNode/SpikeDisplayNode.h index cabe7b4a1..2c7ef00df 100644 --- a/Source/Plugins/BasicSpikeDisplay/SpikeDisplayNode/SpikeDisplayNode.h +++ b/Source/Plugins/BasicSpikeDisplay/SpikeDisplayNode/SpikeDisplayNode.h @@ -2,7 +2,7 @@ ------------------------------------------------------------------ This file is part of the Open Ephys GUI - Copyright (C) 2014 Open Ephys + Copyright (C) 2016 Open Ephys ------------------------------------------------------------------ @@ -31,70 +31,60 @@ class DataViewport; class SpikePlot; -/** - Takes in MidiEvents and extracts SpikeObjects from the MidiEvent buffers. - Those Events are then held in a queue until they are pulled by the SpikeDisplayCanvas. +/** + Takes in MidiEvents and extracts SpikeObjects from the MidiEvent buffers. + Those Events are then held in a queue until they are pulled by the SpikeDisplayCanvas. @see GenericProcessor, SpikeDisplayEditor, SpikeDisplayCanvas - */ - class SpikeDisplayNode : public GenericProcessor { public: - SpikeDisplayNode(); ~SpikeDisplayNode(); - AudioProcessorEditor* createEditor(); - - bool isSink() - { - return true; - } + AudioProcessorEditor* createEditor() override; - void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages); + void process (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) override; - void setParameter(int, float); + void setParameter (int parameterIndex, float newValue) override; - void handleEvent(int, MidiMessage&, int); + void handleEvent (int, MidiMessage&, int) override; - void updateSettings(); + void updateSettings() override; - bool enable(); - bool disable(); + bool enable() override; + bool disable() override; - void startRecording(); - void stopRecording(); + void startRecording() override; + void stopRecording() override; - String getNameForElectrode(int i); - int getNumberOfChannelsForElectrode(int i); - int getNumElectrodes(); + String getNameForElectrode (int i) const; + int getNumberOfChannelsForElectrode (int i) const; + int getNumElectrodes() const; - void addSpikePlotForElectrode(SpikePlot* sp, int i); + void addSpikePlotForElectrode (SpikePlot* sp, int i); void removeSpikePlots(); - bool checkThreshold(int, float, SpikeObject&); + bool checkThreshold (int, float, SpikeObject&); -private: +private: struct Electrode { String name; int numChannels; + int recordIndex; + int currentSpikeIndex; Array<float> displayThresholds; Array<float> detectorThresholds; Array<SpikeObject> mostRecentSpikes; - int currentSpikeIndex; SpikePlot* spikePlot; - - int recordIndex; - }; Array<Electrode> electrodes; @@ -104,19 +94,18 @@ private: // members for recording bool isRecording; - // bool signalFilesShouldClose; - // RecordNode* recordNode; - // String baseDirectory; - // File dataDirectory; - // uint8_t* spikeBuffer; - // SpikeObject currentSpike; - - // uint16 recordingNumber; + // bool signalFilesShouldClose; + // RecordNode* recordNode; + // String baseDirectory; + // File dataDirectory; + // uint8_t* spikeBuffer; + // SpikeObject currentSpike; -// CriticalSection* diskWriteLock; + // uint16 recordingNumber; - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SpikeDisplayNode); + // CriticalSection* diskWriteLock; + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SpikeDisplayNode); }; diff --git a/Source/Plugins/ChannelMappingNode/ChannelMappingNode.cpp b/Source/Plugins/ChannelMappingNode/ChannelMappingNode.cpp index 11886af7a..e547d4c00 100644 --- a/Source/Plugins/ChannelMappingNode/ChannelMappingNode.cpp +++ b/Source/Plugins/ChannelMappingNode/ChannelMappingNode.cpp @@ -1,24 +1,23 @@ /* ------------------------------------------------------------------- + ------------------------------------------------------------------ -This file is part of the Open Ephys GUI -Copyright (C) 2014 Open Ephys + This file is part of the Open Ephys GUI + Copyright (C) 2016 Open Ephys ------------------------------------------------------------------- + ------------------------------------------------------------------ -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see <http://www.gnu.org/licenses/>. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <stdio.h> @@ -26,34 +25,37 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include "ChannelMappingEditor.h" - ChannelMappingNode::ChannelMappingNode() - : GenericProcessor("Channel Map"), channelBuffer(1,10000) + : GenericProcessor ("Channel Map") + , channelBuffer (1, 10000) { - referenceArray.resize(1024); // make room for 1024 channels - channelArray.resize(1024); + setProcessorType (PROCESSOR_TYPE_FILTER); - for (int i = 0; i < referenceArray.size(); i++) + referenceArray.resize (1024); // make room for 1024 channels + channelArray.resize (1024); + + for (int i = 0; i < referenceArray.size(); ++i) { - channelArray.set(i, i); - referenceArray.set(i,-1); - enabledChannelArray.set(i,true); + channelArray.set (i, i); + referenceArray.set (i, -1); + enabledChannelArray.set (i, true); } - for (int i = 0; i < NUM_REFERENCES; i++) + + for (int i = 0; i < NUM_REFERENCES; ++i) { - referenceChannels.set(i, -1); + referenceChannels.set (i, -1); } - } + ChannelMappingNode::~ChannelMappingNode() { - } + AudioProcessorEditor* ChannelMappingNode::createEditor() { - editor = new ChannelMappingEditor(this, true); + editor = new ChannelMappingEditor (this, true); //std::cout << "Creating editor." << std::endl; @@ -61,55 +63,54 @@ AudioProcessorEditor* ChannelMappingNode::createEditor() } - void ChannelMappingNode::updateSettings() { if (getNumInputs() > 0) - channelBuffer.setSize(getNumInputs(), 10000); - - if (editorIsConfigured) - { - OwnedArray<Channel> oldChannels; - oldChannels.swapWith(channels); - channels.clear(); - Array<bool> recordStates; - - settings.numOutputs = 0; - - for (int i = 0; i < getNumInputs(); i++) - { - if ((enabledChannelArray[channelArray[i]]) && (channelArray[i] < oldChannels.size())) - { - oldChannels[channelArray[i]]->mappedIndex = settings.numOutputs; - channels.add(oldChannels[channelArray[i]]); - recordStates.add(oldChannels[i]->getRecordState()); - settings.numOutputs++; - } - - } - oldChannels.clearQuick(false); - for (int i = 0; i < settings.numOutputs; i++) - { - channels[i]->setRecordState(recordStates[i]); - } - } + channelBuffer.setSize (getNumInputs(), 10000); + + if (editorIsConfigured) + { + OwnedArray<Channel> oldChannels; + oldChannels.swapWith (channels); + channels.clear(); + Array<bool> recordStates; + + settings.numOutputs = 0; + + for (int i = 0; i < getNumInputs(); ++i) + { + if ( (enabledChannelArray[channelArray[i]]) + && (channelArray[i] < oldChannels.size())) + { + oldChannels[channelArray[i]]->mappedIndex = settings.numOutputs; + channels.add (oldChannels[channelArray[i]]); + recordStates.add (oldChannels[i]->getRecordState()); + settings.numOutputs++; + } + } + + oldChannels.clearQuick (false); + for (int i = 0; i < settings.numOutputs; ++i) + { + channels[i]->setRecordState (recordStates[i]); + } + } } -void ChannelMappingNode::setParameter(int parameterIndex, float newValue) +void ChannelMappingNode::setParameter (int parameterIndex, float newValue) { - if (parameterIndex == 1) { - referenceArray.set(currentChannel, (int) newValue); + referenceArray.set (currentChannel, (int) newValue); } else if (parameterIndex == 2) { - referenceChannels.set((int)newValue, currentChannel); + referenceChannels.set ((int)newValue, currentChannel); } else if (parameterIndex == 3) { - enabledChannelArray.set(currentChannel, (newValue != 0) ? true : false); + enabledChannelArray.set (currentChannel, (newValue != 0) ? true : false); } else if (parameterIndex == 4) { @@ -117,16 +118,15 @@ void ChannelMappingNode::setParameter(int parameterIndex, float newValue) } else { - channelArray.set(currentChannel, (int) newValue); + channelArray.set (currentChannel, (int) newValue); } - } -void ChannelMappingNode::process(AudioSampleBuffer& buffer, - MidiBuffer& midiMessages) + +void ChannelMappingNode::process (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) { - int j=0; - int i=0; + int j = 0; + int i = 0; int realChan; // use copy constructor to set the data to refer to @@ -137,34 +137,34 @@ void ChannelMappingNode::process(AudioSampleBuffer& buffer, while (j < settings.numOutputs) { realChan = channelArray[i]; - if ((realChan < channelBuffer.getNumChannels()) && (enabledChannelArray[realChan])) + if ((realChan < channelBuffer.getNumChannels()) + && (enabledChannelArray[realChan])) { // copy it back into the buffer according to the channel mapping - buffer.copyFrom(j, // destChannel - 0, // destStartSample - channelBuffer.getReadPointer(realChan), // source - getNumSamples(j), // numSamples - 1.0f // gain to apply to source (positive for original signal) - ); + buffer.copyFrom (j, // destChannel + 0, // destStartSample + channelBuffer.getReadPointer (realChan), // source + getNumSamples (j), // numSamples + 1.0f); // gain to apply to source (positive for original signal) // now do the referencing - if ((referenceArray[realChan] > -1) && (referenceChannels[referenceArray[realChan]] > -1) + if ((referenceArray[realChan] > -1) + && (referenceChannels[referenceArray[realChan]] > -1) && (referenceChannels[referenceArray[realChan]] < channelBuffer.getNumChannels())) { - buffer.addFrom(j, // destChannel - 0, // destStartSample - channelBuffer, // source - channels[referenceChannels[referenceArray[realChan]]]->index-1, // sourceChannel - 0, // sourceStartSample - getNumSamples(j), // numSamples - -1.0f // gain to apply to source (negative for reference) - ); + buffer.addFrom (j, // destChannel + 0, // destStartSample + channelBuffer, // source + channels[referenceChannels[referenceArray[realChan]]]->index - 1, // sourceChannel + 0, // sourceStartSample + getNumSamples (j), // numSamples + -1.0f); // gain to apply to source (negative for reference) } - j++; + + ++j; } - i++; + ++i; } - } diff --git a/Source/Plugins/ChannelMappingNode/ChannelMappingNode.h b/Source/Plugins/ChannelMappingNode/ChannelMappingNode.h index a74240025..bb8e9ef1b 100644 --- a/Source/Plugins/ChannelMappingNode/ChannelMappingNode.h +++ b/Source/Plugins/ChannelMappingNode/ChannelMappingNode.h @@ -2,7 +2,7 @@ ------------------------------------------------------------------ This file is part of the Open Ephys GUI - Copyright (C) 2014 Open Ephys + Copyright (C) 2016 Open Ephys ------------------------------------------------------------------ @@ -18,7 +18,6 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. - */ #ifndef __CHANNELMAPPINGNODE_H_330E50E0__ @@ -29,38 +28,31 @@ /** + Channel mapping node. - Channel mapping node. - - Allows the user to select a subset of channels, remap their order, and reference them against - any other channel. - - @see GenericProcessor + Allows the user to select a subset of channels, remap their order, and reference them against + any other channel. + @see GenericProcessor */ - class ChannelMappingNode : public GenericProcessor - { public: - ChannelMappingNode(); ~ChannelMappingNode(); - void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages); - void setParameter(int parameterIndex, float newValue); + AudioProcessorEditor* createEditor() override; - AudioProcessorEditor* createEditor(); + void process (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) override; - bool hasEditor() const - { - return true; - } + void setParameter (int parameterIndex, float newValue) override; - void updateSettings(); + bool hasEditor() const override { return true; } + + void updateSettings() override; -private: +private: Array<int> referenceArray; Array<int> referenceChannels; Array<int> channelArray; @@ -70,8 +62,7 @@ private: AudioSampleBuffer channelBuffer; - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ChannelMappingNode); - + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ChannelMappingNode); }; diff --git a/Source/Plugins/EcubeSource/EcubeThread.h b/Source/Plugins/EcubeSource/EcubeThread.h index 13b43aac2..b35fd2828 100644 --- a/Source/Plugins/EcubeSource/EcubeThread.h +++ b/Source/Plugins/EcubeSource/EcubeThread.h @@ -1,25 +1,24 @@ /* ------------------------------------------------------------------- + ------------------------------------------------------------------ -This file is part of the Open Ephys GUI -Copyright (C) 2014 Open Ephys -Copyright (C) 2014 Michael Borisov + This file is part of the Open Ephys GUI + Copyright (C) 2016 Open Ephys + Copyright (C) 2014 Michael Borisov ------------------------------------------------------------------- + ------------------------------------------------------------------ -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see <http://www.gnu.org/licenses/>. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -35,25 +34,24 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. class SourceNode; #if JUCE_WINDOWS -#ifdef ECUBE_SUPPORT -#define ECUBE_COMPILE -#endif + #ifdef ECUBE_SUPPORT + #define ECUBE_COMPILE + #endif #endif #ifdef ECUBE_COMPILE -class EcubeDevInt; + class EcubeDevInt; #endif -class EcubeThread : public DataThread +class EcubeThread : public DataThread { public: - #ifdef ECUBE_COMPILE - EcubeThread(SourceNode* sn); + EcubeThread (SourceNode* sn); ~EcubeThread(); - void run(); // Overridden + void run() override; /** Fills the DataBuffer with incoming data. This is the most important method for each DataThread.*/ diff --git a/Source/Plugins/EventBroadcaster/EventBroadcaster.h b/Source/Plugins/EventBroadcaster/EventBroadcaster.h index 4966d2a3d..4cfb74239 100644 --- a/Source/Plugins/EventBroadcaster/EventBroadcaster.h +++ b/Source/Plugins/EventBroadcaster/EventBroadcaster.h @@ -41,6 +41,7 @@ public: void saveCustomParametersToXml (XmlElement* parentElement) override; void loadCustomParametersFromXml() override; + private: static std::shared_ptr<void> getZMQContext(); static void closeZMQSocket (void* socket); diff --git a/Source/Plugins/EventDetector/EventDetector.cpp b/Source/Plugins/EventDetector/EventDetector.cpp index 2bfe33408..36174a107 100644 --- a/Source/Plugins/EventDetector/EventDetector.cpp +++ b/Source/Plugins/EventDetector/EventDetector.cpp @@ -18,7 +18,6 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. - */ @@ -31,58 +30,47 @@ EventDetector::EventDetector() : GenericProcessor("Event Detector"), threshold(200.0), bufferZone(5.0f), state(false) { + setProcessorType (PROCESSOR_TYPE_FILTER); - parameters.add(Parameter("thresh", 0.0, 500.0, 200.0, 0)); - + parameters.add (Parameter ("thresh", 0.0, 500.0, 200.0, 0)); } + EventDetector::~EventDetector() { - } - -void EventDetector::setParameter(int parameterIndex, float newValue) +void EventDetector::setParameter (int parameterIndex, float newValue) { - editor->updateParameterButtons(parameterIndex); + editor->updateParameterButtons (parameterIndex); - Parameter& p = parameters.getReference(parameterIndex); - p.setValue(newValue, 0); + Parameter& p = parameters.getReference (parameterIndex); + p.setValue (newValue, 0); threshold = newValue; //std::cout << float(p[0]) << std::endl; - } -void EventDetector::process(AudioSampleBuffer& buffer, - MidiBuffer& events) -{ +void EventDetector::process (AudioSampleBuffer& buffer, MidiBuffer& events) +{ //std::cout << *buffer.getReadPointer(0, 0) << std::endl; - - for (int i = 0; i < getNumSamples(channels[0]->sourceNodeId); i++) + for (int i = 0; i < getNumSamples(channels[0]->sourceNodeId); ++i) { - - if ((*buffer.getReadPointer(0, i) < -threshold) && !state) + if ((*buffer.getReadPointer (0, i) < -threshold) && !state) { - // generate midi event //std::cout << "Value = " << *buffer.getSampleData(0, i) << std::endl; - addEvent(events, TTL, i); + addEvent (events, TTL, i); state = true; - } - else if ((*buffer.getReadPointer(0, i) > -threshold + bufferZone) && state) + else if ((*buffer.getReadPointer (0, i) > -threshold + bufferZone) && state) { state = false; } - - } - - } diff --git a/Source/Plugins/EventDetector/EventDetector.h b/Source/Plugins/EventDetector/EventDetector.h index f6d42bf75..068d0b953 100644 --- a/Source/Plugins/EventDetector/EventDetector.h +++ b/Source/Plugins/EventDetector/EventDetector.h @@ -2,7 +2,7 @@ ------------------------------------------------------------------ This file is part of the Open Ephys GUI - Copyright (C) 2014 Open Ephys + Copyright (C) 2016 Open Ephys ------------------------------------------------------------------ @@ -27,33 +27,30 @@ #include "../../../JuceLibraryCode/JuceHeader.h" #include "../GenericProcessor/GenericProcessor.h" -/** - - Searches for threshold crossings and sends out TTL events. - @see GenericProcessor +/** + Searches for threshold crossings and sends out TTL events. + @see GenericProcessor */ - class EventDetector : public GenericProcessor - { public: - EventDetector(); ~EventDetector(); - void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages); - void setParameter(int parameterIndex, float newValue); + void process (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) override; + + void setParameter (int parameterIndex, float newValue) override; -private: +private: float threshold; float bufferZone; bool state; - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(EventDetector); - + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (EventDetector); }; + #endif // __EVENTDETECTOR_H_91811542__ diff --git a/Source/Plugins/EventNode/EventNode.cpp b/Source/Plugins/EventNode/EventNode.cpp index acfa5d943..d6814052a 100644 --- a/Source/Plugins/EventNode/EventNode.cpp +++ b/Source/Plugins/EventNode/EventNode.cpp @@ -2,7 +2,7 @@ ------------------------------------------------------------------ This file is part of the Open Ephys GUI - Copyright (C) 2014 Open Ephys + Copyright (C) 2016 Open Ephys ------------------------------------------------------------------ @@ -26,40 +26,44 @@ #include "../Channel/Channel.h" + EventNode::EventNode() - : GenericProcessor("Event Generator"), accumulator(0), Hz(1) + : GenericProcessor ("Event Generator") + , accumulator (0) + , Hz (1) { + setProcessorType (PROCESSOR_TYPE_SOURCE); Array<var> hzValues; - hzValues.add(0.25f); - hzValues.add(0.5f); - hzValues.add(1.0f); - hzValues.add(2.0f); - - parameters.add(Parameter("Frequency",hzValues, 0, 0)); + hzValues.add (0.25f); + hzValues.add (0.5f); + hzValues.add (1.0f); + hzValues.add (2.0f); + parameters.add (Parameter ("Frequency", hzValues, 0, 0)); } + EventNode::~EventNode() { - } + AudioProcessorEditor* EventNode::createEditor() { - editor = new EventNodeEditor(this, true); + editor = new EventNodeEditor (this, true); return editor; } + void EventNode::updateSettings() { // add event channels - Channel* ch = new Channel(this, 1, EVENT_CHANNEL); - ch->setName("Trigger"); - - eventChannels.add(ch); + Channel* ch = new Channel (this, 1, EVENT_CHANNEL); + ch->setName ("Trigger"); + eventChannels.add (ch); } @@ -70,34 +74,30 @@ void EventNode::updateSettings() // } -void EventNode::process(AudioSampleBuffer& buffer, - MidiBuffer& events) +void EventNode::process (AudioSampleBuffer& buffer, MidiBuffer& events) { events.clear(); //std::cout << "Adding message." << std::endl; - Parameter& p1 = parameters.getReference(0); + Parameter& p1 = parameters.getReference (0); //std::cout << (float) p1[0] << std::endl; - for (int i = 0; i < buffer.getNumSamples(); i++) + for (int i = 0; i < buffer.getNumSamples(); ++i) { accumulator += 1.0f; if (accumulator > getSampleRate() / (float) p1[0]) { std::cout << "Adding message." << std::endl; - addEvent(events, // MidiBuffer - TTL, // eventType - i, // sampleNum - 1, // eventID - 1 // eventChannel - ); + addEvent (events, // MidiBuffer + TTL, // eventType + i, // sampleNum + 1, // eventID + 1); // eventChannel accumulator = 0; } - } - } diff --git a/Source/Plugins/EventNode/EventNode.h b/Source/Plugins/EventNode/EventNode.h index 778bd47f9..d5d59132a 100644 --- a/Source/Plugins/EventNode/EventNode.h +++ b/Source/Plugins/EventNode/EventNode.h @@ -2,7 +2,7 @@ ------------------------------------------------------------------ This file is part of the Open Ephys GUI - Copyright (C) 2014 Open Ephys + Copyright (C) 2016 Open Ephys ------------------------------------------------------------------ @@ -28,51 +28,37 @@ #include "../GenericProcessor/GenericProcessor.h" #include "EventNodeEditor.h" -/** +/** Generates events at regular intervals. @see GenericProcessor, EventNodeEditor - */ - class EventNode : public GenericProcessor { public: - EventNode(); ~EventNode(); - void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages); - //void setParameter (int parameterIndex, float newValue); + void process (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) override; + //void setParameter (int parameterIndex, float newValue) override; - bool isSource() - { - return true; - } + int getNumHeadstageOutputs() const override { return 0; } - int getNumHeadstageOutputs() - { - return 0; - } + void updateSettings() override; - void updateSettings(); + AudioProcessorEditor* createEditor() override; - AudioProcessorEditor* createEditor(); private: - float accumulator; float Hz; - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(EventNode); - + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (EventNode); }; - - #endif // __EVENTNODE_H_9B67A789__ diff --git a/Source/Plugins/FilterNode/FilterNode.cpp b/Source/Plugins/FilterNode/FilterNode.cpp index f57ca1734..ca4c8e141 100644 --- a/Source/Plugins/FilterNode/FilterNode.cpp +++ b/Source/Plugins/FilterNode/FilterNode.cpp @@ -2,7 +2,7 @@ ------------------------------------------------------------------ This file is part of the Open Ephys GUI - Copyright (C) 2014 Open Ephys + Copyright (C) 2016 Open Ephys ------------------------------------------------------------------ @@ -18,17 +18,19 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. - */ #include <stdio.h> #include "FilterNode.h" #include "FilterEditor.h" -FilterNode::FilterNode() - : GenericProcessor("Bandpass Filter"), defaultLowCut(300.0f), defaultHighCut(6000.0f) +FilterNode::FilterNode() + : GenericProcessor ("Bandpass Filter") + , defaultLowCut (300.0f) + , defaultHighCut (6000.0f) { + setProcessorType (PROCESSOR_TYPE_FILTER); // // Deprecated "parameters" class // // // Array<var> lowCutValues; @@ -49,19 +51,18 @@ FilterNode::FilterNode() applyOnADC = false; } + FilterNode::~FilterNode() { - } + AudioProcessorEditor* FilterNode::createEditor() { - editor = new FilterEditor(this, true); + editor = new FilterEditor (this, true); FilterEditor* ed = (FilterEditor*) getEditor(); - ed->setDefaults(defaultLowCut, defaultHighCut); - - //std::cout << "Creating editor." << std::endl; + ed->setDefaults (defaultLowCut, defaultHighCut); return editor; } @@ -132,7 +133,8 @@ void FilterNode::updateSettings() if (numInputs < 1024 && numInputs != numfilt) { // SO fixed this. I think values were never restored correctly because you cleared lowCuts. - Array<double> oldlowCuts, oldhighCuts; + Array<double> oldlowCuts; + Array<double> oldhighCuts; oldlowCuts = lowCuts; oldhighCuts = highCuts; @@ -141,17 +143,13 @@ void FilterNode::updateSettings() highCuts.clear(); shouldFilterChannel.clear(); - for (int n = 0; n < getNumInputs(); n++) + for (int n = 0; n < getNumInputs(); ++n) { - - // std::cout << "Creating filter number " << n << std::endl; - - filters.add(new Dsp::SmoothedFilterDesign - <Dsp::Butterworth::Design::BandPass // design type - <2>, // order - 1, // number of channels (must be const) - Dsp::DirectFormII> // realization - (1)); + filters.add (new Dsp::SmoothedFilterDesign + <Dsp::Butterworth::Design::BandPass // design type + <2>, // order + 1, // number of channels (must be const) + Dsp::DirectFormII> (1)); // realization //Parameter& p1 = parameters.getReference(0); @@ -161,177 +159,167 @@ void FilterNode::updateSettings() // restore defaults - shouldFilterChannel.add(true); + shouldFilterChannel.add (true); - float lc, hc; + float newLowCut = 0.f; + float newHighCut = 0.f; if (oldlowCuts.size() > n) { - lc = oldlowCuts[n]; - hc = oldhighCuts[n]; + newLowCut = oldlowCuts[n]; + newHighCut = oldhighCuts[n]; } else { - lc = defaultLowCut; - hc = defaultHighCut; + newLowCut = defaultLowCut; + newHighCut = defaultHighCut; } - lowCuts.add(lc); - highCuts.add(hc); + lowCuts.add (newLowCut); + highCuts.add (newHighCut); - setFilterParameters(lc, hc, n); + setFilterParameters (newLowCut, newHighCut, n); } - } - setApplyOnADC(applyOnADC); - + setApplyOnADC (applyOnADC); } -double FilterNode::getLowCutValueForChannel(int chan) + +double FilterNode::getLowCutValueForChannel (int chan) const { return lowCuts[chan]; } -double FilterNode::getHighCutValueForChannel(int chan) + +double FilterNode::getHighCutValueForChannel (int chan) const { return highCuts[chan]; } -bool FilterNode::getBypassStatusForChannel(int chan) + +bool FilterNode::getBypassStatusForChannel (int chan) const { return shouldFilterChannel[chan]; } -void FilterNode::setFilterParameters(double lowCut, double highCut, int chan) + +void FilterNode::setFilterParameters (double lowCut, double highCut, int chan) { - if (channels.size()-1 < chan) - return; + if (channels.size() - 1 < chan) + return; + Dsp::Params params; params[0] = channels[chan]->sampleRate; // sample rate - params[1] = 2; // order - params[2] = (highCut + lowCut)/2; // center frequency - params[3] = highCut - lowCut; // bandwidth + params[1] = 2; // order + params[2] = (highCut + lowCut) / 2; // center frequency + params[3] = highCut - lowCut; // bandwidth if (filters.size() > chan) - filters[chan]->setParams(params); - + filters[chan]->setParams (params); } -void FilterNode::setParameter(int parameterIndex, float newValue) -{ +void FilterNode::setParameter (int parameterIndex, float newValue) +{ if (parameterIndex < 2) // change filter settings { - if (newValue <= 0.01 || newValue >= 10000.0f) return; - //std::cout << "Setting channel " << currentChannel;// << std::endl; - if (parameterIndex == 0) { - // std::cout << " low cut to " << newValue << std::endl; - lowCuts.set(currentChannel,newValue); + lowCuts.set (currentChannel,newValue); } else if (parameterIndex == 1) { - //std::cout << " high cut to " << newValue << std::endl; - highCuts.set(currentChannel,newValue); + highCuts.set (currentChannel,newValue); } - setFilterParameters(lowCuts[currentChannel], - highCuts[currentChannel], - currentChannel); - - editor->updateParameterButtons(parameterIndex); + setFilterParameters (lowCuts[currentChannel], + highCuts[currentChannel], + currentChannel); + editor->updateParameterButtons (parameterIndex); } - else // change channel bypass state + // change channel bypass state + else { if (newValue == 0) { - shouldFilterChannel.set(currentChannel, false); + shouldFilterChannel.set (currentChannel, false); } else { - shouldFilterChannel.set(currentChannel, true); + shouldFilterChannel.set (currentChannel, true); } - } } -void FilterNode::process(AudioSampleBuffer& buffer, - MidiBuffer& midiMessages) -{ - for (int n = 0; n < getNumOutputs(); n++) +void FilterNode::process (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) +{ + for (int n = 0; n < getNumOutputs(); ++n) { if (shouldFilterChannel[n]) { - float* ptr = buffer.getWritePointer(n); - filters[n]->process(getNumSamples(n), &ptr); + float* ptr = buffer.getWritePointer (n); + filters[n]->process (getNumSamples (n), &ptr); } } - } -void FilterNode::setApplyOnADC(bool state) -{ - for (int n = 0; n < channels.size(); n++) +void FilterNode::setApplyOnADC (bool state) +{ + for (int n = 0; n < channels.size(); ++n) { - if (channels[n]->getType() == ADC_CHANNEL || channels[n]->getType() == AUX_CHANNEL) + if (channels[n]->getType() == ADC_CHANNEL + || channels[n]->getType() == AUX_CHANNEL) { - setCurrentChannel(n); + setCurrentChannel (n); if (state) - setParameter(2,1.0); + setParameter (2,1.0); else - setParameter(2,0.0); + setParameter (2,0.0); } } } -void FilterNode::saveCustomChannelParametersToXml(XmlElement* channelInfo, int channelNumber, bool isEventChannel) -{ - - //std::cout << "CHANNEL: " << channelNumber << std::endl; - if (!isEventChannel && channelNumber > -1 && channelNumber < highCuts.size()) +void FilterNode::saveCustomChannelParametersToXml (XmlElement* channelInfo, int channelNumber, bool isEventChannel) +{ + if (! isEventChannel + && channelNumber > -1 + && channelNumber < highCuts.size()) { //std::cout << "Saving custom parameters for filter node." << std::endl; - XmlElement* channelParams = channelInfo->createNewChildElement("PARAMETERS"); - channelParams->setAttribute("highcut",highCuts[channelNumber]); - channelParams->setAttribute("lowcut",lowCuts[channelNumber]); - channelParams->setAttribute("shouldFilter",shouldFilterChannel[channelNumber]); + XmlElement* channelParams = channelInfo->createNewChildElement ("PARAMETERS"); + channelParams->setAttribute ("highcut", highCuts[channelNumber]); + channelParams->setAttribute ("lowcut", lowCuts[channelNumber]); + channelParams->setAttribute ("shouldFilter", shouldFilterChannel[channelNumber]); } - } -void FilterNode::loadCustomChannelParametersFromXml(XmlElement* channelInfo, bool isEventChannel) -{ - int channelNum = channelInfo->getIntAttribute("number"); +void FilterNode::loadCustomChannelParametersFromXml (XmlElement* channelInfo, bool isEventChannel) +{ + int channelNum = channelInfo->getIntAttribute ("number"); - if (!isEventChannel) + if (! isEventChannel) { - forEachXmlChildElement(*channelInfo, subNode) + forEachXmlChildElement (*channelInfo, subNode) { - if (subNode->hasTagName("PARAMETERS")) + if (subNode->hasTagName ("PARAMETERS")) { - highCuts.set(channelNum, subNode->getDoubleAttribute("highcut",defaultHighCut)); - lowCuts.set(channelNum, subNode->getDoubleAttribute("lowcut",defaultLowCut)); - shouldFilterChannel.set(channelNum, subNode->getBoolAttribute("shouldFilter",true)); - - setFilterParameters(lowCuts[channelNum], - highCuts[channelNum], - channelNum); + highCuts.set (channelNum, subNode->getDoubleAttribute ("highcut", defaultHighCut)); + lowCuts.set (channelNum, subNode->getDoubleAttribute ("lowcut", defaultLowCut)); + shouldFilterChannel.set (channelNum, subNode->getBoolAttribute ("shouldFilter", true)); + setFilterParameters (lowCuts[channelNum], highCuts[channelNum], channelNum); } } } - - } diff --git a/Source/Plugins/FilterNode/FilterNode.h b/Source/Plugins/FilterNode/FilterNode.h index 4f47f2390..5a3b3f1b9 100644 --- a/Source/Plugins/FilterNode/FilterNode.h +++ b/Source/Plugins/FilterNode/FilterNode.h @@ -2,7 +2,7 @@ ------------------------------------------------------------------ This file is part of the Open Ephys GUI - Copyright (C) 2014 Open Ephys + Copyright (C) 2016 Open Ephys ------------------------------------------------------------------ @@ -18,7 +18,6 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. - */ #ifndef __FILTERNODE_H_CED428E__ @@ -27,59 +26,56 @@ #include <ProcessorHeaders.h> #include "Dsp/Dsp.h" -/** - - Filters data using a filter from the DSP library. - The user can select the low- and high-frequency cutoffs. +/** + Filters data using a filter from the DSP library. - @see GenericProcessor, FilterEditor + The user can select the low- and high-frequency cutoffs. + @see GenericProcessor, FilterEditor */ - class FilterNode : public GenericProcessor - { public: - FilterNode(); ~FilterNode(); - void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages); - void setParameter(int parameterIndex, float newValue); + AudioProcessorEditor* createEditor() override; - AudioProcessorEditor* createEditor(); + bool hasEditor() const override { return true; } - bool hasEditor() const - { - return true; - } + void process (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) override; - double getLowCutValueForChannel(int chan); - double getHighCutValueForChannel(int chan); - bool getBypassStatusForChannel(int chan); + void setParameter (int parameterIndex, float newValue) override; - void updateSettings(); + void updateSettings() override; - void saveCustomChannelParametersToXml(XmlElement* channelInfo, int channelNumber, bool isEventChannel); + void saveCustomChannelParametersToXml (XmlElement* channelInfo, int channelNumber, bool isEventChannel) override; + void loadCustomChannelParametersFromXml (XmlElement* channelInfo, bool isEventChannel) override; + + double getLowCutValueForChannel (int chan) const; + double getHighCutValueForChannel (int chan) const; + + bool getBypassStatusForChannel (int chan) const; + + void setApplyOnADC (bool state); - void loadCustomChannelParametersFromXml(XmlElement* channelInfo, bool isEventChannel); - void setApplyOnADC(bool state); private: + void setFilterParameters (double, double, int); + + Array<double> lowCuts; + Array<double> highCuts; - Array<double> lowCuts, highCuts; OwnedArray<Dsp::Filter> filters; Array<bool> shouldFilterChannel; bool applyOnADC; + double defaultLowCut; double defaultHighCut; - void setFilterParameters(double, double, int); - - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(FilterNode); - + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FilterNode); }; #endif // __FILTERNODE_H_CED428E__ diff --git a/Source/Plugins/LfpDisplayNode/LfpDisplayNode.cpp b/Source/Plugins/LfpDisplayNode/LfpDisplayNode.cpp index abb2aff8d..222fb2b7c 100644 --- a/Source/Plugins/LfpDisplayNode/LfpDisplayNode.cpp +++ b/Source/Plugins/LfpDisplayNode/LfpDisplayNode.cpp @@ -2,7 +2,7 @@ ------------------------------------------------------------------ This file is part of the Open Ephys GUI - Copyright (C) 2013 Open Ephys + Copyright (C) 2016 Open Ephys ------------------------------------------------------------------ @@ -26,35 +26,37 @@ #include <stdio.h> LfpDisplayNode::LfpDisplayNode() - : GenericProcessor("LFP Viewer"), - displayGain(1), bufferLength(5.0f), - abstractFifo(100) + : GenericProcessor ("LFP Viewer") + , displayGain (1) + , bufferLength (5.0f) + , abstractFifo (100) { - //std::cout << " LFPDisplayNodeConstructor" << std::endl; - displayBuffer = new AudioSampleBuffer(8, 100); + setProcessorType (PROCESSOR_TYPE_SINK); - arrayOfOnes.malloc(5000); + //std::cout << " LFPDisplayNodeConstructor" << std::endl; + displayBuffer = new AudioSampleBuffer (8, 100); - for (int n = 0; n < 5000; n++) + const int heapSize = 5000; + arrayOfOnes.malloc (heapSize); + for (int n = 0; n < heapSize; ++n) { arrayOfOnes[n] = 1; } - } + LfpDisplayNode::~LfpDisplayNode() { - } + AudioProcessorEditor* LfpDisplayNode::createEditor() { - - editor = new LfpDisplayEditor(this, true); + editor = new LfpDisplayEditor (this, true); return editor; - } + void LfpDisplayNode::updateSettings() { std::cout << "Setting num inputs on LfpDisplayNode to " << getNumInputs() << std::endl; @@ -63,57 +65,57 @@ void LfpDisplayNode::updateSettings() eventSourceNodes.clear(); ttlState.clear(); - for (int i = 0; i < eventChannels.size(); i++) + for (int i = 0; i < eventChannels.size(); ++i) { - if (!eventSourceNodes.contains(eventChannels[i]->sourceNodeId) && eventChannels[i]->type == EVENT_CHANNEL) + if (! eventSourceNodes.contains (eventChannels[i]->sourceNodeId) + && eventChannels[i]->type == EVENT_CHANNEL) { - eventSourceNodes.add(eventChannels[i]->sourceNodeId); + eventSourceNodes.add (eventChannels[i]->sourceNodeId); } - }\ + } numEventChannels = eventSourceNodes.size(); std::cout << "Found " << numEventChannels << " event channels." << std::endl; - for (int i = 0; i < eventSourceNodes.size(); i++) + for (int i = 0; i < eventSourceNodes.size(); ++i) { std::cout << "Adding channel " << getNumInputs() + i << " for event source node " << eventSourceNodes[i] << std::endl; channelForEventSource[eventSourceNodes[i]] = getNumInputs() + i; ttlState[eventSourceNodes[i]] = 0; - Channel* eventChan = new Channel(this, getNumInputs() + i, EVENT_CHANNEL); + Channel* eventChan = new Channel (this, getNumInputs() + i, EVENT_CHANNEL); eventChan->sourceNodeId = eventSourceNodes[i]; - channels.add(eventChan); // add a channel for event data for each source node + channels.add (eventChan); // add a channel for event data for each source node } displayBufferIndex.clear(); - displayBufferIndex.insertMultiple(0, 0, getNumInputs() + numEventChannels); - + displayBufferIndex.insertMultiple (0, 0, getNumInputs() + numEventChannels); } + bool LfpDisplayNode::resizeBuffer() { - int nSamples = (int) getSampleRate()*bufferLength; + int nSamples = (int) getSampleRate() * bufferLength; int nInputs = getNumInputs(); std::cout << "Resizing buffer. Samples: " << nSamples << ", Inputs: " << nInputs << std::endl; if (nSamples > 0 && nInputs > 0) { - abstractFifo.setTotalSize(nSamples); - displayBuffer->setSize(nInputs + numEventChannels, nSamples); // add extra channels for TTLs + abstractFifo.setTotalSize (nSamples); + displayBuffer->setSize (nInputs + numEventChannels, nSamples); // add extra channels for TTLs return true; } else { return false; } - } + bool LfpDisplayNode::enable() { - if (resizeBuffer()) { LfpDisplayEditor* editor = (LfpDisplayEditor*) getEditor(); @@ -127,6 +129,7 @@ bool LfpDisplayNode::enable() } + bool LfpDisplayNode::disable() { LfpDisplayEditor* editor = (LfpDisplayEditor*) getEditor(); @@ -134,46 +137,46 @@ bool LfpDisplayNode::disable() return true; } -void LfpDisplayNode::setParameter(int parameterIndex, float newValue) + +void LfpDisplayNode::setParameter (int parameterIndex, float newValue) { - editor->updateParameterButtons(parameterIndex); + editor->updateParameterButtons (parameterIndex); //Sets Parameter in parameters array for processor Parameter* parameterPointer = parameters.getRawDataPointer(); parameterPointer = parameterPointer+parameterIndex; - parameterPointer->setValue(newValue, currentChannel); + parameterPointer->setValue (newValue, currentChannel); //std::cout << "Saving Parameter from " << currentChannel << ", channel "; LfpDisplayEditor* ed = (LfpDisplayEditor*) getEditor(); if (ed->canvas != 0) - ed->canvas->setParameter(parameterIndex, newValue); + ed->canvas->setParameter (parameterIndex, newValue); } -void LfpDisplayNode::handleEvent(int eventType, MidiMessage& event, int sampleNum) + +void LfpDisplayNode::handleEvent (int eventType, MidiMessage& event, int sampleNum) { if (eventType == TTL) { const uint8* dataptr = event.getRawData(); //int eventNodeId = *(dataptr+1); - int eventId = *(dataptr+2); - int eventChannel = *(dataptr+3); - int eventTime = event.getTimeStamp(); - - int eventSourceNodeId = *(dataptr+5); - - int nSamples = numSamples.at(eventSourceNodeId); - - int samplesToFill = nSamples - eventTime; + const int eventId = *(dataptr + 2); + const int eventChannel = *(dataptr + 3); + const int eventTime = event.getTimeStamp(); + const int eventSourceNodeId = *(dataptr + 5); + const int nSamples = numSamples.at (eventSourceNodeId); + const int samplesToFill = nSamples - eventTime; // std::cout << "Received event from " << eventSourceNode << ", channel " // << eventChannel << ", with ID " << eventId << ", copying to " // << channelForEventSource[eventSourceNode] << std::endl; //// int bufferIndex = (displayBufferIndex[channelForEventSource[eventSourceNodeId]] + eventTime - nSamples) % displayBuffer->getNumSamples(); - - bufferIndex = bufferIndex >= 0 ? bufferIndex : - displayBuffer->getNumSamples() + bufferIndex; + + bufferIndex = bufferIndex >= 0 + ? bufferIndex + : displayBuffer->getNumSamples() + bufferIndex; if (eventId == 1) @@ -187,161 +190,129 @@ void LfpDisplayNode::handleEvent(int eventType, MidiMessage& event, int sampleNu if (samplesToFill + bufferIndex < displayBuffer->getNumSamples()) { - //std::cout << bufferIndex << " " << samplesToFill << " " << ttlState[eventSourceNode] << std::endl; - displayBuffer->copyFrom(channelForEventSource[eventSourceNodeId], // destChannel - bufferIndex, // destStartSample - arrayOfOnes, // source - samplesToFill, // numSamples - float(ttlState[eventSourceNodeId])); // gain + displayBuffer->copyFrom (channelForEventSource[eventSourceNodeId], // destChannel + bufferIndex, // destStartSample + arrayOfOnes, // source + samplesToFill, // numSamples + float (ttlState[eventSourceNodeId])); // gain } else { - - int block2Size = (samplesToFill + bufferIndex) % displayBuffer->getNumSamples(); - int block1Size = samplesToFill - block2Size; - - //std::cout << "OVERFLOW." << std::endl; - - //std::cout << bufferIndex << " " << block1Size << " " << ttlState << std::endl; - - displayBuffer->copyFrom(channelForEventSource[eventSourceNodeId], // destChannel - bufferIndex, // destStartSample - arrayOfOnes, // source - block1Size, // numSamples - float(ttlState[eventSourceNodeId])); // gain - - //std::cout << 0 << " " << block2Size << " " << ttlState << std::endl; - - displayBuffer->copyFrom(channelForEventSource[eventSourceNodeId], // destChannel - 0, // destStartSample - arrayOfOnes, // source - block2Size, // numSamples - float(ttlState[eventSourceNodeId])); // gain - - + const int block2Size = (samplesToFill + bufferIndex) % displayBuffer->getNumSamples(); + const int block1Size = samplesToFill - block2Size; + + displayBuffer->copyFrom (channelForEventSource[eventSourceNodeId], // destChannel + bufferIndex, // destStartSample + arrayOfOnes, // source + block1Size, // numSamples + float (ttlState[eventSourceNodeId])); // gain + + displayBuffer->copyFrom (channelForEventSource[eventSourceNodeId], // destChannel + 0, // destStartSample + arrayOfOnes, // source + block2Size, // numSamples + float (ttlState[eventSourceNodeId])); // gain } - - // std::cout << "ttlState: " << ttlState << std::endl; // std::cout << "Received event from " << eventNodeId << // " on channel " << eventChannel << // " with value " << eventId << // " at timestamp " << event.getTimeStamp() << std::endl; - - } - } + void LfpDisplayNode::initializeEventChannels() { - - for (int i = 0; i < eventSourceNodes.size(); i++) + for (int i = 0; i < eventSourceNodes.size(); ++i) { - - int chan = channelForEventSource[eventSourceNodes[i]]; - int index = displayBufferIndex[chan]; - - //std::cout << "Event source node " << i << ", channel " << chan << std::endl; - - int samplesLeft = displayBuffer->getNumSamples() - index; - - int nSamples = numSamples.at(eventSourceNodes[i]); - - + const int chan = channelForEventSource[eventSourceNodes[i]]; + const int index = displayBufferIndex[chan]; + const int samplesLeft = displayBuffer->getNumSamples() - index; + const int nSamples = numSamples.at(eventSourceNodes[i]); if (nSamples < samplesLeft) { + displayBuffer->copyFrom (chan, // destChannel + index, // destStartSample + arrayOfOnes, // source + nSamples, // numSamples + float (ttlState[eventSourceNodes[i]])); // gain - // std::cout << getNumInputs()+1 << " " << displayBufferIndex << " " << totalSamples << " " << ttlState << std::endl; - // - displayBuffer->copyFrom(chan, // destChannel - index, // destStartSample - arrayOfOnes, // source - nSamples, // numSamples - float(ttlState[eventSourceNodes[i]])); // gain - - displayBufferIndex.set(chan, index + nSamples); + displayBufferIndex.set (chan, index + nSamples); } else { + const int extraSamples = nSamples - samplesLeft; - int extraSamples = nSamples - samplesLeft; - - // std::cout << "OVERFLOW." << std::endl; - // std::cout << bufferIndex << " " << block1Size << " " << ttlState << std::endl; + displayBuffer->copyFrom (chan, // destChannel + index, // destStartSample + arrayOfOnes, // source + samplesLeft, // numSamples + float (ttlState[eventSourceNodes[i]])); // gain - displayBuffer->copyFrom(chan, // destChannel - index, // destStartSample - arrayOfOnes, // source - samplesLeft, // numSamples - float(ttlState[eventSourceNodes[i]])); // gain - // std::cout << 0 << " " << block2Size << " " << ttlState << std::endl; + displayBuffer->copyFrom (chan, // destChannel + 0, // destStartSample + arrayOfOnes, // source + extraSamples, // numSamples + float (ttlState[eventSourceNodes[i]])); // gain - displayBuffer->copyFrom(chan, // destChannel - 0, // destStartSample - arrayOfOnes, // source - extraSamples, // numSamples - float(ttlState[eventSourceNodes[i]])); // gain - - displayBufferIndex.set(chan, extraSamples); + displayBufferIndex.set (chan, extraSamples); } - } + } } -void LfpDisplayNode::process(AudioSampleBuffer& buffer, MidiBuffer& events) + +void LfpDisplayNode::process (AudioSampleBuffer& buffer, MidiBuffer& events) { // 1. place any new samples into the displayBuffer //std::cout << "Display node sample count: " << nSamples << std::endl; ///buffer.getNumSamples() << std::endl; initializeEventChannels(); - checkForEvents(events); // see if we got any TTL events + checkForEvents (events); // see if we got any TTL events - ScopedLock displayLock(displayMutex); + ScopedLock displayLock (displayMutex); - for (int chan = 0; chan < buffer.getNumChannels(); chan++) + for (int chan = 0; chan < buffer.getNumChannels(); ++chan) { - int samplesLeft = displayBuffer->getNumSamples() - displayBufferIndex[chan]; - int nSamples = getNumSamples(chan); - - if (nSamples < samplesLeft) - { - - displayBuffer->copyFrom(chan, // destChannel - displayBufferIndex[chan], // destStartSample - buffer, // source - chan, // source channel - 0, // source start sample - nSamples); // numSamples - - displayBufferIndex.set(chan, displayBufferIndex[chan] + nSamples); - } - else - { - - int extraSamples = nSamples - samplesLeft; - - displayBuffer->copyFrom(chan, // destChannel - displayBufferIndex[chan], // destStartSample - buffer, // source - chan, // source channel - 0, // source start sample - samplesLeft); // numSamples - - displayBuffer->copyFrom(chan, - 0, - buffer, - chan, - samplesLeft, - extraSamples); - - displayBufferIndex.set(chan, extraSamples); + const int samplesLeft = displayBuffer->getNumSamples() - displayBufferIndex[chan]; + const int nSamples = getNumSamples (chan); + + if (nSamples < samplesLeft) + { + displayBuffer->copyFrom (chan, // destChannel + displayBufferIndex[chan], // destStartSample + buffer, // source + chan, // source channel + 0, // source start sample + nSamples); // numSamples + + displayBufferIndex.set (chan, displayBufferIndex[chan] + nSamples); + } + else + { + const int extraSamples = nSamples - samplesLeft; + + displayBuffer->copyFrom (chan, // destChannel + displayBufferIndex[chan], // destStartSample + buffer, // source + chan, // source channel + 0, // source start sample + samplesLeft); // numSamples + + displayBuffer->copyFrom (chan, // destChannel + 0, // destStartSample + buffer, // source + chan, // source channel + samplesLeft, // source start sample + extraSamples); // numSamples + + displayBufferIndex.set (chan, extraSamples); } } - } diff --git a/Source/Plugins/LfpDisplayNode/LfpDisplayNode.h b/Source/Plugins/LfpDisplayNode/LfpDisplayNode.h index 113729eb0..b3145aca1 100644 --- a/Source/Plugins/LfpDisplayNode/LfpDisplayNode.h +++ b/Source/Plugins/LfpDisplayNode/LfpDisplayNode.h @@ -2,7 +2,7 @@ ------------------------------------------------------------------ This file is part of the Open Ephys GUI - Copyright (C) 2013 Open Ephys + Copyright (C) 2016 Open Ephys ------------------------------------------------------------------ @@ -29,6 +29,7 @@ class DataViewport; + /** Holds data in a displayBuffer to be used by the LfpDisplayCanvas @@ -37,49 +38,33 @@ class DataViewport; @see GenericProcessor, LfpDisplayEditor, LfpDisplayCanvas */ - class LfpDisplayNode : public GenericProcessor - { public: - LfpDisplayNode(); ~LfpDisplayNode(); - AudioProcessorEditor* createEditor(); + AudioProcessorEditor* createEditor() override; - bool isSink() - { - return true; - } + void process (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) override; - void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages); + void setParameter (int parameterIndex, float newValue) override; - void setParameter(int, float); + void updateSettings() override; - void updateSettings(); + bool enable() override; + bool disable() override; - bool enable(); - bool disable(); + void handleEvent (int, MidiMessage&, int) override; - void handleEvent(int, MidiMessage&, int); + AudioSampleBuffer* getDisplayBufferAddress() const { return displayBuffer; } - AudioSampleBuffer* getDisplayBufferAddress() - { - return displayBuffer; - } - int getDisplayBufferIndex(int chan) - { - return displayBufferIndex[chan]; - } + int getDisplayBufferIndex (int chan) const { return displayBufferIndex[chan]; } - CriticalSection* getMutex() - { - return &displayMutex; - } + CriticalSection* getMutex() { return &displayMutex; } -private: +private: void initializeEventChannels(); ScopedPointer<AudioSampleBuffer> displayBuffer; @@ -102,13 +87,11 @@ private: bool resizeBuffer(); - CriticalSection displayMutex; - - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(LfpDisplayNode); + CriticalSection displayMutex; + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LfpDisplayNode); }; - #endif // __LFPDISPLAYNODE_H_D969A379__ diff --git a/Source/Plugins/LfpDisplayNodeBeta/LfpDisplayNode.cpp b/Source/Plugins/LfpDisplayNodeBeta/LfpDisplayNode.cpp index d1b0e335c..7b87a33e7 100644 --- a/Source/Plugins/LfpDisplayNodeBeta/LfpDisplayNode.cpp +++ b/Source/Plugins/LfpDisplayNodeBeta/LfpDisplayNode.cpp @@ -2,7 +2,7 @@ ------------------------------------------------------------------ This file is part of the Open Ephys GUI - Copyright (C) 2013 Open Ephys + Copyright (C) 2016 Open Ephys ------------------------------------------------------------------ @@ -27,36 +27,38 @@ using namespace LfpDisplayNodeBeta; + LfpDisplayNode::LfpDisplayNode() - : GenericProcessor("LFP Viewer Beta"), - displayGain(1), bufferLength(20.0f), - abstractFifo(100) + : GenericProcessor ("LFP Viewer Beta") + , displayGain (1) + , bufferLength (20.0f) + , abstractFifo (100) { - //std::cout << " LFPDisplayNodeConstructor" << std::endl; - displayBuffer = new AudioSampleBuffer(8, 100); + setProcessorType (PROCESSOR_TYPE_SINK); - arrayOfOnes = new float[5000]; + displayBuffer = new AudioSampleBuffer (8, 100); - for (int n = 0; n < 5000; n++) + const int heapSize = 5000; + arrayOfOnes = new float[heapSize]; + for (int n = 0; n < heapSize; ++n) { arrayOfOnes[n] = 1; } - } + LfpDisplayNode::~LfpDisplayNode() { - } + AudioProcessorEditor* LfpDisplayNode::createEditor() { - - editor = new LfpDisplayEditor(this, true); + editor = new LfpDisplayEditor (this, true); return editor; - } + void LfpDisplayNode::updateSettings() { std::cout << "Setting num inputs on LfpDisplayNode to " << getNumInputs() << std::endl; @@ -65,12 +67,12 @@ void LfpDisplayNode::updateSettings() eventSourceNodes.clear(); ttlState.clear(); - for (int i = 0; i < eventChannels.size(); i++) + for (int i = 0; i < eventChannels.size(); ++i) { - if (!eventSourceNodes.contains(eventChannels[i]->sourceNodeId) && eventChannels[i]->type == EVENT_CHANNEL) + if (! eventSourceNodes.contains(eventChannels[i]->sourceNodeId) + && eventChannels[i]->type == EVENT_CHANNEL) { - eventSourceNodes.add(eventChannels[i]->sourceNodeId); - + eventSourceNodes.add (eventChannels[i]->sourceNodeId); } }\ @@ -78,44 +80,46 @@ void LfpDisplayNode::updateSettings() std::cout << "Found " << numEventChannels << " event channels." << std::endl; - for (int i = 0; i < eventSourceNodes.size(); i++) + for (int i = 0; i < eventSourceNodes.size(); ++i) { std::cout << "Adding channel " << getNumInputs() + i << " for event source node " << eventSourceNodes[i] << std::endl; + channelForEventSource[eventSourceNodes[i]] = getNumInputs() + i; ttlState[eventSourceNodes[i]] = 0; - Channel* eventChan = new Channel(this, getNumInputs() + i, EVENT_CHANNEL); + + Channel* eventChan = new Channel (this, getNumInputs() + i, EVENT_CHANNEL); eventChan->sourceNodeId = eventSourceNodes[i]; - channels.add(eventChan); // add a channel for event data for each source node + channels.add (eventChan); // add a channel for event data for each source node } displayBufferIndex.clear(); - displayBufferIndex.insertMultiple(0, 0, getNumInputs() + numEventChannels); - + displayBufferIndex.insertMultiple (0, 0, getNumInputs() + numEventChannels); } + bool LfpDisplayNode::resizeBuffer() { - int nSamples = (int) getSampleRate()*bufferLength; + int nSamples = (int) getSampleRate() * bufferLength; int nInputs = getNumInputs(); std::cout << "Resizing buffer. Samples: " << nSamples << ", Inputs: " << nInputs << std::endl; if (nSamples > 0 && nInputs > 0) { - abstractFifo.setTotalSize(nSamples); - displayBuffer->setSize(nInputs + numEventChannels, nSamples); // add extra channels for TTLs + abstractFifo.setTotalSize (nSamples); + displayBuffer->setSize (nInputs + numEventChannels, nSamples); // add extra channels for TTLs + return true; } else { return false; } - } + bool LfpDisplayNode::enable() { - if (resizeBuffer()) { LfpDisplayEditor* editor = (LfpDisplayEditor*) getEditor(); @@ -126,9 +130,9 @@ bool LfpDisplayNode::enable() { return false; } - } + bool LfpDisplayNode::disable() { LfpDisplayEditor* editor = (LfpDisplayEditor*) getEditor(); @@ -136,47 +140,48 @@ bool LfpDisplayNode::disable() return true; } -void LfpDisplayNode::setParameter(int parameterIndex, float newValue) + +void LfpDisplayNode::setParameter (int parameterIndex, float newValue) { - editor->updateParameterButtons(parameterIndex); + editor->updateParameterButtons (parameterIndex); + // //Sets Parameter in parameters array for processor Parameter* parameterPointer = parameters.getRawDataPointer(); - parameterPointer = parameterPointer+parameterIndex; - parameterPointer->setValue(newValue, currentChannel); + parameterPointer += parameterIndex; + parameterPointer->setValue (newValue, currentChannel); //std::cout << "Saving Parameter from " << currentChannel << ", channel "; LfpDisplayEditor* ed = (LfpDisplayEditor*) getEditor(); if (ed->canvas != 0) - ed->canvas->setParameter(parameterIndex, newValue); + ed->canvas->setParameter (parameterIndex, newValue); } -void LfpDisplayNode::handleEvent(int eventType, MidiMessage& event, int sampleNum) + +void LfpDisplayNode::handleEvent (int eventType, MidiMessage& event, int sampleNum) { if (eventType == TTL) { const uint8* dataptr = event.getRawData(); - //int eventNodeId = *(dataptr+1); - int eventId = *(dataptr+2); - int eventChannel = *(dataptr+3); - int eventTime = event.getTimeStamp(); - - int eventSourceNodeId = *(dataptr+5); - - int nSamples = numSamples.at(eventSourceNodeId); - - int samplesToFill = nSamples - eventTime; + //int eventNodeId = *(dataptr + 1); + const int eventId = *(dataptr + 2); + const int eventChannel = *(dataptr + 3); + const int eventTime = event.getTimeStamp(); + const int eventSourceNodeId = *(dataptr + 5); + const int nSamples = numSamples.at (eventSourceNodeId); + const int samplesToFill = nSamples - eventTime; // std::cout << "Received event from " << eventSourceNode << ", channel " // << eventChannel << ", with ID " << eventId << ", copying to " // << channelForEventSource[eventSourceNode] << std::endl; //// - int bufferIndex = (displayBufferIndex[channelForEventSource[eventSourceNodeId]] + eventTime - nSamples) % displayBuffer->getNumSamples(); - - bufferIndex = bufferIndex >= 0 ? bufferIndex : - displayBuffer->getNumSamples() + bufferIndex; + int bufferIndex = (displayBufferIndex[channelForEventSource[eventSourceNodeId]] + eventTime - nSamples) + % displayBuffer->getNumSamples(); + bufferIndex = bufferIndex >= 0 + ? bufferIndex + : displayBuffer->getNumSamples() + bufferIndex; if (eventId == 1) { @@ -189,161 +194,132 @@ void LfpDisplayNode::handleEvent(int eventType, MidiMessage& event, int sampleNu if (samplesToFill + bufferIndex < displayBuffer->getNumSamples()) { - //std::cout << bufferIndex << " " << samplesToFill << " " << ttlState[eventSourceNode] << std::endl; - displayBuffer->copyFrom(channelForEventSource[eventSourceNodeId], // destChannel - bufferIndex, // destStartSample - arrayOfOnes, // source - samplesToFill, // numSamples - float(ttlState[eventSourceNodeId])); // gain + displayBuffer->copyFrom (channelForEventSource[eventSourceNodeId], // destChannel + bufferIndex, // destStartSample + arrayOfOnes, // source + samplesToFill, // numSamples + float (ttlState[eventSourceNodeId])); // gain } else { - - int block2Size = (samplesToFill + bufferIndex) % displayBuffer->getNumSamples(); - int block1Size = samplesToFill - block2Size; - - //std::cout << "OVERFLOW." << std::endl; - - //std::cout << bufferIndex << " " << block1Size << " " << ttlState << std::endl; - - displayBuffer->copyFrom(channelForEventSource[eventSourceNodeId], // destChannel - bufferIndex, // destStartSample - arrayOfOnes, // source - block1Size, // numSamples - float(ttlState[eventSourceNodeId])); // gain - - //std::cout << 0 << " " << block2Size << " " << ttlState << std::endl; - - displayBuffer->copyFrom(channelForEventSource[eventSourceNodeId], // destChannel - 0, // destStartSample - arrayOfOnes, // source - block2Size, // numSamples - float(ttlState[eventSourceNodeId])); // gain - - + const int block2Size = (samplesToFill + bufferIndex) % displayBuffer->getNumSamples(); + const int block1Size = samplesToFill - block2Size; + + displayBuffer->copyFrom (channelForEventSource[eventSourceNodeId], // destChannel + bufferIndex, // destStartSample + arrayOfOnes, // source + block1Size, // numSamples + float (ttlState[eventSourceNodeId])); // gain + + displayBuffer->copyFrom (channelForEventSource[eventSourceNodeId], // destChannel + 0, // destStartSample + arrayOfOnes, // source + block2Size, // numSamples + float (ttlState[eventSourceNodeId])); // gain } - - // std::cout << "ttlState: " << ttlState << std::endl; - - // std::cout << "Received event from " << eventNodeId << - // " on channel " << eventChannel << - // " with value " << eventId << - // " at timestamp " << event.getTimeStamp() << std::endl; - - + // std::cout << "Received event from " << eventNodeId + // << " on channel " << eventChannel + // << " with value " << eventId + // << " at timestamp " << event.getTimeStamp() << std::endl; } - } + void LfpDisplayNode::initializeEventChannels() { - - for (int i = 0; i < eventSourceNodes.size(); i++) + for (int i = 0; i < eventSourceNodes.size(); ++i) { - - int chan = channelForEventSource[eventSourceNodes[i]]; - int index = displayBufferIndex[chan]; + const int chan = channelForEventSource[eventSourceNodes[i]]; + const int index = displayBufferIndex[chan]; + const int samplesLeft = displayBuffer->getNumSamples() - index; + const int nSamples = numSamples.at (eventSourceNodes[i]); //std::cout << "Event source node " << i << ", channel " << chan << std::endl; - int samplesLeft = displayBuffer->getNumSamples() - index; - - int nSamples = numSamples.at(eventSourceNodes[i]); - - - if (nSamples < samplesLeft) { - // std::cout << getNumInputs()+1 << " " << displayBufferIndex << " " << totalSamples << " " << ttlState << std::endl; - // - displayBuffer->copyFrom(chan, // destChannel - index, // destStartSample - arrayOfOnes, // source - nSamples, // numSamples - float(ttlState[eventSourceNodes[i]])); // gain - - displayBufferIndex.set(chan, index + nSamples); + + displayBuffer->copyFrom (chan, // destChannel + index, // destStartSample + arrayOfOnes, // source + nSamples, // numSamples + float (ttlState[eventSourceNodes[i]])); // gain + + displayBufferIndex.set (chan, index + nSamples); } else { - int extraSamples = nSamples - samplesLeft; - // std::cout << "OVERFLOW." << std::endl; - // std::cout << bufferIndex << " " << block1Size << " " << ttlState << std::endl; - - displayBuffer->copyFrom(chan, // destChannel - index, // destStartSample - arrayOfOnes, // source - samplesLeft, // numSamples - float(ttlState[eventSourceNodes[i]])); // gain - // std::cout << 0 << " " << block2Size << " " << ttlState << std::endl; + displayBuffer->copyFrom (chan, // destChannel + index, // destStartSample + arrayOfOnes, // source + samplesLeft, // numSamples + float (ttlState[eventSourceNodes[i]])); // gain - displayBuffer->copyFrom(chan, // destChannel - 0, // destStartSample - arrayOfOnes, // source - extraSamples, // numSamples - float(ttlState[eventSourceNodes[i]])); // gain + displayBuffer->copyFrom (chan, // destChannel + 0, // destStartSample + arrayOfOnes, // source + extraSamples, // numSamples + float (ttlState[eventSourceNodes[i]])); // gain - displayBufferIndex.set(chan, extraSamples); + displayBufferIndex.set (chan, extraSamples); } - } + } } -void LfpDisplayNode::process(AudioSampleBuffer& buffer, MidiBuffer& events) + +void LfpDisplayNode::process (AudioSampleBuffer& buffer, MidiBuffer& events) { // 1. place any new samples into the displayBuffer //std::cout << "Display node sample count: " << nSamples << std::endl; ///buffer.getNumSamples() << std::endl; initializeEventChannels(); - checkForEvents(events); // see if we got any TTL events + checkForEvents (events); // see if we got any TTL events - ScopedLock displayLock(displayMutex); + ScopedLock displayLock (displayMutex); - for (int chan = 0; chan < buffer.getNumChannels(); chan++) + for (int chan = 0; chan < buffer.getNumChannels(); ++chan) { - int samplesLeft = displayBuffer->getNumSamples() - displayBufferIndex[chan]; - int nSamples = getNumSamples(chan); + const int samplesLeft = displayBuffer->getNumSamples() - displayBufferIndex[chan]; + const int nSamples = getNumSamples (chan); if (nSamples < samplesLeft) { - - displayBuffer->copyFrom(chan, // destChannel - displayBufferIndex[chan], // destStartSample - buffer, // source - chan, // source channel - 0, // source start sample - nSamples); // numSamples - - displayBufferIndex.set(chan, displayBufferIndex[chan] + nSamples); + displayBuffer->copyFrom (chan, // destChannel + displayBufferIndex[chan], // destStartSample + buffer, // source + chan, // source channel + 0, // source start sample + nSamples); // numSamples + + displayBufferIndex.set (chan, displayBufferIndex[chan] + nSamples); } else { - - int extraSamples = nSamples - samplesLeft; - - displayBuffer->copyFrom(chan, // destChannel - displayBufferIndex[chan], // destStartSample - buffer, // source - chan, // source channel - 0, // source start sample - samplesLeft); // numSamples - - displayBuffer->copyFrom(chan, - 0, - buffer, - chan, - samplesLeft, - extraSamples); - - displayBufferIndex.set(chan, extraSamples); + const int extraSamples = nSamples - samplesLeft; + + displayBuffer->copyFrom (chan, // destChannel + displayBufferIndex[chan], // destStartSample + buffer, // source + chan, // source channel + 0, // source start sample + samplesLeft); // numSamples + + displayBuffer->copyFrom (chan, // destChannel + 0, // destStartSample + buffer, // source + chan, // source channel + samplesLeft, // source start sample + extraSamples); // numSamples + + displayBufferIndex.set (chan, extraSamples); } } - } diff --git a/Source/Plugins/LfpDisplayNodeBeta/LfpDisplayNode.h b/Source/Plugins/LfpDisplayNodeBeta/LfpDisplayNode.h index 9b595e827..f6a3c2d66 100644 --- a/Source/Plugins/LfpDisplayNodeBeta/LfpDisplayNode.h +++ b/Source/Plugins/LfpDisplayNodeBeta/LfpDisplayNode.h @@ -2,7 +2,7 @@ ------------------------------------------------------------------ This file is part of the Open Ephys GUI - Copyright (C) 2013 Open Ephys + Copyright (C) 2016 Open Ephys ------------------------------------------------------------------ @@ -32,8 +32,9 @@ class DataViewport; -namespace LfpDisplayNodeBeta { - +namespace LfpDisplayNodeBeta +{ + /** Holds data in a displayBuffer to be used by the LfpDisplayCanvas @@ -42,49 +43,34 @@ namespace LfpDisplayNodeBeta { @see GenericProcessor, LfpDisplayEditor, LfpDisplayCanvas */ - class LfpDisplayNode : public GenericProcessor { public: - LfpDisplayNode(); ~LfpDisplayNode(); - AudioProcessorEditor* createEditor(); + AudioProcessorEditor* createEditor() override; - bool isSink() - { - return true; - } + void process (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) override; - void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages); + void setParameter (int parameterIndex, float newValue) override; - void setParameter(int, float); + void updateSettings() override; - void updateSettings(); + bool enable() override; + bool disable() override; - bool enable(); - bool disable(); + void handleEvent (int, MidiMessage&, int) override; - void handleEvent(int, MidiMessage&, int); + AudioSampleBuffer* getDisplayBufferAddress() const { return displayBuffer; } - AudioSampleBuffer* getDisplayBufferAddress() - { - return displayBuffer; - } - int getDisplayBufferIndex(int chan) - { - return displayBufferIndex[chan]; - } + int getDisplayBufferIndex (int chan) const { return displayBufferIndex[chan]; } - CriticalSection* getMutex() - { - return &displayMutex; - } + CriticalSection* getMutex() { return &displayMutex; } -private: +private: void initializeEventChannels(); ScopedPointer<AudioSampleBuffer> displayBuffer; @@ -107,10 +93,9 @@ private: bool resizeBuffer(); - CriticalSection displayMutex; + CriticalSection displayMutex; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(LfpDisplayNode); - }; }; diff --git a/Source/Plugins/LfpTriggeredAverageNode/LfpTriggeredAverageNode.cpp b/Source/Plugins/LfpTriggeredAverageNode/LfpTriggeredAverageNode.cpp index f8bd5f3a3..11709c18c 100644 --- a/Source/Plugins/LfpTriggeredAverageNode/LfpTriggeredAverageNode.cpp +++ b/Source/Plugins/LfpTriggeredAverageNode/LfpTriggeredAverageNode.cpp @@ -2,7 +2,7 @@ ------------------------------------------------------------------ This file is part of the Open Ephys GUI - Copyright (C) 2013 Open Ephys + Copyright (C) 2016 Open Ephys ------------------------------------------------------------------ @@ -26,116 +26,119 @@ #include <stdio.h> LfpTriggeredAverageNode::LfpTriggeredAverageNode() - : GenericProcessor("LFP Trig. Avg."), - displayBufferIndex(0), displayGain(1), bufferLength(5.0f), - abstractFifo(100), ttlState(0) + : GenericProcessor ("LFP Trig. Avg.") + , displayBufferIndex (0) + , displayGain (1) + , bufferLength (5.0f) + , abstractFifo (100) + , ttlState (0) { + setProcessorType (PROCESSOR_TYPE_SINK); + std::cout << " LfpTriggeredAverageNode Constructor" << std::endl; - displayBuffer = new AudioSampleBuffer(8, 100); - eventBuffer = new MidiBuffer(); + displayBuffer = new AudioSampleBuffer (8, 100); + eventBuffer = new MidiBuffer; arrayOfOnes = new float[5000]; - for (int n = 0; n < 5000; n++) + for (int n = 0; n < 5000; ++n) { arrayOfOnes[n] = 1; } - } + LfpTriggeredAverageNode::~LfpTriggeredAverageNode() { - } + AudioProcessorEditor* LfpTriggeredAverageNode::createEditor() { - - editor = new LfpTriggeredAverageEditor(this, true); + editor = new LfpTriggeredAverageEditor (this, true); return editor; - } + void LfpTriggeredAverageNode::updateSettings() { std::cout << "Setting num inputs on LfpTriggeredAverageNode to " << getNumInputs() << std::endl; } + bool LfpTriggeredAverageNode::resizeBuffer() { - int nSamples = (int) getSampleRate()*bufferLength; - int nInputs = getNumInputs(); + const int nSamples = (int) getSampleRate() * bufferLength; + const int nInputs = getNumInputs(); std::cout << "Resizing buffer. Samples: " << nSamples << ", Inputs: " << nInputs << std::endl; if (nSamples > 0 && nInputs > 0) { - abstractFifo.setTotalSize(nSamples); - displayBuffer->setSize(nInputs+1, nSamples); // add an extra channel for TTLs + abstractFifo.setTotalSize (nSamples); + displayBuffer->setSize (nInputs + 1, nSamples); // add an extra channel for TTLs + return true; } else { return false; } - } + bool LfpTriggeredAverageNode::enable() { - if (resizeBuffer()) { LfpTriggeredAverageEditor* editor = (LfpTriggeredAverageEditor*) getEditor(); editor->enable(); + return true; } else { return false; } - } + bool LfpTriggeredAverageNode::disable() { LfpTriggeredAverageEditor* editor = (LfpTriggeredAverageEditor*) getEditor(); editor->disable(); + return true; } -void LfpTriggeredAverageNode::setParameter(int parameterIndex, float newValue) + +void LfpTriggeredAverageNode::setParameter (int parameterIndex, float newValue) { - editor->updateParameterButtons(parameterIndex); - //Sets Parameter in parameters array for processor - Parameter* parameterPointer=parameters.getRawDataPointer(); - parameterPointer=parameterPointer+parameterIndex; - parameterPointer->setValue(newValue, currentChannel); + editor->updateParameterButtons (parameterIndex); - //std::cout << "Saving Parameter from " << currentChannel << ", channel "; + //Sets Parameter in parameters array for processor + Parameter* parameterPointer = parameters.getRawDataPointer(); + parameterPointer += parameterIndex; + parameterPointer->setValue (newValue, currentChannel); LfpTriggeredAverageEditor* ed = (LfpTriggeredAverageEditor*) getEditor(); if (ed->canvas != 0) - ed->canvas->setParameter(parameterIndex, newValue); + ed->canvas->setParameter (parameterIndex, newValue); } -void LfpTriggeredAverageNode::handleEvent(int eventType, MidiMessage& event) + +void LfpTriggeredAverageNode::handleEvent (int eventType, MidiMessage& event) { if (eventType == TTL) { const uint8* dataptr = event.getRawData(); // int eventNodeId = *(dataptr+1); - int eventId = *(dataptr+2); - int eventChannel = *(dataptr+3); - int eventTime = event.getTimeStamp(); - - int samplesLeft = totalSamples - eventTime; - - // std::cout << "Received event from " << eventNodeId << ", channel " - // << eventChannel << ", with ID " << eventId << std::endl; - // - int bufferIndex = (displayBufferIndex + eventTime);// % displayBuffer->getNumSamples(); + const int eventId = *(dataptr + 2); + const int eventChannel = *(dataptr + 3); + const int eventTime = event.getTimeStamp(); + const int samplesLeft = totalSamples - eventTime; + const int bufferIndex = (displayBufferIndex + eventTime);// % displayBuffer->getNumSamples(); if (eventId == 1) { @@ -148,180 +151,122 @@ void LfpTriggeredAverageNode::handleEvent(int eventType, MidiMessage& event) if (samplesLeft + bufferIndex < displayBuffer->getNumSamples()) { - - // std::cout << bufferIndex << " " << samplesLeft << " " << ttlState << std::endl; - - displayBuffer->copyFrom(displayBuffer->getNumChannels()-1, // destChannel - bufferIndex, // destStartSample - arrayOfOnes, // source - samplesLeft, // numSamples - float(ttlState)); // gain + displayBuffer->copyFrom (displayBuffer->getNumChannels() - 1, // destChannel + bufferIndex, // destStartSample + arrayOfOnes, // source + samplesLeft, // numSamples + float (ttlState)); // gain } else { - - int block2Size = (samplesLeft + bufferIndex) % displayBuffer->getNumSamples(); - int block1Size = samplesLeft - block2Size; - - //std::cout << "OVERFLOW." << std::endl; - - //std::cout << bufferIndex << " " << block1Size << " " << ttlState << std::endl; - - displayBuffer->copyFrom(displayBuffer->getNumChannels()-1, // destChannel - bufferIndex, // destStartSample - arrayOfOnes, // source - block1Size, // numSamples - float(ttlState)); // gain - - //std::cout << 0 << " " << block2Size << " " << ttlState << std::endl; - - displayBuffer->copyFrom(displayBuffer->getNumChannels()-1, // destChannel - 0, // destStartSample - arrayOfOnes, // source - block2Size, // numSamples - float(ttlState)); // gain - - + const int block2Size = (samplesLeft + bufferIndex) % displayBuffer->getNumSamples(); + const int block1Size = samplesLeft - block2Size; + + displayBuffer->copyFrom (displayBuffer->getNumChannels() - 1, // destChannel + bufferIndex, // destStartSample + arrayOfOnes, // source + block1Size, // numSamples + float (ttlState)); // gain + + displayBuffer->copyFrom (displayBuffer->getNumChannels() - 1, // destChannel + 0, // destStartSample + arrayOfOnes, // source + block2Size, // numSamples + float (ttlState)); // gain } - - - // std::cout << "ttlState: " << ttlState << std::endl; - - // std::cout << "Received event from " << eventNodeId << - // " on channel " << eventChannel << - // " with value " << eventId << - // " at timestamp " << event.getTimeStamp() << std::endl; - - } else if (eventType == TIMESTAMP) { - const uint8* dataptr = event.getRawData(); - // int eventNodeId = *(dataptr+1); - // int eventId = *(dataptr+2); - // int eventChannel = *(dataptr+3); - // update the timestamp for the current buffer: - memcpy(&bufferTimestamp, dataptr+4, 4); - - - - // double timeInSeconds = double(ts)/Time::getHighResolutionTicksPerSecond(); - // //int64 timestamp = ts[0] << 32 + - // // ts[1] << 16 + - // // ts[2] << 8 + - // // ts[3]; - // //memcpy(ts, dataptr+4, 1); - - // std::cout << "Time in seconds is " << timeInSeconds << std::endl; - - // // std::cout << "Received event from " << eventNodeId << - // // " on channel " << eventChannel << - // // " with value " << eventId << - // // " for time: " << ts << std::endl; + memcpy (&bufferTimestamp, dataptr + 4, 4); } } + void LfpTriggeredAverageNode::initializeEventChannel() { if (displayBufferIndex + totalSamples < displayBuffer->getNumSamples()) { - - // std::cout << getNumInputs()+1 << " " << displayBufferIndex << " " << totalSamples << " " << ttlState << std::endl; - // - displayBuffer->copyFrom(displayBuffer->getNumChannels()-1, // destChannel - displayBufferIndex, // destStartSample - arrayOfOnes, // source - totalSamples, // numSamples - float(ttlState)); // gain + displayBuffer->copyFrom (displayBuffer->getNumChannels() - 1, // destChannel + displayBufferIndex, // destStartSample + arrayOfOnes, // source + totalSamples, // numSamples + float (ttlState)); // gain } else { - - int block2Size = (displayBufferIndex + totalSamples) % displayBuffer->getNumSamples(); - int block1Size = totalSamples - block2Size; - - // std::cout << "OVERFLOW." << std::endl; - - // std::cout << bufferIndex << " " << block1Size << " " << ttlState << std::endl; - - displayBuffer->copyFrom(displayBuffer->getNumChannels()-1, // destChannel - displayBufferIndex, // destStartSample - arrayOfOnes, // source - block1Size, // numSamples - float(ttlState)); // gain - // std::cout << 0 << " " << block2Size << " " << ttlState << std::endl; - - displayBuffer->copyFrom(displayBuffer->getNumChannels()-1, // destChannel - 0, // destStartSample - arrayOfOnes, // source - block2Size, // numSamples - float(ttlState)); // gain - - + const int block2Size = (displayBufferIndex + totalSamples) % displayBuffer->getNumSamples(); + const int block1Size = totalSamples - block2Size; + + displayBuffer->copyFrom(displayBuffer->getNumChannels() - 1, // destChannel + displayBufferIndex, // destStartSample + arrayOfOnes, // source + block1Size, // numSamples + float (ttlState)); // gain + + displayBuffer->copyFrom (displayBuffer->getNumChannels() - 1, // destChannel + 0, // destStartSample + arrayOfOnes, // source + block2Size, // numSamples + float (ttlState)); // gain } } -void LfpTriggeredAverageNode::process(AudioSampleBuffer& buffer, MidiBuffer& events) + +void LfpTriggeredAverageNode::process (AudioSampleBuffer& buffer, MidiBuffer& events) { // 1. place any new samples into the displayBuffer //std::cout << "Display node sample count: " << nSamples << std::endl; ///buffer.getNumSamples() << std::endl; - int nSamples = 100; + const int nSamples = 100; totalSamples = nSamples; //nSamples; displayBufferIndexEvents = displayBufferIndex; initializeEventChannel(); - checkForEvents(events); // update timestamp, see if we got any TTL events + checkForEvents (events); // update timestamp, see if we got any TTL events - int samplesLeft = displayBuffer->getNumSamples() - displayBufferIndex; + const int samplesLeft = displayBuffer->getNumSamples() - displayBufferIndex; if (nSamples < samplesLeft) { - - for (int chan = 0; chan < buffer.getNumChannels(); chan++) + for (int chan = 0; chan < buffer.getNumChannels(); ++chan) { - displayBuffer->copyFrom(chan, // destChannel - displayBufferIndex, // destStartSample - buffer, // source - chan, // source channel - 0, // source start sample - nSamples); // numSamples - + displayBuffer->copyFrom (chan, // destChannel + displayBufferIndex, // destStartSample + buffer, // source + chan, // source channel + 0, // source start sample + nSamples); // numSamples } - displayBufferIndex += (nSamples); + displayBufferIndex += (nSamples); } else { + const int extraSamples = nSamples - samplesLeft; - int extraSamples = nSamples - samplesLeft; - - for (int chan = 0; chan < buffer.getNumChannels(); chan++) + for (int chan = 0; chan < buffer.getNumChannels(); ++chan) { - displayBuffer->copyFrom(chan, // destChannel - displayBufferIndex, // destStartSample - buffer, // source - chan, // source channel - 0, // source start sample - samplesLeft); // numSamples - - displayBuffer->copyFrom(chan, - 0, - buffer, - chan, - samplesLeft, - extraSamples); + displayBuffer->copyFrom (chan, // destChannel + displayBufferIndex, // destStartSample + buffer, // source + chan, // source channel + 0, // source start sample + samplesLeft); // numSamples + + displayBuffer->copyFrom (chan, // destChannel + 0, // destStartSample + buffer, // source + chan, // source channel + samplesLeft, // source start sample + extraSamples); // numSamples } displayBufferIndex = extraSamples; } - - - } diff --git a/Source/Plugins/LfpTriggeredAverageNode/LfpTriggeredAverageNode.h b/Source/Plugins/LfpTriggeredAverageNode/LfpTriggeredAverageNode.h index b4cf606a3..131ef4ad9 100644 --- a/Source/Plugins/LfpTriggeredAverageNode/LfpTriggeredAverageNode.h +++ b/Source/Plugins/LfpTriggeredAverageNode/LfpTriggeredAverageNode.h @@ -2,7 +2,7 @@ ------------------------------------------------------------------ This file is part of the Open Ephys GUI - Copyright (C) 2013 Open Ephys + Copyright (C) 2016 Open Ephys ------------------------------------------------------------------ @@ -32,50 +32,34 @@ class DataViewport; /** + Displays the average of a continuous signal, triggered on a certain event channel. - Displays the average of a continuous signal, triggered on a certain event channel. - - @see GenericProcessor, LfpTriggeredAverageEditor, LfpDisplayCanvas - + @see GenericProcessor, LfpTriggeredAverageEditor, LfpDisplayCanvas */ - class LfpTriggeredAverageNode : public GenericProcessor - { public: - LfpTriggeredAverageNode(); ~LfpTriggeredAverageNode(); - AudioProcessorEditor* createEditor(); + AudioProcessorEditor* createEditor() override; - bool isSink() - { - return true; - } + void process (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) override; - void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages); + void setParameter (int parameterIndex, float newValue) override; - void setParameter(int, float); + void updateSettings() override; - void updateSettings(); + bool enable() override; + bool disable() override; - bool enable(); - bool disable(); + void handleEvent (int, MidiMessage&) override; - void handleEvent(int, MidiMessage&); + AudioSampleBuffer* getDisplayBufferAddress() const { return displayBuffer; } + int getDisplayBufferIndex() const { return displayBufferIndex; } - AudioSampleBuffer* getDisplayBufferAddress() - { - return displayBuffer; - } - int getDisplayBufferIndex() - { - return displayBufferIndex; - } private: - void initializeEventChannel(); ScopedPointer<AudioSampleBuffer> displayBuffer; @@ -98,11 +82,8 @@ private: bool resizeBuffer(); - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(LfpTriggeredAverageNode); - + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LfpTriggeredAverageNode); }; - - #endif // __LFPTRIGAVGNODE_H_D969A379__ diff --git a/Source/Plugins/NetworkEvents/NetworkEvents.cpp b/Source/Plugins/NetworkEvents/NetworkEvents.cpp index 0982e85d8..772132e21 100644 --- a/Source/Plugins/NetworkEvents/NetworkEvents.cpp +++ b/Source/Plugins/NetworkEvents/NetworkEvents.cpp @@ -1,23 +1,23 @@ /* ------------------------------------------------------------------- + ------------------------------------------------------------------ -This file is part of the Open Ephys GUI -Copyright (C) 2015 Open Ephys + This file is part of the Open Ephys GUI + Copyright (C) 2016 Open Ephys ------------------------------------------------------------------- + ------------------------------------------------------------------ -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program. If not, see <http://www.gnu.org/licenses/>. + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -30,26 +30,27 @@ const int MAX_MESSAGE_LENGTH = 64000; #ifdef WIN32 -#include <windows.h> + #include <windows.h> #else -#include <unistd.h> + #include <unistd.h> #endif + StringTS::StringTS() { - str = nullptr; len= 0; timestamp = 0; } -std::vector<String> StringTS::splitString(char sep) +std::vector<String> StringTS::splitString (char sep) { - String S((const char*)str,len); + String S ((const char*)str, len); + String curr; + std::list<String> ls; - String curr; - for (int k=0; k < S.length(); k++) + for (int k = 0; k < S.length(); ++k) { if (S[k] != sep) { @@ -57,104 +58,121 @@ std::vector<String> StringTS::splitString(char sep) } else { - ls.push_back(curr); + ls.push_back (curr); while (S[k] == sep && k < S.length()) - k++; + ++k; curr = ""; if (S[k] != sep && k < S.length()) - curr+=S[k]; + curr += S[k]; } } if (S.length() > 0) { - if (S[S.length()-1] != sep) - ls.push_back(curr); + if (S[S.length() - 1] != sep) + ls.push_back (curr); } - std::vector<String> Svec(ls.begin(), ls.end()); - return Svec; + std::vector<String> Svec (ls.begin(), ls.end()); + return Svec; } -StringTS::StringTS(MidiMessage& event) + +StringTS::StringTS (MidiMessage& event) { const uint8* dataptr = event.getRawData(); - int bufferSize = event.getRawDataSize(); - len = bufferSize-6-8; // -6 for initial event prefix, -8 for timestamp at the end + const int bufferSize = event.getRawDataSize(); + len = bufferSize - 6 - 8; // -6 for initial event prefix, -8 for timestamp at the end - memcpy(×tamp, dataptr + 6+ len, 8); // remember to skip first six bytes + memcpy (×tamp, dataptr + 6 + len, 8); // remember to skip first six bytes str = new uint8[len]; - memcpy(str,dataptr + 6, len); + memcpy (str,dataptr + 6, len); } -StringTS& StringTS::operator=(const StringTS& rhs) + +StringTS& StringTS::operator= (const StringTS& rhs) { - delete(str); + delete (str); len = rhs.len; str = new uint8[len]; - memcpy(str,rhs.str,len); + memcpy (str,rhs.str,len); timestamp = rhs.timestamp; return *this; } + String StringTS::getString() { - return String((const char*)str,len); + return String ((const char*)str,len); } -StringTS::StringTS(String S) + +StringTS::StringTS (String S) { Time t; str = new uint8[S.length()]; - memcpy(str,S.toRawUTF8(),S.length()); + memcpy (str, S.toRawUTF8(), S.length()); timestamp = t.getHighResolutionTicks(); len = S.length(); } -StringTS::StringTS(String S, int64 ts_software) + +StringTS::StringTS (String S, int64 ts_software) { str = new uint8[S.length()]; - memcpy(str,S.toRawUTF8(),S.length()); + memcpy (str, S.toRawUTF8(), S.length()); timestamp = ts_software; len = S.length(); } -StringTS::StringTS(const StringTS& s) + +StringTS::StringTS (const StringTS& s) { str = new uint8[s.len]; - memcpy(str,s.str,s.len); + memcpy (str, s.str, s.len); timestamp = s.timestamp; len = s.len; } -StringTS::StringTS(unsigned char* buf, int _len, int64 ts_software) : len(_len),timestamp(ts_software) +StringTS::StringTS (unsigned char* buf, int _len, int64 ts_software) + : len (_len) + ,timestamp (ts_software) { str = new juce::uint8[len]; - for (int k=0; k<len; k++) + for (int k = 0; k < len; ++k) str[k] = buf[k]; } + StringTS::~StringTS() { delete str; } + /*********************************************/ void* NetworkEvents::zmqcontext = nullptr; NetworkEvents::NetworkEvents() - : GenericProcessor("Network Events"), Thread("NetworkThread"), threshold(200.0), bufferZone(5.0f), state(false) - + : GenericProcessor ("Network Events") + , Thread ("NetworkThread") + , threshold (200.0) + , bufferZone (5.0f) + , state (false) { + setProcessorType (PROCESSOR_TYPE_SOURCE); + createZmqContext(); + firstTime = true; responder = nullptr; urlport = 5556; threadRunning = false; + opensocket(); sendSampleCount = false; // disable updating the continuous buffer sample counts, @@ -162,99 +180,99 @@ NetworkEvents::NetworkEvents() shutdown = false; } -void NetworkEvents::setNewListeningPort(int port) + +void NetworkEvents::setNewListeningPort (int port) { // first, close existing thread. closesocket(); + // allow some time for thread to quit #ifdef WIN32 - Sleep(300); + Sleep (300); #else - usleep(300 * 1000); + usleep (300 * 1000); #endif - urlport = port; opensocket(); } + NetworkEvents::~NetworkEvents() { shutdown = true; closesocket(); } + bool NetworkEvents::closesocket() { - std::cout << "Disabling network node" << std::endl; #ifdef ZEROMQ if (threadRunning) { - zmq_close(responder); - zmq_ctx_destroy(zmqcontext); // this will cause the thread to exit + zmq_close (responder); + zmq_ctx_destroy (zmqcontext); // this will cause the thread to exit zmqcontext = nullptr; - if (!shutdown) + if (! shutdown) createZmqContext();// and this will take care that processor graph doesn't attempt to delete the context again } #endif return true; } -int NetworkEvents::getNumEventChannels() + +int NetworkEvents::getNumEventChannels() const { return 1; } + void NetworkEvents::updateSettings() { eventChannels[0]->type = MESSAGE_CHANNEL; // so it's ignored by LFP Viewer } -AudioProcessorEditor* NetworkEvents::createEditor( -) + +AudioProcessorEditor* NetworkEvents::createEditor () { - editor = new NetworkEventsEditor(this, true); + editor = new NetworkEventsEditor (this, true); return editor; - - } -void NetworkEvents::setParameter(int parameterIndex, float newValue) +void NetworkEvents::setParameter (int parameterIndex, float newValue) { /* - editor->updateParameterButtons(parameterIndex); + editor->updateParameterButtons(parameterIndex); - Parameter& p = parameters.getReference(parameterIndex); - p.setValue(newValue, 0); + Parameter& p = parameters.getReference(parameterIndex); + p.setValue(newValue, 0); - threshold = newValue; - */ + threshold = newValue; + */ //std::cout << float(p[0]) << std::endl; - } + void NetworkEvents::initSimulation() { Time t; - int64 secondsToTicks = t.getHighResolutionTicksPerSecond(); - simulationStartTime=3*secondsToTicks + t.getHighResolutionTicks(); // start 10 seconds after - - simulation.push(StringTS("ClearDesign",simulationStartTime)); - simulation.push(StringTS("NewDesign Test",simulationStartTime+0.5*secondsToTicks)); - simulation.push(StringTS("AddCondition Name GoRight TrialTypes 1 2 3",simulationStartTime+0.6*secondsToTicks)); - simulation.push(StringTS("AddCondition Name GoLeft TrialTypes 4 5 6",simulationStartTime+0.6*secondsToTicks)); - - + const int64 secondsToTicks = t.getHighResolutionTicksPerSecond(); + simulationStartTime = 3 * secondsToTicks + t.getHighResolutionTicks(); // start 10 seconds after + simulation.push (StringTS ("ClearDesign", simulationStartTime)); + simulation.push (StringTS ("NewDesign Test", simulationStartTime + 0.5 * secondsToTicks)); + simulation.push (StringTS ("AddCondition Name GoRight TrialTypes 1 2 3", simulationStartTime + 0.6 * secondsToTicks)); + simulation.push (StringTS ("AddCondition Name GoLeft TrialTypes 4 5 6", simulationStartTime + 0.6 * secondsToTicks)); } -void NetworkEvents::simulateDesignAndTrials(juce::MidiBuffer& events) + +void NetworkEvents::simulateDesignAndTrials (juce::MidiBuffer& events) { Time t; while (simulation.size() > 0) @@ -263,66 +281,67 @@ void NetworkEvents::simulateDesignAndTrials(juce::MidiBuffer& events) StringTS S = simulation.front(); if (currenttime > S.timestamp) { - // handle special messages - handleSpecialMessages(S); + handleSpecialMessages (S); - postTimestamppedStringToMidiBuffer(S,events); + postTimestamppedStringToMidiBuffer (S,events); //getUIComponent()->getLogWindow()->addLineToLog(S.getString()); simulation.pop(); } else + { break; + } } } -void NetworkEvents::handleEvent(int eventType, juce::MidiMessage& event, int samplePosition) +void NetworkEvents::handleEvent (int eventType, juce::MidiMessage& event, int samplePosition) { - } -void NetworkEvents::postTimestamppedStringToMidiBuffer(StringTS s, MidiBuffer& events) + +void NetworkEvents::postTimestamppedStringToMidiBuffer (StringTS s, MidiBuffer& events) { uint8* msg_with_ts = new uint8[s.len+1];//+8]; // for the two timestamps - memcpy(msg_with_ts, s.str, s.len); + memcpy (msg_with_ts, s.str, s.len); *(msg_with_ts + s.len) = '\0'; - //memcpy(msg_with_ts+s.len, &s.timestamp, 8); - addEvent(events, - (uint8) MESSAGE, - 0, - 1, - 0, - (uint8) s.len+1,//+8, - msg_with_ts); + addEvent (events, + (uint8) MESSAGE, + 0, + 1, + 0, + (uint8) s.len + 1,//+8, + msg_with_ts); delete[] msg_with_ts; } + void NetworkEvents::simulateStopRecord() { Time t; - simulation.push(StringTS("StopRecord",t.getHighResolutionTicks())); - + simulation.push (StringTS ("StopRecord", t.getHighResolutionTicks())); } + void NetworkEvents::simulateStartRecord() { Time t; - simulation.push(StringTS("StartRecord",t.getHighResolutionTicks())); - + simulation.push (StringTS ("StartRecord", t.getHighResolutionTicks())); } + void NetworkEvents::simulateSingleTrial() { - std::cout << "Simulating trial." << std::endl; - int numTrials = 1; - float ITI = 0.7; - float TrialLength = 0.4; + const int numTrials = 1; + const float ITI = 0.7; + const float TrialLength = 0.4; + Time t; if (firstTime) @@ -332,26 +351,31 @@ void NetworkEvents::simulateSingleTrial() } int64 secondsToTicks = t.getHighResolutionTicksPerSecond(); - simulationStartTime=3*secondsToTicks + t.getHighResolutionTicks(); // start 10 seconds after + simulationStartTime = 3 * secondsToTicks + t.getHighResolutionTicks(); // start 10 seconds after // trial every 5 seconds - for (int k=0; k<numTrials; k++) + for (int k = 0; k < numTrials; ++k) { - simulation.push(StringTS("TrialStart",simulationStartTime+ITI*k*secondsToTicks)); - if (k%2 == 0) - simulation.push(StringTS("TrialType 2",simulationStartTime+(ITI*k+0.1)*secondsToTicks)); // 100 ms after trial start - else - simulation.push(StringTS("TrialType 4",simulationStartTime+(ITI*k+0.1)*secondsToTicks)); // 100 ms after trial start - - simulation.push(StringTS("TrialAlign",simulationStartTime+(ITI*k+0.1)*secondsToTicks)); // 100 ms after trial start - simulation.push(StringTS("TrialOutcome 1",simulationStartTime+(ITI*k+0.3)*secondsToTicks)); // 300 ms after trial start - simulation.push(StringTS("TrialEnd",simulationStartTime+(ITI*k+TrialLength)*secondsToTicks)); // 400 ms after trial start + simulation.push (StringTS ("TrialStart", simulationStartTime + ITI * k * secondsToTicks)); + if (k % 2 == 0) + // 100 ms after trial start + simulation.push (StringTS ("TrialType 2", simulationStartTime + (ITI * k + 0.1) * secondsToTicks)); + else + // 100 ms after trial start + simulation.push (StringTS ("TrialType 4", simulationStartTime + (ITI * k + 0.1) * secondsToTicks)); + + // 100 ms after trial start + simulation.push (StringTS ("TrialAlign", simulationStartTime + (ITI * k + 0.1) * secondsToTicks)); + // 300 ms after trial start + simulation.push (StringTS ("TrialOutcome 1", simulationStartTime + (ITI * k + 0.3) * secondsToTicks)); + // 400 ms after trial start + simulation.push (StringTS ("TrialEnd", simulationStartTime + (ITI * k + TrialLength) * secondsToTicks)); } } -String NetworkEvents::handleSpecialMessages(StringTS msg) +String NetworkEvents::handleSpecialMessages (StringTS msg) { /* std::vector<String> input = msg.splitString(' '); @@ -404,135 +428,131 @@ String NetworkEvents::handleSpecialMessages(StringTS msg) */ - /** Start/stop data acquisition */ - String s = msg.getString(); - - /** Command is first substring */ - StringArray inputs = StringArray::fromTokens(s, " "); - String cmd = String(inputs[0]); - - const MessageManagerLock mmLock; - if (cmd.compareIgnoreCase("StartAcquisition") == 0) - { - if (!CoreServices::getAcquisitionStatus()) - { - CoreServices::setAcquisitionStatus(true); - } - return String("StartedAcquisition"); - } - else if (cmd.compareIgnoreCase("StopAcquisition") == 0) - { - if (CoreServices::getAcquisitionStatus()) - { - CoreServices::setAcquisitionStatus(false); - } - return String("StoppedAcquisition"); - } - else if (String("StartRecord").compareIgnoreCase(cmd) == 0) - { - if (!CoreServices::getRecordingStatus() && CoreServices::getAcquisitionStatus()) - { - /** First set optional parameters (name/value pairs)*/ - if (s.contains("=")) - { - String params = s.substring(cmd.length()); - StringPairArray dict = parseNetworkMessage(params); - - StringArray keys = dict.getAllKeys(); - for (int i = 0; i<keys.size(); i++) - { - String key = keys[i]; - String value = dict[key]; - - if (key.compareIgnoreCase("CreateNewDir") == 0) - { - if (value.compareIgnoreCase("1") == 0) - { - CoreServices::createNewRecordingDir(); - } - } - else if (key.compareIgnoreCase("RecDir") == 0) - { - CoreServices::setRecordingDirectory(value); - } - else if (key.compareIgnoreCase("PrependText") == 0) - { - CoreServices::setPrependTextToRecordingDir(value); - } - else if (key.compareIgnoreCase("AppendText") == 0) - { - CoreServices::setAppendTextToRecordingDir(value); - } - } - } - - /** Start recording */ - CoreServices::setRecordingStatus(true); - return String("StartedRecording"); - } - } - else if (String("StopRecord").compareIgnoreCase(cmd) == 0) - { - if (CoreServices::getRecordingStatus()) - { - CoreServices::setRecordingStatus(false); - return String("StoppedRecording"); - } - } - else if (cmd.compareIgnoreCase("IsAcquiring") == 0) - { - String status = CoreServices::getAcquisitionStatus() ? String("1") : String("0"); - return status; - } - else if (cmd.compareIgnoreCase("IsRecording") == 0) - { - String status = CoreServices::getRecordingStatus() ? String("1") : String("0"); - return status; - } - else if (cmd.compareIgnoreCase("GetRecordingPath") == 0) - { - File file = CoreServices::RecordNode::getRecordingPath(); - String msg(file.getFullPathName()); - return msg; - } - else if (cmd.compareIgnoreCase("GetRecordingNumber") == 0) - { - String status; - status += (CoreServices::RecordNode::getRecordingNumber() +1); - return status; - } - else if (cmd.compareIgnoreCase("GetExperimentNumber") == 0) - { - String status; - status += CoreServices::RecordNode::getExperimentNumber(); - return status; - } - - return String("NotHandled"); -} - -void NetworkEvents::process(AudioSampleBuffer& buffer, - MidiBuffer& events) -{ - - //std::cout << "NETWORK NODE" << std::endl; - //printf("Entering NetworkEvents::process\n"); - setTimestamp(events,CoreServices::getGlobalTimestamp()); - checkForEvents(events); + /** Start/stop data acquisition */ + String s = msg.getString(); + + /** Command is first substring */ + StringArray inputs = StringArray::fromTokens (s, " "); + String cmd = String (inputs[0]); + + const MessageManagerLock mmLock; + if (cmd.compareIgnoreCase ("StartAcquisition") == 0) + { + if (! CoreServices::getAcquisitionStatus()) + { + CoreServices::setAcquisitionStatus (true); + } + return String ("StartedAcquisition"); + } + else if (cmd.compareIgnoreCase ("StopAcquisition") == 0) + { + if (CoreServices::getAcquisitionStatus()) + { + CoreServices::setAcquisitionStatus (false); + } + return String ("StoppedAcquisition"); + } + else if (String ("StartRecord").compareIgnoreCase (cmd) == 0) + { + if (! CoreServices::getRecordingStatus() + && CoreServices::getAcquisitionStatus()) + { + /** First set optional parameters (name/value pairs)*/ + if (s.contains ("=")) + { + String params = s.substring (cmd.length()); + StringPairArray dict = parseNetworkMessage (params); + + StringArray keys = dict.getAllKeys(); + for (int i = 0; i < keys.size(); ++i) + { + String key = keys[i]; + String value = dict[key]; + + if (key.compareIgnoreCase ("CreateNewDir") == 0) + { + if (value.compareIgnoreCase ("1") == 0) + { + CoreServices::createNewRecordingDir(); + } + } + else if (key.compareIgnoreCase ("RecDir") == 0) + { + CoreServices::setRecordingDirectory (value); + } + else if (key.compareIgnoreCase ("PrependText") == 0) + { + CoreServices::setPrependTextToRecordingDir (value); + } + else if (key.compareIgnoreCase ("AppendText") == 0) + { + CoreServices::setAppendTextToRecordingDir (value); + } + } + } + + /** Start recording */ + CoreServices::setRecordingStatus (true); + return String ("StartedRecording"); + } + } + else if (String ("StopRecord").compareIgnoreCase (cmd) == 0) + { + if (CoreServices::getRecordingStatus()) + { + CoreServices::setRecordingStatus (false); + return String ("StoppedRecording"); + } + } + else if (cmd.compareIgnoreCase ("IsAcquiring") == 0) + { + String status = CoreServices::getAcquisitionStatus() ? String ("1") : String ("0"); + return status; + } + else if (cmd.compareIgnoreCase ("IsRecording") == 0) + { + String status = CoreServices::getRecordingStatus() ? String ("1") : String ("0"); + return status; + } + else if (cmd.compareIgnoreCase ("GetRecordingPath") == 0) + { + File file = CoreServices::RecordNode::getRecordingPath(); + String msg (file.getFullPathName()); + return msg; + } + else if (cmd.compareIgnoreCase ("GetRecordingNumber") == 0) + { + String status; + status += (CoreServices::RecordNode::getRecordingNumber() + 1); + return status; + } + else if (cmd.compareIgnoreCase ("GetExperimentNumber") == 0) + { + String status; + status += CoreServices::RecordNode::getExperimentNumber(); + return status; + } + + return String ("NotHandled"); +} + + +void NetworkEvents::process (AudioSampleBuffer& buffer, MidiBuffer& events) +{ + setTimestamp (events,CoreServices::getGlobalTimestamp()); + checkForEvents (events); //simulateDesignAndTrials(events); - //std::cout << *buffer.getSampleData(0, 0) << std::endl; lock.enter(); - while (!networkMessagesQueue.empty()) + while (! networkMessagesQueue.empty()) { StringTS msg = networkMessagesQueue.front(); - postTimestamppedStringToMidiBuffer(msg, events); - CoreServices::sendStatusMessage(("Network event received: " + msg.getString()).toRawUTF8()); - // getUIComponent()->getLogWindow()->addLineToLog(msg); + postTimestamppedStringToMidiBuffer (msg, events); + CoreServices::sendStatusMessage ( ("Network event received: " + msg.getString()).toRawUTF8()); networkMessagesQueue.pop(); } - lock.exit(); + lock.exit(); } @@ -541,127 +561,116 @@ void NetworkEvents::opensocket() startThread(); } + void NetworkEvents::run() { - #ifdef ZEROMQ - responder = zmq_socket(zmqcontext, ZMQ_REP); - String url= String("tcp://*:")+String(urlport); - int rc = zmq_bind(responder, url.toRawUTF8()); + responder = zmq_socket (zmqcontext, ZMQ_REP); + String url= String ("tcp://*:") + String (urlport); + int rc = zmq_bind (responder, url.toRawUTF8()); if (rc != 0) { // failed to open socket? - std::cout << "Failed to open socket: " << zmq_strerror(zmq_errno()) << std::endl; + std::cout << "Failed to open socket: " << zmq_strerror (zmq_errno()) << std::endl; return; } threadRunning = true; unsigned char* buffer = new unsigned char[MAX_MESSAGE_LENGTH]; - int result=-1; + int result = -1; while (threadRunning) { - - result = zmq_recv(responder, buffer, MAX_MESSAGE_LENGTH-1, 0); // blocking + result = zmq_recv (responder, buffer, MAX_MESSAGE_LENGTH - 1, 0); // blocking juce::int64 timestamp_software = timer.getHighResolutionTicks(); if (result < 0) // will only happen when responder dies. break; - StringTS Msg(buffer, result, timestamp_software); + StringTS Msg (buffer, result, timestamp_software); if (result > 0) { lock.enter(); - networkMessagesQueue.push(Msg); + networkMessagesQueue.push (Msg); lock.exit(); //std::cout << "Received message!" << std::endl; // handle special messages - String response = handleSpecialMessages(Msg); + String response = handleSpecialMessages (Msg); - zmq_send(responder, response.getCharPointer(), response.length(), 0); + zmq_send (responder, response.getCharPointer(), response.length(), 0); } else { String zeroMessageError = "Recieved Zero Message?!?!?"; //std::cout << "Received Zero Message!" << std::endl; - zmq_send(responder, zeroMessageError.getCharPointer(), zeroMessageError.length(), 0); + zmq_send (responder, zeroMessageError.getCharPointer(), zeroMessageError.length(), 0); } } + zmq_close (responder); - zmq_close(responder); delete[] buffer; threadRunning = false; + return; #endif } - - - +int NetworkEvents::getDefaultNumOutputs() const +{ + return 0; +} bool NetworkEvents::isReady() { - return true; - } -float NetworkEvents::getDefaultSampleRate() +float NetworkEvents::getDefaultSampleRate() const { return 30000.0f; } -int NetworkEvents::getDefaultNumOutputs() -{ - return 0; -} -float NetworkEvents::getDefaultBitVolts() +float NetworkEvents::getDefaultBitVolts() const { return 0.05f; } -void NetworkEvents::enabledState(bool t) +void NetworkEvents::setEnabledState (bool newState) { - - isEnabled = t; - + isEnabled = newState; } -bool NetworkEvents::isSource() -{ - return true; -} -void NetworkEvents::saveCustomParametersToXml(XmlElement* parentElement) +void NetworkEvents::saveCustomParametersToXml (XmlElement* parentElement) { - XmlElement* mainNode = parentElement->createNewChildElement("NETWORKEVENTS"); - mainNode->setAttribute("port", urlport); + XmlElement* mainNode = parentElement->createNewChildElement ("NETWORKEVENTS"); + mainNode->setAttribute ("port", urlport); } void NetworkEvents::loadCustomParametersFromXml() { - if (parametersAsXml != nullptr) { - forEachXmlChildElement(*parametersAsXml, mainNode) + forEachXmlChildElement (*parametersAsXml, mainNode) { - if (mainNode->hasTagName("NETWORKEVENTS")) + if (mainNode->hasTagName ("NETWORKEVENTS")) { - setNewListeningPort(mainNode->getIntAttribute("port")); + setNewListeningPort (mainNode->getIntAttribute("port")); } } } } + void NetworkEvents::createZmqContext() { #ifdef ZEROMQ @@ -670,50 +679,52 @@ void NetworkEvents::createZmqContext() #endif } -StringPairArray NetworkEvents::parseNetworkMessage(String msg) -{ - StringArray splitted; - splitted.addTokens(msg, "=", ""); - - StringPairArray dict = StringPairArray(); - String key = ""; - String value = ""; - for (int i = 0; i<splitted.size() - 1; i++) - { - String s1 = splitted[i]; - String s2 = splitted[i + 1]; - - /** Get key */ - if (!key.isEmpty()) - { - if (s1.contains(" ")) - { - int i1 = s1.lastIndexOf(" "); - key = s1.substring(i1 + 1); - } - else - { - key = s1; - } - } - else - { - key = s1.trim(); - } - - /** Get value */ - if (i < splitted.size() - 2) - { - int i1 = s2.lastIndexOf(" "); - value = s2.substring(0, i1); - } - else - { - value = s2; - } - - dict.set(key, value); - } - - return dict; + +StringPairArray NetworkEvents::parseNetworkMessage (String msg) +{ + StringArray splitted; + splitted.addTokens (msg, "=", ""); + + StringPairArray dict = StringPairArray(); + String key = ""; + String value = ""; + + for (int i = 0; i < splitted.size() - 1; ++i) + { + String s1 = splitted[i]; + String s2 = splitted[i + 1]; + + /** Get key */ + if (! key.isEmpty()) + { + if (s1.contains (" ")) + { + int i1 = s1.lastIndexOf (" "); + key = s1.substring (i1 + 1); + } + else + { + key = s1; + } + } + else + { + key = s1.trim(); + } + + /** Get value */ + if (i < splitted.size() - 2) + { + int i1 = s2.lastIndexOf (" "); + value = s2.substring (0, i1); + } + else + { + value = s2; + } + + dict.set (key, value); + } + + return dict; } diff --git a/Source/Plugins/NetworkEvents/NetworkEvents.h b/Source/Plugins/NetworkEvents/NetworkEvents.h index 9341601c0..61a581528 100644 --- a/Source/Plugins/NetworkEvents/NetworkEvents.h +++ b/Source/Plugins/NetworkEvents/NetworkEvents.h @@ -2,7 +2,7 @@ ------------------------------------------------------------------ This file is part of the Open Ephys GUI - Copyright (C) 2015 Open Ephys + Copyright (C) 2016 Open Ephys ------------------------------------------------------------------ @@ -26,15 +26,13 @@ //#define ZEROMQ #ifdef ZEROMQ - -#ifdef WIN32 -//#pragma comment( lib, "../../Resources/windows-libs/ZeroMQ/lib_x64/libzmq-v120-mt-4_0_4.lib" ) -#include <zmq.h> -#include <zmq_utils.h> -#else -#include <zmq.h> -#endif - + #ifdef WIN32 + //#pragma comment( lib, "../../Resources/windows-libs/ZeroMQ/lib_x64/libzmq-v120-mt-4_0_4.lib" ) + #include <zmq.h> + #include <zmq_utils.h> + #else + #include <zmq.h> + #endif #endif #include <ProcessorHeaders.h> @@ -42,100 +40,120 @@ #include <list> #include <queue> -/** +class StringTS; + +/** Sends incoming TCP/IP messages from 0MQ to the events buffer @see GenericProcessor - */ - -class StringTS -{ -public: - StringTS(); - std::vector<String> splitString(char sep); - StringTS(MidiMessage& event); - String getString(); - StringTS(String S); - StringTS(String S, int64 ts_software); - StringTS(const StringTS& s); - StringTS(unsigned char* buf, int _len, int64 ts_software); - StringTS& operator=(const StringTS& rhs); - ~StringTS(); - - juce::uint8* str; - int len; - juce::int64 timestamp; -}; - -class NetworkEvents : public GenericProcessor, public Thread +class NetworkEvents : public GenericProcessor + , public Thread { public: NetworkEvents(); ~NetworkEvents(); - AudioProcessorEditor* createEditor(); - int64 getExtrapolatedHardwareTimestamp(int64 softwareTS); - void initSimulation(); - void simulateDesignAndTrials(juce::MidiBuffer& events); - void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages); - void setParameter(int parameterIndex, float newValue); - String handleSpecialMessages(StringTS msg); - std::vector<String> splitString(String S, char sep); - void simulateSingleTrial(); - bool isSource(); + // GenericProcessor methods + // ========================================================================= + AudioProcessorEditor* createEditor() override; - void simulateStartRecord(); - void simulateStopRecord(); - bool closesocket(); - void run(); - void opensocket(); + void process (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) override; + + void setParameter (int parameterIndex, float newValue) override; + + void updateSettings() override; - void updateSettings(); + void setEnabledState (bool newState) override; - bool isReady(); - float getDefaultSampleRate(); - int getDefaultNumOutputs(); - float getDefaultBitVolts(); - void enabledState(bool t); + void saveCustomParametersToXml (XmlElement* parentElement) override; + void loadCustomParametersFromXml() override; - int getNumEventChannels(); + bool isReady() override; - void postTimestamppedStringToMidiBuffer(StringTS s, MidiBuffer& events); - void setNewListeningPort(int port); + float getDefaultSampleRate() const override; + float getDefaultBitVolts() const override; - void saveCustomParametersToXml(XmlElement* parentElement); - void loadCustomParametersFromXml(); + int getNumEventChannels() const override; + // ========================================================================= + + int getDefaultNumOutputs() const; + + //int64 getExtrapolatedHardwareTimestamp (int64 softwareTS) const; + + String handleSpecialMessages (StringTS msg); + std::vector<String> splitString (String S, char sep); + + void initSimulation(); + void simulateDesignAndTrials (juce::MidiBuffer& events); + void simulateSingleTrial(); + void simulateStartRecord(); + void simulateStopRecord(); + void run(); + void opensocket(); + bool closesocket(); + + void postTimestamppedStringToMidiBuffer (StringTS s, MidiBuffer& events); + void setNewListeningPort (int port); int urlport; String socketStatus; - bool threadRunning ; + bool threadRunning; + + private: - void handleEvent(int eventType, MidiMessage& event, int samplePos); + void handleEvent (int eventType, MidiMessage& event, int samplePos) override; void createZmqContext(); - //* Split network message into name/value pairs (name1=val1 name2=val2 etc) */ - StringPairArray parseNetworkMessage(String msg); + //* Split network message into name/value pairs (name1=val1 name2=val2 etc) */ + StringPairArray parseNetworkMessage (String msg); - StringTS createStringTS(String S, int64 t); + StringTS createStringTS (String S, int64 t); static void* zmqcontext; void* responder; + float threshold; float bufferZone; + bool state; bool shutdown; + bool firstTime; + Time timer; + std::queue<StringTS> networkMessagesQueue; + std::queue<StringTS> simulation; CriticalSection lock; - std::queue<StringTS> simulation; int64 simulationStartTime; - bool firstTime ; - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NetworkEvents); + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NetworkEvents); +}; + + +class StringTS +{ +public: + StringTS(); + StringTS (MidiMessage& event); + StringTS (String S); + StringTS (String S, int64 ts_software); + StringTS (const StringTS& s); + StringTS (unsigned char* buf, int _len, int64 ts_software); + ~StringTS(); + std::vector<String> splitString (char sep); + String getString(); + + StringTS& operator= (const StringTS& rhs); + + juce::uint8* str; + int len; + juce::int64 timestamp; }; + + #endif // __NETWORKEVENT_H_91811541__ diff --git a/Source/Plugins/PhaseDetector/PhaseDetector.cpp b/Source/Plugins/PhaseDetector/PhaseDetector.cpp index 40681ebe2..231839177 100644 --- a/Source/Plugins/PhaseDetector/PhaseDetector.cpp +++ b/Source/Plugins/PhaseDetector/PhaseDetector.cpp @@ -2,7 +2,7 @@ ------------------------------------------------------------------ This file is part of the Open Ephys GUI - Copyright (C) 2013 Open Ephys + Copyright (C) 2016 Open Ephys ------------------------------------------------------------------ @@ -18,35 +18,40 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. - */ #include <stdio.h> #include "PhaseDetector.h" #include "PhaseDetectorEditor.h" -PhaseDetector::PhaseDetector() - : GenericProcessor("Phase Detector"), activeModule(-1), - risingPos(false), risingNeg(false), fallingPos(false), fallingNeg(false) +PhaseDetector::PhaseDetector() + : GenericProcessor ("Phase Detector") + , activeModule (-1) + , risingPos (false) + , risingNeg (false) + , fallingPos (false) + , fallingNeg (false) { - + setProcessorType (PROCESSOR_TYPE_FILTER); } + PhaseDetector::~PhaseDetector() { - } + AudioProcessorEditor* PhaseDetector::createEditor() { - editor = new PhaseDetectorEditor(this, true); + editor = new PhaseDetectorEditor (this, true); std::cout << "Creating editor." << std::endl; return editor; } + void PhaseDetector::addModule() { DetectorModule m = DetectorModule(); @@ -60,24 +65,22 @@ void PhaseDetector::addModule() m.wasTriggered = false; m.phase = NO_PHASE; - modules.add(m); + modules.add (m); } -void PhaseDetector::setActiveModule(int i) + +void PhaseDetector::setActiveModule (int i) { activeModule = i; - } -void PhaseDetector::setParameter(int parameterIndex, float newValue) +void PhaseDetector::setParameter (int parameterIndex, float newValue) { - - DetectorModule& module = modules.getReference(activeModule); + DetectorModule& module = modules.getReference (activeModule); if (parameterIndex == 1) // module type { - int val = (int) newValue; switch (val) @@ -85,18 +88,23 @@ void PhaseDetector::setParameter(int parameterIndex, float newValue) case 0: module.type = NONE; break; + case 1: module.type = PEAK; break; + case 2: module.type = FALLING_ZERO; break; + case 3: module.type = TROUGH; break; + case 4: module.type = RISING_ZERO; break; + default: module.type = NONE; } @@ -121,20 +129,21 @@ void PhaseDetector::setParameter(int parameterIndex, float newValue) module.isActive = false; } } - } + void PhaseDetector::updateSettings() { - } + bool PhaseDetector::enable() { return true; } -void PhaseDetector::handleEvent(int eventType, MidiMessage& event, int sampleNum) + +void PhaseDetector::handleEvent (int eventType, MidiMessage& event, int sampleNum) { // MOVED GATING TO PULSE PAL OUTPUT! // now use to randomize phase for next trial @@ -146,12 +155,12 @@ void PhaseDetector::handleEvent(int eventType, MidiMessage& event, int sampleNum const uint8* dataptr = event.getRawData(); // int eventNodeId = *(dataptr+1); - int eventId = *(dataptr+2); - int eventChannel = *(dataptr+3); + const int eventId = *(dataptr + 2); + const int eventChannel = *(dataptr + 3); - for (int i = 0; i < modules.size(); i++) + for (int i = 0; i < modules.size(); ++i) { - DetectorModule& module = modules.getReference(i); + DetectorModule& module = modules.getReference (i); if (module.gateChan == eventChannel) { @@ -161,82 +170,77 @@ void PhaseDetector::handleEvent(int eventType, MidiMessage& event, int sampleNum module.isActive = false; } } - } - } -void PhaseDetector::process(AudioSampleBuffer& buffer, - MidiBuffer& events) -{ - checkForEvents(events); +void PhaseDetector::process (AudioSampleBuffer& buffer, MidiBuffer& events) +{ + checkForEvents (events); // loop through the modules - for (int i = 0; i < modules.size(); i++) + for (int i = 0; i < modules.size(); ++i) { - DetectorModule& module = modules.getReference(i); + DetectorModule& module = modules.getReference (i); // check to see if it's active and has a channel - if (module.isActive && module.outputChan >= 0 && - module.inputChan >= 0 && - module.inputChan < buffer.getNumChannels()) + if (module.isActive && module.outputChan >= 0 + && module.inputChan >= 0 + && module.inputChan < buffer.getNumChannels()) { - for (int i = 0; i < getNumSamples(module.inputChan); i++) + for (int i = 0; i < getNumSamples (module.inputChan); ++i) { - const float sample = *buffer.getReadPointer(module.inputChan, i); + const float sample = *buffer.getReadPointer (module.inputChan, i); - if (sample < module.lastSample && sample > 0 && module.phase != FALLING_POS) + if (sample < module.lastSample + && sample > 0 + && module.phase != FALLING_POS) { - if (module.type == PEAK) { - addEvent(events, TTL, i, 1, module.outputChan); + addEvent (events, TTL, i, 1, module.outputChan); module.samplesSinceTrigger = 0; module.wasTriggered = true; } module.phase = FALLING_POS; - } - else if (sample < 0 && module.lastSample >= 0 && module.phase != FALLING_NEG) + else if (sample < 0 + && module.lastSample >= 0 + && module.phase != FALLING_NEG) { - if (module.type == FALLING_ZERO) { - addEvent(events, TTL, i, 1, module.outputChan); + addEvent (events, TTL, i, 1, module.outputChan); module.samplesSinceTrigger = 0; module.wasTriggered = true; } module.phase = FALLING_NEG; - } else if (sample > module.lastSample && sample < 0 && module.phase != RISING_NEG) { - if (module.type == TROUGH) { - addEvent(events, TTL, i, 1, module.outputChan); + addEvent (events, TTL, i, 1, module.outputChan); module.samplesSinceTrigger = 0; module.wasTriggered = true; } module.phase = RISING_NEG; - } - else if (sample > 0 && module.lastSample <= 0 && module.phase != RISING_POS) + else if (sample > 0 + && module.lastSample <= 0 + && module.phase != RISING_POS) { - if (module.type == RISING_ZERO) { - addEvent(events, TTL, i, 1, module.outputChan); + addEvent (events, TTL, i, 1, module.outputChan); module.samplesSinceTrigger = 0; module.wasTriggered = true; } module.phase = RISING_POS; - } module.lastSample = sample; @@ -245,7 +249,7 @@ void PhaseDetector::process(AudioSampleBuffer& buffer, { if (module.samplesSinceTrigger > 1000) { - addEvent(events, TTL, i, 0, module.outputChan); + addEvent (events, TTL, i, 0, module.outputChan); module.wasTriggered = false; } else @@ -253,31 +257,13 @@ void PhaseDetector::process(AudioSampleBuffer& buffer, module.samplesSinceTrigger++; } } - } - - } - } - } + void PhaseDetector::estimateFrequency() { - - // int N = (numPeakIntervals < NUM_INTERVALS) ? numPeakIntervals - // : NUM_INTERVALS; - - // int sum = 0; - - // for (int i = 0; i < N; i++) - // { - // sum += peakIntervals[i]; - // } - - // estimatedFrequency = getSampleRate()/(float(sum)/float(N)); - - } diff --git a/Source/Plugins/PhaseDetector/PhaseDetector.h b/Source/Plugins/PhaseDetector/PhaseDetector.h index 4ce9e8f78..1404c660d 100644 --- a/Source/Plugins/PhaseDetector/PhaseDetector.h +++ b/Source/Plugins/PhaseDetector/PhaseDetector.h @@ -29,40 +29,38 @@ #define NUM_INTERVALS 5 -/** - Uses peaks to estimate the phase of a continuous signal. +/** - @see GenericProcessor, PhaseDetectorEditor + Uses peaks to estimate the phase of a continuous signal. + @see GenericProcessor, PhaseDetectorEditor */ - class PhaseDetector : public GenericProcessor - { public: - PhaseDetector(); ~PhaseDetector(); - void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages); - void setParameter(int parameterIndex, float newValue); + AudioProcessorEditor* createEditor() override; + bool hasEditor() const override { return false; } - AudioProcessorEditor* createEditor(); + void process (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) override; - bool hasEditor() const - { - return false; - } + void setParameter (int parameterIndex, float newValue) override; - bool enable(); + bool enable() override; - void updateSettings(); + void updateSettings() override; void addModule(); - void setActiveModule(int); + void setActiveModule (int); + private: + void handleEvent (int eventType, MidiMessage& event, int sampleNum) override; + + void estimateFrequency(); enum ModuleType { @@ -76,14 +74,16 @@ private: struct DetectorModule { - int inputChan; int gateChan; int outputChan; - bool isActive; - float lastSample; int samplesSinceTrigger; + + float lastSample; + + bool isActive; bool wasTriggered; + ModuleType type; PhaseType phase; }; @@ -92,14 +92,13 @@ private: int activeModule; - void handleEvent(int eventType, MidiMessage& event, int sampleNum); - - bool risingPos, risingNeg, fallingPos, fallingNeg; - - void estimateFrequency(); + bool risingPos; + bool risingNeg; + bool fallingPos; + bool fallingNeg; - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PhaseDetector); + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PhaseDetector); }; #endif // __PHASEDETECTOR_H_F411F29D__ diff --git a/Source/Plugins/PulsePalOutput/PulsePalOutput.cpp b/Source/Plugins/PulsePalOutput/PulsePalOutput.cpp index 2dd836b04..61e005f13 100644 --- a/Source/Plugins/PulsePalOutput/PulsePalOutput.cpp +++ b/Source/Plugins/PulsePalOutput/PulsePalOutput.cpp @@ -2,7 +2,7 @@ ------------------------------------------------------------------ This file is part of the Open Ephys GUI - Copyright (C) 2014 Open Ephys + Copyright (C) 2016 Open Ephys ------------------------------------------------------------------ @@ -18,7 +18,6 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. - */ @@ -28,35 +27,38 @@ PulsePalOutput::PulsePalOutput() - : GenericProcessor("Pulse Pal"), channelToChange(0) + : GenericProcessor ("Pulse Pal") + , channelToChange (0) { + setProcessorType (PROCESSOR_TYPE_SINK); pulsePal.initialize(); - pulsePal.updateDisplay("GUI Connected","Click for menu"); + pulsePal.updateDisplay ("GUI Connected","Click for menu"); - for (int i = 0; i < 4; i++) + for (int i = 0; i < 4; ++i) { - channelTtlTrigger.add(-1); - channelTtlGate.add(-1); - channelState.add(true); + channelTtlTrigger.add (-1); + channelTtlGate.add (-1); + channelState.add (true); } - } + PulsePalOutput::~PulsePalOutput() { - - pulsePal.updateDisplay("PULSE PAL v1.0","Click for menu"); + pulsePal.updateDisplay ("PULSE PAL v1.0","Click for menu"); } + AudioProcessorEditor* PulsePalOutput::createEditor() { - editor = new PulsePalOutputEditor(this, &pulsePal, true); + editor = new PulsePalOutputEditor (this, &pulsePal, true); return editor; } -void PulsePalOutput::handleEvent(int eventType, MidiMessage& event, int sampleNum) + +void PulsePalOutput::handleEvent (int eventType, MidiMessage& event, int sampleNum) { if (eventType == TTL) { @@ -65,32 +67,33 @@ void PulsePalOutput::handleEvent(int eventType, MidiMessage& event, int sampleNu const uint8* dataptr = event.getRawData(); // int eventNodeId = *(dataptr+1); - int eventId = *(dataptr+2); - int eventChannel = *(dataptr+3); + const int eventId = *(dataptr + 2); + const int eventChannel = *(dataptr + 3); - for (int i = 0; i < channelTtlTrigger.size(); i++) + for (int i = 0; i < channelTtlTrigger.size(); ++i) { - if (eventId == 1 && eventChannel == channelTtlTrigger[i] && channelState[i]) + if (eventId == 1 + && eventChannel == channelTtlTrigger[i] + && channelState[i]) { - pulsePal.triggerChannel(i+1); + pulsePal.triggerChannel (i + 1); } if (eventChannel == channelTtlGate[i]) { if (eventId == 1) - channelState.set(i, true); + channelState.set (i, true); else - channelState.set(i, false); + channelState.set (i, false); } } - } - } -void PulsePalOutput::setParameter(int parameterIndex, float newValue) + +void PulsePalOutput::setParameter (int parameterIndex, float newValue) { - editor->updateParameterButtons(parameterIndex); + editor->updateParameterButtons (parameterIndex); //std::cout << "Changing channel " << parameterIndex << " to " << newValue << std::endl; switch (parameterIndex) @@ -98,32 +101,31 @@ void PulsePalOutput::setParameter(int parameterIndex, float newValue) case 0: channelToChange = (int) newValue - 1; break; + case 1: - channelTtlTrigger.set(channelToChange, (int) newValue); + channelTtlTrigger.set (channelToChange, (int) newValue); break; + case 2: - channelTtlGate.set(channelToChange, (int) newValue); + channelTtlGate.set (channelToChange, (int) newValue); if (newValue < 0) { - channelState.set(channelToChange, true); + channelState.set (channelToChange, true); } else { - channelState.set(channelToChange, false); + channelState.set (channelToChange, false); } - break; + default: std::cout << "Unrecognized parameter index." << std::endl; } - } -void PulsePalOutput::process(AudioSampleBuffer& buffer, - MidiBuffer& events) -{ - - checkForEvents(events); +void PulsePalOutput::process (AudioSampleBuffer& buffer, MidiBuffer& events) +{ + checkForEvents (events); } diff --git a/Source/Plugins/PulsePalOutput/PulsePalOutput.h b/Source/Plugins/PulsePalOutput/PulsePalOutput.h index 76c86fb8e..438b61092 100644 --- a/Source/Plugins/PulsePalOutput/PulsePalOutput.h +++ b/Source/Plugins/PulsePalOutput/PulsePalOutput.h @@ -2,7 +2,7 @@ ------------------------------------------------------------------ This file is part of the Open Ephys GUI - Copyright (C) 2014 Open Ephys + Copyright (C) 2016 Open Ephys ------------------------------------------------------------------ @@ -18,7 +18,6 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. - */ #ifndef __PULSEPALOUTPUT_H_A8BF66D6__ @@ -28,37 +27,29 @@ #include "PulsePalOutputEditor.h" #include "serial/PulsePal.h" -/** - - Allows the signal chain to send outputs to the Pulse Pal - from Lucid Biosystems (www.lucidbiosystems.com) - @see GenericProcessor, PulsePalOutputEditor, PulsePal +/** + Allows the signal chain to send outputs to the Pulse Pal + from Lucid Biosystems (www.lucidbiosystems.com) + @see GenericProcessor, PulsePalOutputEditor, PulsePal */ - class PulsePalOutput : public GenericProcessor - { public: - PulsePalOutput(); ~PulsePalOutput(); - void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages); - void setParameter(int parameterIndex, float newValue); + AudioProcessorEditor* createEditor() override; - void handleEvent(int eventType, MidiMessage& event, int sampleNum); + void process (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) override; - AudioProcessorEditor* createEditor(); + void setParameter (int parameterIndex, float newValue) override; - bool isSink() - { - return true; - } + void handleEvent (int eventType, MidiMessage& event, int sampleNum) override; -private: +private: Array<int> channelTtlTrigger; Array<int> channelTtlGate; Array<bool> channelState; @@ -67,10 +58,8 @@ private: PulsePal pulsePal; - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PulsePalOutput); - + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PulsePalOutput); }; - #endif // __PULSEPALOUTPUT_H_A8BF66D6__ diff --git a/Source/Plugins/RecordControl/RecordControl.cpp b/Source/Plugins/RecordControl/RecordControl.cpp index 612435be7..2dd446f4a 100644 --- a/Source/Plugins/RecordControl/RecordControl.cpp +++ b/Source/Plugins/RecordControl/RecordControl.cpp @@ -2,7 +2,7 @@ ------------------------------------------------------------------ This file is part of the Open Ephys GUI - Copyright (C) 2013 Open Ephys + Copyright (C) 2016 Open Ephys ------------------------------------------------------------------ @@ -18,36 +18,38 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. - */ #include <stdio.h> #include "RecordControl.h" + RecordControl::RecordControl() - : GenericProcessor("Record Control"), - triggerChannel(0) + : GenericProcessor ("Record Control") + , triggerChannel (0) { - + setProcessorType (PROCESSOR_TYPE_UTILITY); } + RecordControl::~RecordControl() { - } + AudioProcessorEditor* RecordControl::createEditor() { - editor = new RecordControlEditor(this, true); + editor = new RecordControlEditor (this, true); return editor; } -void RecordControl::setParameter(int parameterIndex, float newValue) + +void RecordControl::setParameter (int parameterIndex, float newValue) { if (parameterIndex == 0) { - updateTriggerChannel((int) newValue); + updateTriggerChannel ((int) newValue); } else if (parameterIndex == 1) { @@ -59,30 +61,31 @@ void RecordControl::setParameter(int parameterIndex, float newValue) } } -void RecordControl::updateTriggerChannel(int newChannel) + +void RecordControl::updateTriggerChannel (int newChannel) { triggerChannel = newChannel; } + bool RecordControl::enable() { - return true; } -void RecordControl::process(AudioSampleBuffer& buffer, - MidiBuffer& events) + +void RecordControl::process (AudioSampleBuffer& buffer, MidiBuffer& events) { - checkForEvents(events); + checkForEvents (events); } -void RecordControl::handleEvent(int eventType, MidiMessage& event, int) +void RecordControl::handleEvent (int eventType, MidiMessage& event, int) { const uint8* dataptr = event.getRawData(); - int eventId = *(dataptr+2); - int eventChannel = *(dataptr+3); + const int eventId = *(dataptr + 2); + const int eventChannel = *(dataptr + 3); //std::cout << "Received event with id=" << eventId << " and ch=" << eventChannel << std::endl; @@ -90,27 +93,24 @@ void RecordControl::handleEvent(int eventType, MidiMessage& event, int) { int edge = triggerEdge == RISING ? 1 : 0; - //std::cout << "Trigger!" << std::endl; - const MessageManagerLock mmLock; if (triggerType == SET) { if (eventId == edge) { - CoreServices::setRecordingStatus(true); + CoreServices::setRecordingStatus (true); } else { - CoreServices::setRecordingStatus(false); + CoreServices::setRecordingStatus (false); } } else if (triggerType == TOGGLE && eventId == edge) { - CoreServices::setRecordingStatus(!CoreServices::getRecordingStatus()); + CoreServices::setRecordingStatus (! CoreServices::getRecordingStatus()); } } - } diff --git a/Source/Plugins/RecordControl/RecordControl.h b/Source/Plugins/RecordControl/RecordControl.h index 75601632b..132d751d2 100644 --- a/Source/Plugins/RecordControl/RecordControl.h +++ b/Source/Plugins/RecordControl/RecordControl.h @@ -2,7 +2,7 @@ ------------------------------------------------------------------ This file is part of the Open Ephys GUI - Copyright (C) 2013 Open Ephys + Copyright (C) 2016 Open Ephys ------------------------------------------------------------------ @@ -18,7 +18,6 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. - */ #ifndef __RECORDCONTROL_H_120DD434__ @@ -27,43 +26,40 @@ #include <ProcessorHeaders.h> #include "RecordControlEditor.h" -/** - - Stops and stops recording in response to incoming events. - @see RecordNode +/** + Stops and stops recording in response to incoming events. + @see RecordNode */ - class RecordControl : public GenericProcessor { public: RecordControl(); ~RecordControl(); - void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages); - void setParameter(int, float); - void updateTriggerChannel(int newChannel); - void handleEvent(int eventType, MidiMessage& event, int); + AudioProcessorEditor* createEditor() override; - bool enable(); + void process (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) override; - bool isUtility() - { - return true; - } + void setParameter (int parameterIndex, float newValue) override; + void handleEvent (int eventType, MidiMessage& event, int) override; + + bool enable() override; + + void updateTriggerChannel (int newChannel); - AudioProcessorEditor* createEditor(); private: int triggerChannel; + enum Edges { RISING = 0, FALLING = 1 }; - enum Types {SET = 0, TOGGLE = 1}; + enum Types { SET = 0, TOGGLE = 1}; + Edges triggerEdge; Types triggerType; - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(RecordControl); - + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RecordControl); }; #endif diff --git a/Source/Plugins/Rectifier/Rectifier.cpp b/Source/Plugins/Rectifier/Rectifier.cpp index db3491227..638a22d44 100644 --- a/Source/Plugins/Rectifier/Rectifier.cpp +++ b/Source/Plugins/Rectifier/Rectifier.cpp @@ -1,74 +1,69 @@ - /* - ------------------------------------------------------------------ - - This file is part of the Open Ephys GUI - Copyright (C) 2014 Open Ephys - - ------------------------------------------------------------------ - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - - */ + ------------------------------------------------------------------ + + This file is part of the Open Ephys GUI + Copyright (C) 2016 Open Ephys + + ------------------------------------------------------------------ + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +*/ #include <stdio.h> #include "Rectifier.h" -Rectifier::Rectifier() -: GenericProcessor("Rectifier") +Rectifier::Rectifier() + : GenericProcessor ("Rectifier") { + setProcessorType (PROCESSOR_TYPE_FILTER); + // It would be nice to have the option to do -abs for negative events (e.g. sharp waves) //parameters.add(Parameter("Sign", -1.0, 1.0, 1.0, -1.0)); - } + Rectifier::~Rectifier() { - } - -void Rectifier::setParameter(int parameterIndex, float newValue) +void Rectifier::setParameter (int parameterIndex, float newValue) { - editor->updateParameterButtons(parameterIndex); - // std::cout << "Setting Rectifier" << std::endl; - + editor->updateParameterButtons (parameterIndex); + if (currentChannel >= 0) { - Parameter& p = parameters.getReference(parameterIndex); - p.setValue(newValue, currentChannel); + Parameter& p = parameters.getReference (parameterIndex); + p.setValue (newValue, currentChannel); } } -void Rectifier::process(AudioSampleBuffer& buffer, - MidiBuffer& events) + +void Rectifier::process (AudioSampleBuffer& buffer, MidiBuffer& events) { - int nChannels = buffer.getNumChannels(); - - for (int ch = 0; ch < nChannels ; ch++) + const int nChannels = buffer.getNumChannels(); + + for (int ch = 0; ch < nChannels ; ++ch) { - int nSamples = buffer.getNumSamples(); - float* bufPtr = buffer.getWritePointer(ch); - for (int n = 0; n < nSamples; n++) + const int nSamples = buffer.getNumSamples(); + float* bufPtr = buffer.getWritePointer (ch); + for (int n = 0; n < nSamples; ++n) { - *(bufPtr + n) = fabsf(*(bufPtr + n)); + *(bufPtr + n) = fabsf (*(bufPtr + n)); } } - } diff --git a/Source/Plugins/Rectifier/Rectifier.h b/Source/Plugins/Rectifier/Rectifier.h index e8a65f0d2..ab50c2241 100644 --- a/Source/Plugins/Rectifier/Rectifier.h +++ b/Source/Plugins/Rectifier/Rectifier.h @@ -1,91 +1,71 @@ /* - ------------------------------------------------------------------ - - This file is part of the Open Ephys GUI - Copyright (C) 2014 Open Ephys - - ------------------------------------------------------------------ - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - - */ + ------------------------------------------------------------------ + + This file is part of the Open Ephys GUI + Copyright (C) 2016 Open Ephys + + ------------------------------------------------------------------ + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +*/ #ifndef RECTIFIER_H_INCLUDED #define RECTIFIER_H_INCLUDED #ifdef _WIN32 -#include <Windows.h> + #include <Windows.h> #endif #include <ProcessorHeaders.h> -/** - - A simple rectifier - - */ +/** A simple rectifier */ class Rectifier : public GenericProcessor - { public: - /** The class constructor, used to initialize any members. */ Rectifier(); - + /** The class destructor, used to deallocate memory */ ~Rectifier(); - - /** Determines whether the processor is treated as a source. */ - bool isSource() - { - return false; - } - - /** Determines whether the processor is treated as a sink. */ - bool isSink() - { - return false; - } - + /** Defines the functionality of the processor. - + The process method is called every time a new data buffer is available. - + Processors can either use this method to add new data, manipulate existing data, or send data to an external target (such as a display or other hardware). - + Continuous signals arrive in the "buffer" variable, event data (such as TTLs and spikes) is contained in the "events" variable, and "nSamples" holds the number of continous samples in the current buffer (which may differ from the size of the buffer). */ - void process(AudioSampleBuffer& buffer, MidiBuffer& events); - + void process (AudioSampleBuffer& buffer, MidiBuffer& events) override; + /** Any variables used by the "process" function _must_ be modified only through this method while data acquisition is active. If they are modified in any other way, the application will crash. */ - void setParameter(int parameterIndex, float newValue); - + void setParameter (int parameterIndex, float newValue) override; + + private: - - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Rectifier); - + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Rectifier); }; - #endif // RECTIFIER_H_INCLUDED diff --git a/Source/Plugins/SerialInput/SerialInput.cpp b/Source/Plugins/SerialInput/SerialInput.cpp index d35d9704f..f1dc7d227 100644 --- a/Source/Plugins/SerialInput/SerialInput.cpp +++ b/Source/Plugins/SerialInput/SerialInput.cpp @@ -1,68 +1,89 @@ /* - ------------------------------------------------------------------ + ------------------------------------------------------------------ - This file is part of the Open Ephys GUI - Copyright (C) 2014 Florian Franzen + This file is part of the Open Ephys GUI + Copyright (C) 2016 Florian Franzen - ------------------------------------------------------------------ + ------------------------------------------------------------------ - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. - */ +*/ #include <stdio.h> #include "SerialInput.h" -const int SerialInput::BAUDRATES[12] = {300, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, 115200, 230400}; +const int SerialInput::BAUDRATES[12] = +{ + 300 + , 1200 + , 2400 + , 4800 + , 9600 + , 14400 + , 19200 + , 28800 + , 38400 + , 57600 + , 115200 + , 230400 +}; + SerialInput::SerialInput() - : GenericProcessor("Serial Port"), baudrate(0) + : GenericProcessor ("Serial Port") + , baudrate (0) { + setProcessorType (PROCESSOR_TYPE_SOURCE); } + SerialInput::~SerialInput() { serial.close(); } + StringArray SerialInput::getDevices() { vector<ofSerialDeviceInfo> allDeviceInfos = serial.getDeviceList(); StringArray allDevices; - for (int i = 0; i < allDeviceInfos.size(); i++) + for (int i = 0; i < allDeviceInfos.size(); ++i) { - allDevices.add(allDeviceInfos[i].getDeviceName()); + allDevices.add (allDeviceInfos[i].getDeviceName()); } return allDevices; } -Array<int> SerialInput::getBaudrates() + +Array<int> SerialInput::getBaudrates() const { - Array<int> allBaudrates(BAUDRATES, 12); + Array<int> allBaudrates (BAUDRATES, 12); return allBaudrates; } -void SerialInput::setDevice(string device) + +void SerialInput::setDevice (string device) { this->device = device; } -void SerialInput::setBaudrate(int baudrate) +void SerialInput::setBaudrate (int baudrate) { this->baudrate = baudrate; } @@ -72,17 +93,18 @@ bool SerialInput::isReady() { if (device == "" || baudrate == 0) { - AlertWindow::showMessageBoxAsync(AlertWindow::WarningIcon, "SerialInput connection error!", "Please set device and baudrate to use first!"); + AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, "SerialInput connection error!", "Please set device and baudrate to use first!"); return false; } - if (!serial.setup(device, baudrate)) + if (! serial.setup (device, baudrate)) { - AlertWindow::showMessageBoxAsync(AlertWindow::WarningIcon, "SerialInput connection error!", "Could not connect to specified serial device. Check log files for details."); + AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, "SerialInput connection error!", "Could not connect to specified serial device. Check log files for details."); return false; } return true; } + bool SerialInput::disable() { serial.close(); @@ -90,44 +112,44 @@ bool SerialInput::disable() } -void SerialInput::process(AudioSampleBuffer&, MidiBuffer& events) +void SerialInput::process (AudioSampleBuffer&, MidiBuffer& events) { int bytesAvailable = serial.available(); if (bytesAvailable == OF_SERIAL_ERROR) { // ToDo: Properly warn about problem here! - AlertWindow::showMessageBoxAsync(AlertWindow::WarningIcon, "SerialInput device access error!", "Could not access serial device."); + AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, "SerialInput device access error!", "Could not access serial device."); return; } if (bytesAvailable > 0) { - unsigned char buffer[10000]; - int bytesRead = serial.readBytes(buffer, bytesAvailable); + int bytesRead = serial.readBytes (buffer, bytesAvailable); if (bytesRead > 0) { - addEvent(events, // MidiBuffer - BINARY_MSG, // eventType - 0, // sampleNum - nodeId, // eventID - 0, // eventChannel - bytesRead, // numBytes - buffer); // data + addEvent (events, // MidiBuffer + BINARY_MSG, // eventType + 0, // sampleNum + nodeId, // eventID + 0, // eventChannel + bytesRead, // numBytes + buffer); // data } else if (bytesRead < 0) { // ToDo: Properly warn about problem here! - AlertWindow::showMessageBoxAsync(AlertWindow::WarningIcon, "SerialInput device read error!", "Could not read serial input, even though data should be available."); + AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, "SerialInput device read error!", "Could not read serial input, even though data should be available."); return; } } } + AudioProcessorEditor* SerialInput::createEditor() { - editor = new SerialInputEditor(this); + editor = new SerialInputEditor (this); return editor; } diff --git a/Source/Plugins/SerialInput/SerialInput.h b/Source/Plugins/SerialInput/SerialInput.h index bf85702b5..b9333bc86 100644 --- a/Source/Plugins/SerialInput/SerialInput.h +++ b/Source/Plugins/SerialInput/SerialInput.h @@ -1,31 +1,31 @@ /* - ------------------------------------------------------------------ + ------------------------------------------------------------------ - This file is part of the Open Ephys GUI - Copyright (C) 2014 Florian Franzen + This file is part of the Open Ephys GUI + Copyright (C) 2016 Florian Franzen - ------------------------------------------------------------------ + ------------------------------------------------------------------ - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. - */ +*/ #ifndef __SERIALINPUT_H_B8E3F86B__ #define __SERIALINPUT_H_B8E3F86B__ #ifdef _WIN32 -#include <Windows.h> + #include <Windows.h> #endif #include <ProcessorHeaders.h> @@ -33,84 +33,65 @@ #include "SerialInputEditor.h" #include <SerialLib.h> -/** - - This source processor allows you to pipe binary serial data input straight to the event cue/buffer. - @see SerialInputEditor - - */ +/** + This source processor allows you to pipe binary serial data input straight to the event cue/buffer. + @see SerialInputEditor +*/ class SerialInput : public GenericProcessor - { public: - /** The class constructor, used to initialize any members. */ SerialInput(); /** The class destructor, used to deallocate memory */ virtual ~SerialInput(); - /** - Returns a list of all serial devices that are available on the system. - - The list of available devices changes whenever devices are connected or removed. - */ - StringArray getDevices(); + AudioProcessorEditor* createEditor(); - /** - Returns a list of all supported baudrates. - */ - Array<int> getBaudrates(); + /** Defines the functionality of the processor. - /** - Used by the ProcessorGraph to determines whether the processor should be treated as a source. + The process method is called every time a new data buffer is available. - Returns always true, since SerialInput is a source. + Adds all the new serial data that is available to the event data buffer. */ - bool isSource() - { - return true; - } + void process (AudioSampleBuffer& buffer, MidiBuffer& events) override; /** - This should only be run by the ProcessorGraph, before acquisition will be started. + This should only be run by the ProcessorGraph, before acquisition will be started. - It tries to open the serial port previsouly specified by the setDevice and setBaudrate setters. + It tries to open the serial port previsouly specified by the setDevice and setBaudrate setters. - Returns true on success, false if port could not be opened. - */ - bool isReady(); + Returns true on success, false if port could not be opened. + */ + bool isReady() override; /** - Called immediately after the end of data acquisition by the ProcessorGraph. + Called immediately after the end of data acquisition by the ProcessorGraph. - It closes the open port serial port. + It closes the open port serial port. */ - bool disable(); + bool disable() override; - /** Setter, that allows you to set the serial device that will be used during acquisition */ - void setDevice(string device); + /** + Returns a list of all serial devices that are available on the system. - /** Setter, that allows you to set the baudrate that will be used during acquisition */ - void setBaudrate(int baudrate); + The list of available devices changes whenever devices are connected or removed. + */ + StringArray getDevices(); - /** Defines the functionality of the processor. + /** Returns a list of all supported baudrates. */ + Array<int> getBaudrates() const; - The process method is called every time a new data buffer is available. + /** Setter, that allows you to set the serial device that will be used during acquisition */ + void setDevice (string device); - Adds all the new serial data that is available to the event data buffer. - */ - void process(AudioSampleBuffer& buffer, MidiBuffer& events); + /** Setter, that allows you to set the baudrate that will be used during acquisition */ + void setBaudrate (int baudrate); - /** - Returns the Juce GUI component that should be used with this processor. - */ - AudioProcessorEditor* createEditor(); private: - // The current serial connection ofSerial serial; @@ -123,7 +104,7 @@ private: // List of baudrates that are available by default. static const int BAUDRATES[12]; - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SerialInput); + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SerialInput); }; #endif // __SERIALINPUT_H_B8E3F86B__ diff --git a/Source/Plugins/SignalGenerator/SignalGenerator.cpp b/Source/Plugins/SignalGenerator/SignalGenerator.cpp index b75d13534..b39987d92 100644 --- a/Source/Plugins/SignalGenerator/SignalGenerator.cpp +++ b/Source/Plugins/SignalGenerator/SignalGenerator.cpp @@ -2,7 +2,7 @@ ------------------------------------------------------------------ This file is part of the Open Ephys GUI - Copyright (C) 2013 Open Ephys + Copyright (C) 2016 Open Ephys ------------------------------------------------------------------ @@ -28,26 +28,29 @@ #include "../Visualization/SpikeObject.h" #ifdef WIN32 -#define copysign(x,y) _copysign(x,y) + #define copysign(x,y) _copysign(x,y) #endif SignalGenerator::SignalGenerator() - : GenericProcessor("Signal Generator"), - nOut(5), defaultFrequency(10.0), defaultAmplitude(0.5f), - previousPhase(1000), spikeDelay(0) + : GenericProcessor ("Signal Generator") + , nOut (5) + , defaultFrequency (10.0) + , defaultAmplitude (0.5f) + , previousPhase (1000) + , spikeDelay (0) { - parameters.add(Parameter("Amplitude", 0.0005f, 500.0f, .5f, 0, true)); - parameters.add(Parameter("Frequency", 0.01, 10000.0, 10, 1, true)); - parameters.add(Parameter("Phase", -double_Pi, double_Pi, 0, 2, true)); - parameters.add(Parameter("Waveform Type", waveformParameter, 0, 3, true)); + parameters.add (Parameter ("Amplitude", 0.0005f, 500.0f, .5f, 0, true)); + parameters.add (Parameter ("Frequency", 0.01, 10000.0, 10, 1, true)); + parameters.add (Parameter ("Phase", -double_Pi, double_Pi, 0, 2, true)); + parameters.add (Parameter ("Waveform Type", waveformParameter, 0, 3, true)); } SignalGenerator::~SignalGenerator() { - } + /*void SignalGenerator::initializeParameters(){ parameters.add(Parameter("Amplitude", 0.0005f, 500.0f, .5f, 1, true)); parameters.add(Parameter("Frequency", 0.01, 10000.0, 10, 2, true)); @@ -56,79 +59,79 @@ SignalGenerator::~SignalGenerator() } */ + AudioProcessorEditor* SignalGenerator::createEditor() { - editor = new SignalGeneratorEditor(this, false); + editor = new SignalGeneratorEditor (this, false); return editor; } + void SignalGenerator::updateSettings() { - //std::cout << "Signal generator updating parameters" << std::endl; while (waveformType.size() < getNumOutputs()) { - waveformType.add(SINE); - frequency.add(defaultFrequency); - amplitude.add(defaultAmplitude); - phase.add(0); - phasePerSample.add(double_Pi * 2.0 / (getSampleRate() / frequency.getLast())); - currentPhase.add(0); + waveformType.add (SINE); + frequency.add (defaultFrequency); + amplitude.add (defaultAmplitude); + phase.add (0); + phasePerSample.add (double_Pi * 2.0 / (getSampleRate() / frequency.getLast())); + currentPhase.add (0); } sampleRateRatio = getSampleRate() / 44100.0; std::cout << "Sample rate ratio: " << sampleRateRatio << std::endl; - } -void SignalGenerator::setParameter(int parameterIndex, float newValue) + +void SignalGenerator::setParameter (int parameterIndex, float newValue) { - editor->updateParameterButtons(parameterIndex); + editor->updateParameterButtons (parameterIndex); + std::cout << "Message received." << std::endl; + Parameter* parameterPointer=parameters.getRawDataPointer(); - parameterPointer=parameterPointer+parameterIndex; - editor->updateParameterButtons(parameterIndex); + parameterPointer += parameterIndex; + editor->updateParameterButtons (parameterIndex); if (currentChannel > -1) { if (parameterIndex == 0) { - amplitude.set(currentChannel,newValue*100.0f); - parameterPointer->setValue(newValue*100.0f, currentChannel); + amplitude.set (currentChannel,newValue * 100.0f); + parameterPointer->setValue (newValue * 100.0f, currentChannel); } else if (parameterIndex == 1) { - frequency.set(currentChannel,newValue); - phasePerSample.set(currentChannel, double_Pi * 2.0 / (getSampleRate() / frequency[currentChannel])); - parameterPointer->setValue(newValue, currentChannel); + frequency.set (currentChannel,newValue); + phasePerSample.set (currentChannel, double_Pi * 2.0 / (getSampleRate() / frequency[currentChannel])); + parameterPointer->setValue (newValue, currentChannel); } else if (parameterIndex == 2) { - phase.set(currentChannel, newValue/360.0f * (double_Pi * 2.0)); - parameterPointer->setValue(newValue/360.0f * (double_Pi * 2.0), currentChannel); + phase.set (currentChannel, newValue / 360.0f * (double_Pi * 2.0)); + parameterPointer->setValue (newValue / 360.0f * (double_Pi * 2.0), currentChannel); } else if (parameterIndex == 3) { - waveformType.set(currentChannel, (int) newValue); - parameterPointer->setValue(newValue, currentChannel); + waveformType.set (currentChannel, (int) newValue); + parameterPointer->setValue (newValue, currentChannel); } //updateWaveform(currentChannel); } - } bool SignalGenerator::enable() { - std::cout << "Signal generator received enable signal." << std::endl; // for (int n = 0; n < waveformType.size(); n++) // { // updateWaveform(n); - // } return true; @@ -177,163 +180,103 @@ bool SignalGenerator::enable() bool SignalGenerator::disable() { - std::cout << "Signal generator received disable signal." << std::endl; return true; } -void SignalGenerator::process(AudioSampleBuffer& buffer, - MidiBuffer& midiMessages) +void SignalGenerator::process (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) { - - int nSamps = int((float) buffer.getNumSamples() * sampleRateRatio); + int nSamps = int ((float) buffer.getNumSamples() * sampleRateRatio); for (int i = 0; i < nSamps; ++i) { for (int j = buffer.getNumChannels(); --j >= 0;) { - float sample; switch (waveformType[j]) { case SINE: - sample = amplitude[j] * (float) std::sin(currentPhase[j] + phase[j]); + sample = amplitude[j] * (float) std::sin (currentPhase[j] + phase[j]); break; + case SQUARE: - sample = amplitude[j] * copysign(1,std::sin(currentPhase[j] + phase[j])); + sample = amplitude[j] * copysign (1, std::sin (currentPhase[j] + phase[j])); break; + case TRIANGLE: - sample = amplitude[j] * ((currentPhase[j] + phase[j]) / double_Pi - 1) * - copysign(2,std::sin(currentPhase[j] + phase[j])); + sample = amplitude[j] * ((currentPhase[j] + phase[j]) / double_Pi - 1) + * copysign (2,std::sin (currentPhase[j] + phase[j])); break; + case SAW: sample = amplitude[j] * ((currentPhase[j] + phase[j]) / double_Pi - 1); break; + case NOISE: // sample = amplitude[j] * (float(rand()) / float(RAND_MAX)-0.5f); - // break; + sample = 0 + break; + case SPIKE: - sample = generateSpikeSample(amplitude[j], currentPhase[j], phase[j]); + sample = generateSpikeSample (amplitude[j], currentPhase[j], phase[j]); break; + default: sample = 0; } - currentPhase.set(j,currentPhase[j] + phasePerSample[j]); + currentPhase.set (j,currentPhase[j] + phasePerSample[j]); - if (currentPhase[j] > double_Pi*2) - currentPhase.set(j,0); + if (currentPhase[j] > double_Pi * 2) + currentPhase.set (j, 0); // dereference pointer to one of the buffer's samples - *buffer.getWritePointer(j, i) = sample; + *buffer.getWritePointer (j, i) = sample; } } +} - // for (int chan = 0; chan < buffer.getNumChannels(); chan++) - // { - - // int dataSize = waveforms[chan].size(); - // int destSample = -dataSize; - // int lastSample = dataSize; - - // while (lastSample < nSamps) - // { - - // destSample += dataSize; - - // //std::cout << lastSample << " " << destSample << " " << currentSample[chan] << " " << dataSize << std::endl; - - // // buffer.copyFrom(chan, - // // destSample, - // // waveforms[chan].getRawDataPointer() + currentSample[chan], - // // dataSize - currentSample[chan]); - - // lastSample += dataSize; - - // currentSample.set(chan,0); - - // //std::cout << "DONE" << std::endl; - // } - - // //std::cout << lastSample << " " << destSample << " " << currentSample[chan] << " " << dataSize << std::endl; - - // if (destSample < 0) - // destSample = 0; - - // int samplesLeft = nSamps - destSample; - - // if (samplesLeft < dataSize - currentSample[chan]) - // { - // // buffer.copyFrom(chan, - // // destSample, - // // waveforms[chan].getRawDataPointer() + currentSample[chan], - // // samplesLeft); - - // currentSample.set(chan, currentSample[chan] + samplesLeft); - - // } else { - - // int samps = dataSize - currentSample[chan]; - - // // buffer.copyFrom(chan, - // // destSample, - // // waveforms[chan].getRawDataPointer() + currentSample[chan], - // // samps); - - // destSample += samps; - // samplesLeft -= samps; - - // // buffer.copyFrom(chan, - // // destSample, - // // waveforms[chan].getRawDataPointer(), - // // samplesLeft); - - // currentSample.set(chan, samplesLeft); - // } - - // } - -} float SignalGenerator::generateSpikeSample(double amp, double phase, double noise) { - - // if the current phase is less than the previous phase we've probably wrapped and its time to select a new spike // if we've delayed long enough then draw a new spike otherwise wait until spikeDelay==0 if (phase < previousPhase) { - spikeIdx = rand()%5; + spikeIdx = rand() % 5; if (spikeDelay <= 0) - spikeDelay = rand()%200 + 50; + spikeDelay = rand() % 200 + 50; if (spikeDelay > 0) - spikeDelay --; + --spikeDelay; } - previousPhase = phase; - int shift = -9500;//1000 + 32768; - int gain = 8000; + const int shift = -9500;//1000 + 32768; + const int gain = 8000; - double r = ((rand() % 201) - 100) / 1000.0; // Generate random number between -.1 and .1 - noise = r * noise / (double_Pi * 2); // Shrink the range of r based upon the value of noise + // Generate random number between -.1 and .1 + const double r = ((rand() % 201) - 100) / 1000.0; + // Shrink the range of r based upon the value of noise + noise = r * noise / (double_Pi * 2); - int sampIdx = (int)(phase / (2 * double_Pi) * (N_WAVEFORM_SAMPLES-1)); // bind between 0 and N_SAMP-1, too tired to figure out the proper math + // bind between 0 and N_SAMP-1, too tired to figure out the proper math + const int sampIdx = (int)(phase / (2 * double_Pi) * (N_WAVEFORM_SAMPLES-1)); //sampIdx = sampIdx + 8; - // Right now only sample from the 3rd waveform. I need to figure out a way to only sample from a single spike until the phase wraps - float baseline = shift + gain * SPIKE_WAVEFORMS[spikeIdx][1] ; + // Right now only sample from the 3rd waveform. + // I need to figure out a way to only sample from a single spike until the phase wraps + const float baseline = shift + gain * SPIKE_WAVEFORMS[spikeIdx][1] ; - float sample = shift + gain * (SPIKE_WAVEFORMS[spikeIdx][sampIdx] + noise); // * pow( WAVEFORM_SCALE[sampIdx], amp / 200.0 ) ) ; - float dV = sample - baseline; + const float sample = shift + gain * (SPIKE_WAVEFORMS[spikeIdx][sampIdx] + noise); // * pow( WAVEFORM_SCALE[sampIdx], amp / 200.0 ) ) ; + const float dV = sample - baseline; dV = dV * (1 + amp / 250); sample = baseline + dV; - if (spikeDelay==0) + if (spikeDelay == 0) return sample; else return baseline; diff --git a/Source/Plugins/SignalGenerator/SignalGenerator.h b/Source/Plugins/SignalGenerator/SignalGenerator.h index 3ec69656c..dbf3102d7 100644 --- a/Source/Plugins/SignalGenerator/SignalGenerator.h +++ b/Source/Plugins/SignalGenerator/SignalGenerator.h @@ -2,7 +2,7 @@ ------------------------------------------------------------------ This file is part of the Open Ephys GUI - Copyright (C) 2013 Open Ephys + Copyright (C) 2016 Open Ephys ------------------------------------------------------------------ @@ -29,71 +29,49 @@ #include "../GenericProcessor/GenericProcessor.h" #include "SignalGeneratorEditor.h" -/** +/** Outputs synthesized data of one of 5 different waveform types. @see GenericProcessor, SignalGeneratorEditor - */ - class SignalGenerator : public GenericProcessor - { public: - SignalGenerator(); ~SignalGenerator(); - void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages); + void process (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) override; - void setParameter(int parameterIndex, float newValue); + void setParameter (int parameterIndex, float newValue) override; - float getSampleRate() - { - return 44100.0; - } + float getSampleRate() const override { return 44100.0; } + float getDefaultBitVolts() const override { return 0.03; } - float getDefaultBitVolts() - { - return 0.03; - } + bool hasEditor() const override { return true; } - AudioProcessorEditor* createEditor(); - bool hasEditor() const - { - return true; - } + AudioProcessorEditor* createEditor() override; - bool enable(); - bool disable(); + bool enable() override; + bool disable() override; - bool isSource() - { - return true; - } - - void updateSettings(); + void updateSettings() override; - int getDefaultNumOutputs() - { - return nOut; - } + int getDefaultNumOutputs() { return nOut; } int nOut; private: + float generateSpikeSample (double amp, double phase, double noise); double defaultFrequency; double defaultAmplitude; - float generateSpikeSample(double amp, double phase, double noise); - float sampleRateRatio; //void updateWaveform(int chan); - + // void initializeParameters(); enum wvfrm @@ -113,12 +91,9 @@ private: int spikeIdx; int spikeDelay; - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SignalGenerator); - + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SignalGenerator); }; - - #endif // __SIGNALGENERATOR_H_EAA44B0B__ diff --git a/Source/Plugins/SpikeSorter/SpikeSorter.cpp b/Source/Plugins/SpikeSorter/SpikeSorter.cpp index d437744ab..140ce236e 100644 --- a/Source/Plugins/SpikeSorter/SpikeSorter.cpp +++ b/Source/Plugins/SpikeSorter/SpikeSorter.cpp @@ -34,6 +34,8 @@ SpikeSorter::SpikeSorter() overflowBufferSize(100), currentElectrode(-1), numPreSamples(8),numPostSamples(32) { + setProcessorType (PROCESSOR_TYPE_FILTER); + uniqueID = 0; // for electrode count uniqueSpikeID = 0; juce::Time timer; diff --git a/Source/Processors/FileReader/FileReader.cpp b/Source/Processors/FileReader/FileReader.cpp index dc3c06b2a..7a07ff86f 100644 --- a/Source/Processors/FileReader/FileReader.cpp +++ b/Source/Processors/FileReader/FileReader.cpp @@ -2,7 +2,7 @@ ------------------------------------------------------------------ This file is part of the Open Ephys GUI - Copyright (C) 2013 Open Ephys + Copyright (C) 2016 Open Ephys ------------------------------------------------------------------ @@ -39,6 +39,8 @@ FileReader::FileReader() , stopSample (0) , counter (0) { + setProcessorType (PROCESSOR_TYPE_SOURCE); + setEnabledState (false); const int numFileSources = AccessClass::getPluginManager()->getNumFileSources(); @@ -71,7 +73,7 @@ AudioProcessorEditor* FileReader::createEditor() } -bool FileReader::isReady() const +bool FileReader::isReady() { if (! input) { diff --git a/Source/Processors/FileReader/FileReader.h b/Source/Processors/FileReader/FileReader.h index 385cd5315..a6976278b 100644 --- a/Source/Processors/FileReader/FileReader.h +++ b/Source/Processors/FileReader/FileReader.h @@ -2,7 +2,7 @@ ------------------------------------------------------------------ This file is part of the Open Ephys GUI - Copyright (C) 2013 Open Ephys + Copyright (C) 2016 Open Ephys ------------------------------------------------------------------ @@ -51,9 +51,8 @@ public: AudioProcessorEditor* createEditor() override; bool hasEditor() const override { return true; } - bool isSource() const override { return true; } bool isGeneratesTimestamps() const override { return true; } - bool isReady() const override; + bool isReady() override; int getNumHeadstageOutputs() const override; int getNumEventChannels() const override; diff --git a/Source/Processors/GenericProcessor/GenericProcessor.cpp b/Source/Processors/GenericProcessor/GenericProcessor.cpp index 774fd913d..743808275 100755 --- a/Source/Processors/GenericProcessor/GenericProcessor.cpp +++ b/Source/Processors/GenericProcessor/GenericProcessor.cpp @@ -1011,7 +1011,7 @@ bool GenericProcessor::isMetaParameter (int parameterIndex) const { ret bool GenericProcessor::canSendSignalTo (GenericProcessor*) const { return true; } -bool GenericProcessor::isReady() const { return isEnabled; } +bool GenericProcessor::isReady() { return isEnabled; } bool GenericProcessor::isEnabledState() const { return isEnabled; } bool GenericProcessor::isGeneratesTimestamps() const { return false; } diff --git a/Source/Processors/GenericProcessor/GenericProcessor.h b/Source/Processors/GenericProcessor/GenericProcessor.h index 038e0662a..d6603981a 100755 --- a/Source/Processors/GenericProcessor/GenericProcessor.h +++ b/Source/Processors/GenericProcessor/GenericProcessor.h @@ -335,7 +335,7 @@ public: virtual bool canSendSignalTo (GenericProcessor*) const; /** Returns true if a processor is ready to process data (e.g., all of its parameters are initialized, and its data source is connected).*/ - virtual bool isReady() const; + virtual bool isReady(); /** Called immediately prior to the start of data acquisition, once all processors in the signal chain have indicated they are ready to process data.*/ virtual bool enable(); diff --git a/Source/Processors/PlaceholderProcessor/PlaceholderProcessor.cpp b/Source/Processors/PlaceholderProcessor/PlaceholderProcessor.cpp index 5215dd4ee..8b995d60b 100644 --- a/Source/Processors/PlaceholderProcessor/PlaceholderProcessor.cpp +++ b/Source/Processors/PlaceholderProcessor/PlaceholderProcessor.cpp @@ -71,7 +71,7 @@ bool PlaceholderProcessor::isSink() const } -bool PlaceholderProcessor::isReady() const +bool PlaceholderProcessor::isReady() { CoreServices::sendStatusMessage ("Cannot acquire with placeholder nodes"); return false; //This processor never allows processing diff --git a/Source/Processors/PlaceholderProcessor/PlaceholderProcessor.h b/Source/Processors/PlaceholderProcessor/PlaceholderProcessor.h index 6bb60809b..70e365b2f 100644 --- a/Source/Processors/PlaceholderProcessor/PlaceholderProcessor.h +++ b/Source/Processors/PlaceholderProcessor/PlaceholderProcessor.h @@ -34,13 +34,13 @@ public: PlaceholderProcessor (String pName, String lName, int lVer, bool pSource, bool pSink); ~PlaceholderProcessor(); + AudioProcessorEditor* createEditor() override; + bool hasEditor() const override; bool isSource() const override; bool isSink() const override; - bool isReady() const override; - - AudioProcessorEditor* createEditor() override; + bool isReady() override; void process (AudioSampleBuffer& continuousBuffer, MidiBuffer& eventBuffer) override; diff --git a/Source/Processors/SourceNode/SourceNode.cpp b/Source/Processors/SourceNode/SourceNode.cpp index 359c60bf0..25911415d 100755 --- a/Source/Processors/SourceNode/SourceNode.cpp +++ b/Source/Processors/SourceNode/SourceNode.cpp @@ -2,7 +2,7 @@ ------------------------------------------------------------------ This file is part of the Open Ephys GUI - Copyright (C) 2014 Open Ephys + Copyright (C) 2016 Open Ephys ------------------------------------------------------------------ @@ -28,102 +28,96 @@ #include "../../AccessClass.h" #include "../PluginManager/OpenEphysPlugin.h" -SourceNode::SourceNode(const String& name_, DataThreadCreator dt) - : GenericProcessor(name_), - sourceCheckInterval(2000), wasDisabled(true), dataThread(nullptr), - inputBuffer(0), ttlState(0) + +SourceNode::SourceNode (const String& name_, DataThreadCreator dt) + : GenericProcessor (name_) + , sourceCheckInterval (2000) + , wasDisabled (true) + , dataThread (nullptr) + , inputBuffer (0) + , ttlState (0) { - dataThread = dt(this); + setProcessorType (PROCESSOR_TYPE_SOURCE); + + dataThread = dt (this); if (dataThread != nullptr) { - if (!dataThread->foundInputSource()) + if (! dataThread->foundInputSource()) { - enabledState(false); + setEnabledState (false); } numEventChannels = dataThread->getNumEventChannels(); //eventChannelState = new int[numEventChannels]; - eventChannelState.malloc(numEventChannels); - for (int i = 0; i < numEventChannels; i++) + eventChannelState.malloc (numEventChannels); + for (int i = 0; i < numEventChannels; ++i) { eventChannelState[i] = 0; } - } else { - enabledState(false); - // eventChannelState = 0; + setEnabledState (false); + // eventChannelState = 0; numEventChannels = 0; } // check for input source every few seconds - startTimer(sourceCheckInterval); + startTimer (sourceCheckInterval); timestamp = 0; //eventCodeBuffer = new uint64[10000]; //10000 samples per buffer max? - eventCodeBuffer.malloc(10000); - - + eventCodeBuffer.malloc (10000); } + SourceNode::~SourceNode() { - if (dataThread->isThreadRunning()) { std::cout << "Forcing thread to stop." << std::endl; - dataThread->stopThread(500); + dataThread->stopThread (500); } - - - //if (eventChannelState) - // delete[] eventChannelState; } -DataThread* SourceNode::getThread() -{ - return dataThread; -} void SourceNode::requestChainUpdate() { - CoreServices::updateSignalChain(getEditor()); + CoreServices::updateSignalChain (getEditor()); } -void SourceNode::getEventChannelNames(StringArray& names) + +void SourceNode::getEventChannelNames (StringArray& names) { if (dataThread != 0) dataThread->getEventChannelNames(names); - } + void SourceNode::updateSettings() { if (inputBuffer == 0 && dataThread != 0) { - inputBuffer = dataThread->getBufferAddress(); std::cout << "Input buffer address is " << inputBuffer << std::endl; } dataThread->updateChannels(); - } -void SourceNode::actionListenerCallback(const String& msg) -{ +void SourceNode::actionListenerCallback (const String& msg) +{ //std::cout << msg << std::endl; - if (msg.equalsIgnoreCase("HI")) + if (msg.equalsIgnoreCase ("HI")) { // std::cout << "HI." << std::endl; // dataThread->setOutputHigh(); ttlState = 1; } - else if (msg.equalsIgnoreCase("LO")) + else if (msg.equalsIgnoreCase ("LO")) { // std::cout << "LO." << std::endl; // dataThread->setOutputLow(); @@ -131,109 +125,113 @@ void SourceNode::actionListenerCallback(const String& msg) } } -int SourceNode::getTTLState() -{ - return ttlState; -} -float SourceNode::getSampleRate() +float SourceNode::getSampleRate() const { - - if (dataThread != 0) + if (dataThread != nullptr) return dataThread->getSampleRate(); else return 44100.0; } -float SourceNode::getDefaultSampleRate() + +float SourceNode::getDefaultSampleRate() const { - if (dataThread != 0) + if (dataThread != nullptr) return dataThread->getSampleRate(); else return 44100.0; } -int SourceNode::getNumHeadstageOutputs() + +int SourceNode::getNumHeadstageOutputs() const { - if (dataThread != 0) + if (dataThread != nullptr) return dataThread->getNumHeadstageOutputs(); else return 2; } -int SourceNode::getNumAuxOutputs() + +int SourceNode::getNumAuxOutputs() const { - if (dataThread != 0) + if (dataThread != nullptr) return dataThread->getNumAuxOutputs(); else return 0; } -int SourceNode::getNumAdcOutputs() + +int SourceNode::getNumAdcOutputs() const { - if (dataThread != 0) + if (dataThread != nullptr) return dataThread->getNumAdcOutputs(); else return 0; } -int SourceNode::getNumEventChannels() + +int SourceNode::getNumEventChannels() const { - if (dataThread != 0) + if (dataThread != nullptr) return dataThread->getNumEventChannels(); else return 0; } -float SourceNode::getBitVolts(Channel* chan) + +float SourceNode::getBitVolts (Channel* chan) const { if (dataThread != 0) - return dataThread->getBitVolts(chan); + return dataThread->getBitVolts (chan); else return 1.0f; } -void SourceNode::enabledState(bool t) +void SourceNode::setEnabledState (bool newState) { - if (t && !dataThread->foundInputSource()) + if (newState && ! dataThread->foundInputSource()) { isEnabled = false; } else { - isEnabled = t; + isEnabled = newState; } - } -void SourceNode::setParameter(int parameterIndex, float newValue) + +void SourceNode::setParameter (int parameterIndex, float newValue) { - editor->updateParameterButtons(parameterIndex); + editor->updateParameterButtons (parameterIndex); //std::cout << "Got parameter change notification"; } + AudioProcessorEditor* SourceNode::createEditor() { - if (dataThread != nullptr) - { - editor = dataThread->createEditor(this); - } - else - { - editor = nullptr; - } - - if (editor == nullptr) + if (dataThread != nullptr) { - editor = new SourceNodeEditor(this, true); + editor = dataThread->createEditor (this); } + else + { + editor = nullptr; + } + + if (editor == nullptr) + { + editor = new SourceNodeEditor (this, true); + } + return editor; } + bool SourceNode::tryEnablingEditor() { - if (!sourcePresent()) + if (! isSourcePresent()) { //std::cout << "No input source found." << std::endl; return false; @@ -247,43 +245,47 @@ bool SourceNode::tryEnablingEditor() } std::cout << "Input source found." << std::endl; - enabledState(true); + setEnabledState (true); + GenericEditor* ed = getEditor(); - CoreServices::highlightEditor(ed); + CoreServices::highlightEditor (ed); return true; } + void SourceNode::timerCallback() { - if (!tryEnablingEditor() && isEnabled) + if (! tryEnablingEditor() && isEnabled) { std::cout << "Input source lost." << std::endl; - enabledState(false); + setEnabledState (false); GenericEditor* ed = getEditor(); - CoreServices::highlightEditor(ed); + CoreServices::highlightEditor (ed); } } + bool SourceNode::isReady() { - return sourcePresent() && dataThread->isReady(); + return isSourcePresent() && dataThread->isReady(); } -bool SourceNode::sourcePresent() + +bool SourceNode::isSourcePresent() const { - return dataThread && dataThread->foundInputSource(); + return dataThread && dataThread->foundInputSource(); } + bool SourceNode::enable() { - std::cout << "Source node received enable signal" << std::endl; wasDisabled = false; stopTimer(); - if (dataThread != 0) + if (dataThread != nullptr) { dataThread->startAcquisition(); return true; @@ -292,18 +294,17 @@ bool SourceNode::enable() { return false; } - } + bool SourceNode::disable() { - std::cout << "Source node received disable signal" << std::endl; - if (dataThread != 0) + if (dataThread != nullptr) dataThread->stopAcquisition(); - startTimer(2000); // timer to check for connected source + startTimer (2000); // timer to check for connected source wasDisabled = true; @@ -312,148 +313,109 @@ bool SourceNode::disable() return true; } + void SourceNode::acquisitionStopped() { - //if (!dataThread->foundInputSource()) { - - if (!wasDisabled) + if (! wasDisabled) { std::cout << "Source node sending signal to UI." << std::endl; + AccessClass::getUIComponent()->disableCallbacks(); - enabledState(false); + setEnabledState (false); + GenericEditor* ed = (GenericEditor*) getEditor(); - CoreServices::highlightEditor(ed); + CoreServices::highlightEditor (ed); } - //} } -void SourceNode::process(AudioSampleBuffer& buffer, - MidiBuffer& events) +void SourceNode::process (AudioSampleBuffer& buffer, MidiBuffer& events) { - - //std::cout << "SOURCE NODE" << std::endl; - // clear the input buffers events.clear(); buffer.clear(); - int nSamples = inputBuffer->readAllFromBuffer(buffer, ×tamp, eventCodeBuffer, buffer.getNumSamples()); - - setNumSamples(events, nSamples); - setTimestamp(events, timestamp); - - //std::cout << *buffer.getReadPointer(0) << std::endl; - - //std::cout << "Source node timestamp: " << timestamp << std::endl; - - //std::cout << "Samples per buffer: " << nSamples << std::endl; - - - - - // std::cout << (int) *(data + 7) << " " << - // (int) *(data + 6) << " " << - // (int) *(data + 5) << " " << - // (int) *(data + 4) << " " << - // (int) *(data + 3) << " " << - // (int) *(data + 2) << " " << - // (int) *(data + 1) << " " << - // (int) *(data + 0) << std::endl; + int nSamples = inputBuffer->readAllFromBuffer (buffer, ×tamp, eventCodeBuffer, buffer.getNumSamples()); + setNumSamples (events, nSamples); + setTimestamp (events, timestamp); // fill event buffer - for (int i = 0; i < nSamples; i++) + for (int i = 0; i < nSamples; ++i) { - for (int c = 0; c < numEventChannels; c++) + for (int c = 0; c < numEventChannels; ++c) { - int state = eventCodeBuffer[i] & (1 << c); + const int state = eventCodeBuffer[i] & (1 << c); if (eventChannelState[c] != state) { if (state == 0) { - - //std::cout << "OFF" << std::endl; - //std::cout << c << std::endl; // signal channel state is OFF - addEvent(events, // MidiBuffer - TTL, // eventType - i, // sampleNum - 0, // eventID - c, // eventChannel - 8, - (uint8*)(&eventCodeBuffer[i]) - ); + addEvent (events, // MidiBuffer + TTL, // eventType + i, // sampleNum + 0, // eventID + c, // eventChannel + 8, + (uint8*)(&eventCodeBuffer[i])); } else { - - // std::cout << "ON" << std::endl; - // std::cout << c << std::endl; - // signal channel state is ON - addEvent(events, // MidiBuffer - TTL, // eventType - i, // sampleNum - 1, // eventID - c, // eventChannel - 8, - (uint8*)(&eventCodeBuffer[i]) - ); - - + addEvent(events, // MidiBuffer + TTL, // eventType + i, // sampleNum + 1, // eventID + c, // eventChannel + 8, + (uint8*)(&eventCodeBuffer[i])); } eventChannelState[c] = state; } } } - } - -void SourceNode::saveCustomParametersToXml(XmlElement* parentElement) +void SourceNode::saveCustomParametersToXml (XmlElement* parentElement) { - - XmlElement* channelXml = parentElement->createNewChildElement("CHANNEL_INFO"); + XmlElement* channelXml = parentElement->createNewChildElement ("CHANNEL_INFO"); if (dataThread->usesCustomNames()) { Array<ChannelCustomInfo> channelInfo; - dataThread->getChannelInfo(channelInfo); - for (int i = 0; i < channelInfo.size(); i++) + dataThread->getChannelInfo (channelInfo); + for (int i = 0; i < channelInfo.size(); ++i) { - XmlElement* chan = channelXml->createNewChildElement("CHANNEL"); - chan->setAttribute("name", channelInfo[i].name); - chan->setAttribute("number", i); - chan->setAttribute("gain", channelInfo[i].gain); + XmlElement* chan = channelXml->createNewChildElement ("CHANNEL"); + chan->setAttribute ("name", channelInfo[i].name); + chan->setAttribute ("number", i); + chan->setAttribute ("gain", channelInfo[i].gain); } } - } + void SourceNode::loadCustomParametersFromXml() { - if (parametersAsXml != nullptr) { // use parametersAsXml to restore state - - forEachXmlChildElement(*parametersAsXml, xmlNode) + forEachXmlChildElement (*parametersAsXml, xmlNode) { - if (xmlNode->hasTagName("CHANNEL_INFO")) + if (xmlNode->hasTagName ("CHANNEL_INFO")) { - forEachXmlChildElementWithTagName(*xmlNode,chan,"CHANNEL") + forEachXmlChildElementWithTagName (*xmlNode, chan, "CHANNEL") { - String name = chan->getStringAttribute("name"); - int number = chan->getIntAttribute("number"); - float gain = chan->getDoubleAttribute("gain"); - dataThread->modifyChannelGain(number, gain); - dataThread->modifyChannelName(number, name); + const int number = chan->getIntAttribute ("number"); + const float gain = chan->getDoubleAttribute ("gain"); + String name = chan->getStringAttribute ("name"); + + dataThread->modifyChannelGain (number, gain); + dataThread->modifyChannelName (number, name); } } } } - -} \ No newline at end of file +} diff --git a/Source/Processors/SourceNode/SourceNode.h b/Source/Processors/SourceNode/SourceNode.h index 88febeba1..0dc674af3 100755 --- a/Source/Processors/SourceNode/SourceNode.h +++ b/Source/Processors/SourceNode/SourceNode.h @@ -2,7 +2,7 @@ ------------------------------------------------------------------ This file is part of the Open Ephys GUI - Copyright (C) 2014 Open Ephys + Copyright (C) 2016 Open Ephys ------------------------------------------------------------------ @@ -30,105 +30,91 @@ #include "../GenericProcessor/GenericProcessor.h" #include "../../UI/UIComponent.h" -/** +/** Creates and controls a thread for reading data from external sources. @see GenericProcessor, SourceNodeEditor, DataThread, IntanThread - */ - -class PLUGIN_API SourceNode : public GenericProcessor, - public Timer, - public ActionListener - +class PLUGIN_API SourceNode : public GenericProcessor + , public Timer + , public ActionListener { public: - - // real member functions: - SourceNode(const String& name, DataThreadCreator dt); + SourceNode (const String& name, DataThreadCreator dt); ~SourceNode(); - void enabledState(bool t); + void actionListenerCallback (const String& message) override; - void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages); + AudioProcessorEditor* createEditor() override; - void setParameter(int parameterIndex, float newValue); + void setEnabledState (bool newState) override; - float getSampleRate(); - float getDefaultSampleRate(); - int getNumHeadstageOutputs(); + void process (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) override; - int getNumAuxOutputs(); - int getNumAdcOutputs(); + void setParameter (int parameterIndex, float newValue) override; - int getNumEventChannels(); - float getBitVolts(Channel* chan); + void getEventChannelNames (StringArray& names) override; - void requestChainUpdate(); + void saveCustomParametersToXml (XmlElement* parentElement) override; + void loadCustomParametersFromXml() override; - void getEventChannelNames(StringArray& names); + float getSampleRate() const override; + float getDefaultSampleRate() const override; - AudioProcessorEditor* createEditor(); - bool hasEditor() const - { - return true; - } + float getBitVolts (Channel* chan) const override; - bool enable(); - bool disable(); + int getNumHeadstageOutputs() const override; + int getNumAuxOutputs() const override; + int getNumAdcOutputs() const override; - bool isReady(); - bool sourcePresent(); + int getNumEventChannels() const override; - bool isSource() - { - return true; - } + void requestChainUpdate(); - bool generatesTimestamps() - { - return true; - } + bool hasEditor() const override { return true; } - void acquisitionStopped(); + bool isGeneratesTimestamps() const override { return true; } - DataThread* getThread(); + bool enable() override; + bool disable() override; - void actionListenerCallback(const String& message); + bool isReady() override; - int getTTLState(); + bool isSourcePresent() const; - void saveCustomParametersToXml(XmlElement* parentElement); - void loadCustomParametersFromXml(); + void acquisitionStopped(); + + DataThread* getThread() const { return dataThread; } + + int getTTLState() const { return ttlState; } bool tryEnablingEditor(); + private: + void timerCallback() override; - int numEventChannels; + void updateSettings() override; + int numEventChannels; int sourceCheckInterval; bool wasDisabled; - void timerCallback(); - ScopedPointer<DataThread> dataThread; DataBuffer* inputBuffer; uint64 timestamp; //uint64* eventCodeBuffer; //int* eventChannelState; - HeapBlock<uint64> eventCodeBuffer; - HeapBlock<int> eventChannelState; + HeapBlock<uint64> eventCodeBuffer; + HeapBlock<int> eventChannelState; int ttlState; - void updateSettings(); - - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SourceNode); + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SourceNode); }; -- GitLab