GenericProcessor.cpp 8.65 KiB
/*
------------------------------------------------------------------
This file is part of the Open Ephys GUI
Copyright (C) 2012 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 "GenericProcessor.h"
#include "../UI/UIComponent.h"
GenericProcessor::GenericProcessor(const String& name_) :
name(name_),
sourceNode(0), destNode(0),
isEnabled(true),
saveOrder(-1), loadOrder(-1),
nextAvailableChannel(0), currentChannel(-1),
wasConnected(false)
{
}
GenericProcessor::~GenericProcessor()
{
}
AudioProcessorEditor* GenericProcessor::createEditor()
{
editor = new GenericEditor (this);
return editor;
}
void GenericProcessor::setParameter (int parameterIndex, float newValue)
{
}
void GenericProcessor::prepareToPlay (double sampleRate_, int estimatedSamplesPerBlock)
{
// use the enable() function instead
// prepareToPlay() is called by Juce as soon as a processor is created
// enable() is only called by the ProcessorGraph just before the start of acquisition
}
void GenericProcessor::releaseResources()
{
// use the disable() function instead
// releaseResources() is called by Juce at unpredictable times
// disable() is only called by the ProcessorGraph at the end of acquisition
}
int GenericProcessor::getNextChannel(bool increment)
{
int chan = nextAvailableChannel;
//std::cout << chan << std::endl;
if (increment)
nextAvailableChannel++;
if (chan < getNumInputs())
return chan;
else
return -1;
}
void GenericProcessor::resetConnections()
{
//std::cout << "Resetting connections" << std::endl;
nextAvailableChannel = 0;
wasConnected = false;
}
void GenericProcessor::setNumSamples(MidiBuffer& midiMessages, int sampleIndex) {
uint8 data[2];
data[0] = BUFFER_SIZE; // most-significant byte
data[1] = nodeId; // least-significant byte
midiMessages.addEvent(data, // spike data
2, // total bytes
sampleIndex); // sample index
}
int GenericProcessor::getNumSamples(MidiBuffer& midiMessages) {
int numRead = 0;
if (midiMessages.getNumEvents() > 0)
{
int m = midiMessages.getNumEvents();
MidiBuffer::Iterator i (midiMessages);
MidiMessage message(0xf4);
int samplePosition = -5;
while (i.getNextEvent (message, samplePosition)) {
uint8* dataptr = message.getRawData();
if (*dataptr == BUFFER_SIZE)
{
numRead = message.getTimeStamp();
}
}
}
return numRead;
}
void GenericProcessor::setSourceNode(GenericProcessor* sn)
{
//std::cout << "My name is " << getName() << ". Setting source node." << std::endl;
if (!isSource())
{
// std::cout << " I am not a source." << std::endl;
if (sn != 0)
{
// std::cout << " The source is not blank." << std::endl;
if (!sn->isSink())
{
// std::cout << " The source is not a sink." << std::endl;
if (sourceNode != sn) {
// std::cout << " The source is new and named " << sn->getName() << std::endl;
if (this->isMerger())
setMergerSourceNode(sn);
else
sourceNode = sn;
sn->setDestNode(this);
//setNumInputs(sn->getNumOutputs());
//setSampleRate(sn->getSampleRate());
} else {
// std::cout << " The source node is not new." << std::endl;
}
} else {
// std::cout << " The source is a sink." << std::endl;
sourceNode = 0;
}
} else {
// std::cout << " The source is blank." << std::endl;
sourceNode = 0;
}
} else {
// std::cout << " I am a source. I can't have a source node." << std::endl;
if (sn != 0)
sn->setDestNode(this);
}
}
void GenericProcessor::setDestNode(GenericProcessor* dn)
{
// std::cout << "My name is " << getName() << ". Setting dest node." << std::endl;
if (!isSink())
{
// std::cout << " I am not a sink." << std::endl;
if (dn != 0)
{
// std::cout << " The dest node is not blank." << std::endl;
if (!dn->isSource())
{
// std::cout << " The dest node is not a source." << std::endl;
if (destNode != dn)
{
// std::cout << " The dest node is new and named " << dn->getName() << std::endl;
//
if (this->isSplitter())
setSplitterDestNode(dn);
else
destNode = dn;
dn->setSourceNode(this);
//dn->setNumInputs(getNumOutputs());
//dn->setSampleRate(getSampleRate());
} else {
// std::cout << " The dest node is not new." << std::endl;
}
} else {
// std::cout << " The dest node is a source." << std::endl;
destNode = 0;
}
} else {
// std::cout << " The dest node is blank." << std::endl;
destNode = 0;
}
} else {
//std::cout << " I am a sink, I can't have a dest node." << std::endl;
//if (dn != 0)
// dn->setSourceNode(this);
}
}
void GenericProcessor::clearSettings()
{
settings.originalSource = 0;
settings.numInputs = 0;
settings.numOutputs = 0;
settings.inputChannelNames.clear();
settings.outputChannelNames.clear();
settings.bitVolts.clear();
settings.eventChannelIds.clear();
settings.eventChannelNames.clear();
}
void GenericProcessor::update()
{
std::cout << getName() << " updating settings." << std::endl;
clearSettings();
if (sourceNode != 0)
{
// everything is inherited except numOutputs
settings = sourceNode->settings;
settings.numInputs = settings.numOutputs;
settings.numOutputs = settings.numInputs;
} else {
settings.sampleRate = getDefaultSampleRate();
settings.numOutputs = getDefaultNumOutputs();
for (int i = 0; i < getNumOutputs(); i++)
settings.bitVolts.add(getDefaultBitVolts());
generateDefaultChannelNames(settings.outputChannelNames);
}
if (this->isSink())
{
settings.numOutputs = 0;
settings.outputChannelNames.clear();
}
updateSettings(); // custom settings code
// required for the ProcessorGraph to know the
// details of this processor:
setPlayConfigDetails(getNumInputs(), // numIns
getNumOutputs(), // numOuts
44100.0, // sampleRate
128); // blockSize
editor->update(); // update editor settings
}
void GenericProcessor::generateDefaultChannelNames(StringArray& names)
{
names.clear();
for (int i = 0; i < settings.numOutputs; i++)
{
String channelName = "CH";
channelName += (i+1);
names.add(channelName);
}
}
int GenericProcessor::checkForEvents(MidiBuffer& midiMessages)
{
if (midiMessages.getNumEvents() > 0)
{
int m = midiMessages.getNumEvents();
//std::cout << m << " events received by node " << getNodeId() << std::endl;
MidiBuffer::Iterator i (midiMessages);
MidiMessage message(0xf4);
int samplePosition;
i.setNextSamplePosition(samplePosition);
while (i.getNextEvent (message, samplePosition)) {
//int numbytes = message.getRawDataSize();
uint8* dataptr = message.getRawData();
handleEvent(*dataptr, message);
}
}
return -1;
}
void GenericProcessor::addEvent(MidiBuffer& midiMessages,
uint8 type,
int sampleNum,
uint8 eventId,
uint8 eventChannel,
uint8 numBytes,
uint8* eventData)
{
uint8 data[4+numBytes];
data[0] = type; // event type
data[1] = nodeId; // processor ID
data[2] = eventId; // event ID
data[3] = eventChannel; // event channel
memcpy(&data[4], eventData, numBytes);
midiMessages.addEvent(data, // spike data
sizeof(data), // total bytes
sampleNum); // sample index
}
void GenericProcessor::processBlock (AudioSampleBuffer &buffer, MidiBuffer &midiMessages)
{
int nSamples = getNumSamples(midiMessages); // removes first value from midimessages
process(buffer, midiMessages, nSamples);
setNumSamples(midiMessages, nSamples); // adds it back,
// even if it's unchanged
}