Skip to content
Snippets Groups Projects
Commit d229f5be authored by Aaron Cuevas Lopez's avatar Aaron Cuevas Lopez
Browse files

Implement basic generic RecordEngine functionality

parent 16452b04
No related branches found
No related tags found
No related merge requests found
Microsoft Visual Studio Solution File, Format Version 11.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012 # Visual Studio 2012
Project("{5A05F353-1D63-394C-DFB0-981BB2309002}") = "open-ephys", "open-ephys.vcxproj", "{9C924D66-7DEC-1AEF-B375-DB8666BFB909}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "open-ephys", "open-ephys.vcxproj", "{9C924D66-7DEC-1AEF-B375-DB8666BFB909}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32 Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32 Debug|x64 = Debug|x64
Debug64|Win32 = Debug64|Win32
Debug64|x64 = Debug64|x64 Debug64|x64 = Debug64|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
Release64|Win32 = Release64|Win32
Release64|x64 = Release64|x64 Release64|x64 = Release64|x64
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Debug|Win32.ActiveCfg = Debug|Win32 {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Debug|Win32.ActiveCfg = Debug|Win32
{9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Debug|Win32.Build.0 = Debug|Win32 {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Debug|Win32.Build.0 = Debug|Win32
{9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Release|Win32.ActiveCfg = Release|Win32 {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Debug|x64.ActiveCfg = Debug|Win32
{9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Release|Win32.Build.0 = Release|Win32 {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Debug64|Win32.ActiveCfg = Debug64|x64
{9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Debug64|x64.ActiveCfg = Debug64|x64 {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Debug64|x64.ActiveCfg = Debug64|x64
{9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Debug64|x64.Build.0 = Debug64|x64 {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Debug64|x64.Build.0 = Debug64|x64
{9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Release|Win32.ActiveCfg = Release|Win32
{9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Release|Win32.Build.0 = Release|Win32
{9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Release|x64.ActiveCfg = Release|Win32
{9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Release64|Win32.ActiveCfg = Release64|x64
{9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Release64|x64.ActiveCfg = Release64|x64 {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Release64|x64.ActiveCfg = Release64|x64
{9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Release64|x64.Build.0 = Release64|x64 {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Release64|x64.Build.0 = Release64|x64
EndGlobalSection EndGlobalSection
......
...@@ -24,7 +24,8 @@ ...@@ -24,7 +24,8 @@
#include "Channel.h" #include "Channel.h"
Channel::Channel(GenericProcessor* p, int n) : num(n), eventType(0), processor(p), sampleRate(44100.0), bitVolts(1.0f), isADCchannel(false),isEventChannel(false), isMonitored(false), isEnabled(true), isRecording(false) Channel::Channel(GenericProcessor* p, int n) : num(n), eventType(0), processor(p), sampleRate(44100.0), bitVolts(1.0f),
isADCchannel(false),isEventChannel(false), isMonitored(false), isEnabled(true), isRecording(false), recordFileId(-1);
{ {
nodeId = p->getNodeId(); nodeId = p->getNodeId();
......
...@@ -98,10 +98,8 @@ public: ...@@ -98,10 +98,8 @@ public:
bool isMonitored; bool isMonitored;
bool isEnabled; bool isEnabled;
// file info (for disk writing): // file info (for disk writing). Meaning depends on RecordEngine
String filename; int recordIndex;
FILE* file;
int recordFileId;
String name; String name;
......
...@@ -22,3 +22,18 @@ ...@@ -22,3 +22,18 @@
*/ */
#include "RecordEngine.h" #include "RecordEngine.h"
#include "RecordNode.h"
RecordEngine::RecordEngine(RecordNode* rn)
{
recordNode = rn;
}
void RecordEngine::clearConnections() {}
void RecordEngine::registerProcessor(GenericProcessor* processor) {}
Channel* RecordEngine::getChannel(int index)
{
return recordNode->getDataChannel(index);
}
\ No newline at end of file
...@@ -24,7 +24,34 @@ ...@@ -24,7 +24,34 @@
#ifndef RECORDENGINE_H_INCLUDED #ifndef RECORDENGINE_H_INCLUDED
#define RECORDENGINE_H_INCLUDED #define RECORDENGINE_H_INCLUDED
#include "../../JuceLibraryCode/JuceHeader.h"
#include "Channel.h"
#include "GenericProcessor.h"
class RecordNode;
class RecordEngine
{
public:
RecordEngine(RecordNode* rn);
~RecordEngine();
virtual void openFiles(File rootfolder) =0;
virtual void closeFiles() =0;
virtual void writeData(AudioSampleBuffer& buffer, int nSamples, int64 timestamp) =0;
virtual void writeEvent(MidiMessage& event, int samplePosition) =0;
virtual void addChannel(int index, Channel* chan) =0;
virtual void registerProcessor(GenericProcessor* processor);
virtual void clearConnections();
protected:
Channel* getChannel(int index);
private:
RecordNode* recordNode;
};
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
#include "../UI/EditorViewport.h" #include "../UI/EditorViewport.h"
#include "../UI/ControlPanel.h" #include "../UI/ControlPanel.h"
#define EVERY_ENGINE for(int eng = 0; eng < engineArray.size(); eng++) engineArray[eng]
...@@ -34,40 +34,24 @@ ...@@ -34,40 +34,24 @@
RecordNode::RecordNode() RecordNode::RecordNode()
: GenericProcessor("Record Node"), : GenericProcessor("Record Node"),
newDirectoryNeeded(true), zeroBuffer(1, 50000), timestamp(0), newDirectoryNeeded(true), timestamp(0)
appendTrialNum(false), trialNum(0)
{ {
isProcessing = false; isProcessing = false;
isRecording = false; isRecording = false;
allFilesOpened = false; allFilesOpened = false;
blockIndex = 0;
signalFilesShouldClose = false; signalFilesShouldClose = false;
continuousDataIntegerBuffer = new int16[10000];
continuousDataFloatBuffer = new float[10000];
signalFilesShouldClose = false; signalFilesShouldClose = false;
settings.numInputs = 2048; settings.numInputs = 2048;
settings.numOutputs = 0; settings.numOutputs = 0;
eventChannel = new Channel(this, 0);
eventChannel->isEventChannel = true;
recordMarker = new char[10];
for (int i = 0; i < 9; i++)
{
recordMarker[i] = i;
}
recordMarker[9] = 255;
recordingNumber = 0; recordingNumber = 0;
// 128 inputs, 0 outputs // 128 inputs, 0 outputs
setPlayConfigDetails(getNumInputs(),getNumOutputs(),44100.0,128); setPlayConfigDetails(getNumInputs(),getNumOutputs(),44100.0,128);
zeroBuffer.clear();
} }
...@@ -125,7 +109,7 @@ void RecordNode::resetConnections() ...@@ -125,7 +109,7 @@ void RecordNode::resetConnections()
channelPointers.clear(); channelPointers.clear();
eventChannelPointers.clear(); eventChannelPointers.clear();
EVERY_ENGINE->clearConnections();
} }
...@@ -149,34 +133,19 @@ void RecordNode::filenameComponentChanged(FilenameComponent* fnc) ...@@ -149,34 +133,19 @@ void RecordNode::filenameComponentChanged(FilenameComponent* fnc)
void RecordNode::addInputChannel(GenericProcessor* sourceNode, int chan) void RecordNode::addInputChannel(GenericProcessor* sourceNode, int chan)
{ {
if (chan != getProcessorGraph()->midiChannelIndex) if (chan != getProcessorGraph()->midiChannelIndex)
{ {
int channelIndex = getNextChannel(false); int channelIndex = getNextChannel(false);
setPlayConfigDetails(channelIndex+1,0,44100.0,128);
channelPointers.add(sourceNode->channels[chan]); channelPointers.add(sourceNode->channels[chan]);
// std::cout << channelIndex << std::endl; // std::cout << channelIndex << std::endl;
updateFileName(channelPointers[channelIndex]); channelPointers[channelIndex]->recordIndex = channelIndex;
//if (channelPointers[channelIndex]->isRecording)
// std::cout << " This channel will be recorded." << std::endl;
//else
// std::cout << " This channel will NOT be recorded." << std::endl;
//std::cout << "adding channel " << getNextChannel(false) << std::endl;
//std::pair<int, Channel> newPair (getNextChannel(false), newChannel);
//std::cout << "adding channel " << getNextChannel(false) << std::endl;
//continuouschannelPointers.insert(newPair);
EVERY_ENGINE->addChannel(channelIndex,channelPointers[channelIndex]);
} }
else else
...@@ -193,75 +162,13 @@ void RecordNode::addInputChannel(GenericProcessor* sourceNode, int chan) ...@@ -193,75 +162,13 @@ void RecordNode::addInputChannel(GenericProcessor* sourceNode, int chan)
} }
void RecordNode::updateFileName(Channel* ch)
{
String filename = rootFolder.getFullPathName();
filename += rootFolder.separatorString;
if (!ch->isEventChannel)
{
filename += ch->nodeId;
filename += "_";
filename += ch->name;
if (appendTrialNum)
{
filename += "_";
filename += trialNum;
}
filename += ".continuous";
}
else
{
filename += "all_channels.events";
}
ch->filename = filename;
ch->file = 0;
//std::cout << "Updating " << filename << std::endl;
}
void RecordNode::updateTrialNumber()
{
trialNum++;
}
void RecordNode::appendTrialNumber(bool t)
{
appendTrialNum = t;
}
void RecordNode::createNewDirectory() void RecordNode::createNewDirectory()
{ {
std::cout << "Creating new directory." << std::endl; std::cout << "Creating new directory." << std::endl;
rootFolder = File(dataDirectory.getFullPathName() + File::separator + generateDirectoryName()); rootFolder = File(dataDirectory.getFullPathName() + File::separator + generateDirectoryName());
updateFileName(eventChannel);
for (int i = 0; i < channelPointers.size(); i++)
{
updateFileName(channelPointers[i]);
}
newDirectoryNeeded = false; newDirectoryNeeded = false;
trialNum = 0;
}
void RecordNode::createNewFiles()
{
for (int i = 0; i < channelPointers.size(); i++)
{
updateFileName(channelPointers[i]);
}
} }
String RecordNode::generateDirectoryName() String RecordNode::generateDirectoryName()
...@@ -368,28 +275,8 @@ void RecordNode::setParameter(int parameterIndex, float newValue) ...@@ -368,28 +275,8 @@ void RecordNode::setParameter(int parameterIndex, float newValue)
getEditorViewport()->saveState(File(settingsFileName)); getEditorViewport()->saveState(File(settingsFileName));
} }
createNewFiles(); EVERY_ENGINE->openFiles(rootFolder);
openFile(eventChannel);
//HDF5
HDFOpenFiles();
blockIndex = 0; // reset index
// create / open necessary files
for (int i = 0; i < channelPointers.size(); i++)
{
// std::cout << "Checking channel " << i << std::endl;
if (channelPointers[i]->getRecordState())
{
openFile(channelPointers[i]);
}
}
allFilesOpened = true; allFilesOpened = true;
} }
...@@ -419,186 +306,34 @@ void RecordNode::setParameter(int parameterIndex, float newValue) ...@@ -419,186 +306,34 @@ void RecordNode::setParameter(int parameterIndex, float newValue)
std::cout << "Toggling channel " << currentChannel << std::endl; std::cout << "Toggling channel " << currentChannel << std::endl;
if (isRecording)
{
//Toggling channels while recording isn't allowed. Code shouldn't reach here.
//In case it does, display an error and exit.
sendActionMessage("Toggling record channels while recording is not allowed");
std::cout << "ERROR: Wrong code section reached\n Toggling record channels while recording is not allowed." << std::endl;
return;
}
if (newValue == 0.0f) if (newValue == 0.0f)
{ {
channelPointers[currentChannel]->setRecordState(false); channelPointers[currentChannel]->setRecordState(false);
if (isRecording)
{
if (blockIndex < BLOCK_LENGTH)
{
// fill out the rest of the current buffer
writeContinuousBuffer(zeroBuffer.getReadPointer(0), BLOCK_LENGTH - blockIndex, currentChannel);
}
closeFile(channelPointers[currentChannel]);
}
} }
else else
{ {
channelPointers[currentChannel]->setRecordState(true); channelPointers[currentChannel]->setRecordState(true);
if (isRecording)
{
openFile(channelPointers[currentChannel]);
if (blockIndex > 0)
{
writeTimestampAndSampleCount(channelPointers[currentChannel]->file);
// fill up the first data block up to sample count
writeContinuousBuffer(zeroBuffer.getReadPointer(0), blockIndex, currentChannel);
}
}
} }
} }
} }
} }
void RecordNode::openFile(Channel* ch)
{
std::cout << "OPENING FILE: " << ch->filename << std::endl;
File f = File(ch->filename);
FILE* chFile;
bool fileExists = f.exists();
diskWriteLock.enter();
chFile = fopen(ch->filename.toUTF8(), "ab");
if (!fileExists)
{
// create and write header
std::cout << "Writing header." << std::endl;
String header = generateHeader(ch);
//std::cout << header << std::endl;
std::cout << "File ID: " << chFile << ", number of bytes: " << header.getNumBytesAsUTF8() << std::endl;
fwrite(header.toUTF8(), 1, header.getNumBytesAsUTF8(), chFile);
std::cout << "Wrote header." << std::endl;
std::cout << "Block index: " << blockIndex << std::endl;
}
else
{
std::cout << "File already exists, just opening." << std::endl;
}
diskWriteLock.exit();
//To avoid a race condition resulting on data written before the header,
//do not assign the channel pointer until the header has been written
ch->file = chFile;
}
void RecordNode::closeFile(Channel* ch)
{
diskWriteLock.enter();
std::cout << "CLOSING FILE: " << ch->filename << std::endl;
if (ch->file != NULL)
fclose(ch->file);
diskWriteLock.exit();
}
String RecordNode::generateHeader(Channel* ch)
{
String header = "header.format = 'Open Ephys Data Format'; \n";
header += "header.version = 0.2;";
header += "header.header_bytes = ";
header += String(HEADER_SIZE);
header += ";\n";
if (ch->isEventChannel)
{
header += "header.description = 'each record contains one 64-bit timestamp, one 16-bit sample position, one uint8 event type, one uint8 processor ID, one uint8 event ID, one uint8 event channel, and one uint16 recordingNumber'; \n";
}
else
{
header += "header.description = 'each record contains one 64-bit timestamp, one 16-bit sample count (N), 1 uint16 recordingNumber, N 16-bit samples, and one 10-byte record marker (0 1 2 3 4 5 6 7 8 255)'; \n";
}
header += "header.date_created = '";
header += generateDateString();
header += "';\n";
header += "header.channel = '";
header += ch->name;
header += "';\n";
if (ch->isEventChannel)
{
header += "header.channelType = 'Event';\n";
}
else
{
header += "header.channelType = 'Continuous';\n";
}
header += "header.sampleRate = ";
// all channels need to have the same sample rate under the current scheme
header += String(channelPointers[0]->sampleRate);
header += ";\n";
header += "header.blockLength = ";
header += BLOCK_LENGTH;
header += ";\n";
header += "header.bufferSize = ";
header += getAudioComponent()->getBufferSize();
header += ";\n";
header += "header.bitVolts = ";
header += String(ch->bitVolts);
header += ";\n";
header = header.paddedRight(' ', HEADER_SIZE);
//std::cout << header << std::endl;
return header;
}
void RecordNode::closeAllFiles() void RecordNode::closeAllFiles()
{ {
if (allFilesOpened) if (allFilesOpened)
{ {
for (int i = 0; i < channelPointers.size(); i++) EVERY_ENGINE->closeFiles();
{
if (channelPointers[i]->getRecordState())
{
if (blockIndex < BLOCK_LENGTH)
{
// fill out the rest of the current buffer
writeContinuousBuffer(zeroBuffer.getReadPointer(0), BLOCK_LENGTH - blockIndex, i);
}
closeFile(channelPointers[i]);
}
}
closeFile(eventChannel);
blockIndex = 0; // back to the beginning of the block
allFilesOpened = false; allFilesOpened = false;
} }
//HDF5
HDFCloseFiles();
} }
bool RecordNode::enable() bool RecordNode::enable()
...@@ -627,135 +362,12 @@ float RecordNode::getFreeSpace() ...@@ -627,135 +362,12 @@ float RecordNode::getFreeSpace()
return 1.0f - float(dataDirectory.getBytesFreeOnVolume())/float(dataDirectory.getVolumeTotalSize()); return 1.0f - float(dataDirectory.getBytesFreeOnVolume())/float(dataDirectory.getVolumeTotalSize());
} }
void RecordNode::writeContinuousBuffer(const float* data, int nSamples, int channel)
{
// check to see if the file exists
if (channelPointers[channel]->file == NULL)
return;
// scale the data back into the range of int16
float scaleFactor = float(0x7fff) * channelPointers[channel]->bitVolts;
for (int n = 0; n < nSamples; n++)
{
*(continuousDataFloatBuffer+n) = *(data+n) / scaleFactor;
}
AudioDataConverters::convertFloatToInt16BE(continuousDataFloatBuffer, continuousDataIntegerBuffer, nSamples);
//HDF5
fileArray[channelPointers[channel]->recordFileId]->writeRowData(continuousDataIntegerBuffer,nSamples);
if (blockIndex == 0)
{
writeTimestampAndSampleCount(channelPointers[channel]->file);
}
diskWriteLock.enter();
size_t count = fwrite(continuousDataIntegerBuffer, // ptr
2, // size of each element
nSamples, // count
channelPointers[channel]->file); // ptr to FILE object
jassert(count == nSamples); // make sure all the data was written
diskWriteLock.exit();
if (blockIndex + nSamples == BLOCK_LENGTH)
{
writeRecordMarker(channelPointers[channel]->file);
}
}
void RecordNode::writeTimestampAndSampleCount(FILE* file)
{
diskWriteLock.enter();
uint16 samps = BLOCK_LENGTH;
fwrite(&timestamp, // ptr
8, // size of each element
1, // count
file); // ptr to FILE object
fwrite(&samps, // ptr
2, // size of each element
1, // count
file); // ptr to FILE object
fwrite(&recordingNumber, // ptr
2, // size of each element
1, // count
file); // ptr to FILE object
diskWriteLock.exit();
}
void RecordNode::writeRecordMarker(FILE* file)
{
// write a 10-byte marker indicating the end of a record
diskWriteLock.enter();
fwrite(recordMarker, // ptr
1, // size of each element
10, // count
file); // ptr to FILE object
diskWriteLock.exit();
}
void RecordNode::writeEventBuffer(MidiMessage& event, int samplePosition) //, int node, int channel)
{
// find file and write samples to disk
// std::cout << "Received event!" << std::endl;
if (eventChannel->file == NULL)
return;
const uint8* dataptr = event.getRawData();
if (event.getNoteNumber() > 0) // processor ID > 0
{
uint64 samplePos = (uint64) samplePosition;
int64 eventTimestamp = timestamp + samplePos; // add the sample position to the buffer timestamp
diskWriteLock.enter();
fwrite(&eventTimestamp, // ptr
8, // size of each element
1, // count
eventChannel->file); // ptr to FILE object
fwrite(&samplePos, // ptr
2, // size of each element
1, // count
eventChannel->file); // ptr to FILE object
// write 1st four bytes of event (type, nodeId, eventId, eventChannel)
fwrite(dataptr, 1, 4, eventChannel->file);
// write recording number
fwrite(&recordingNumber, // ptr
2, // size of each element
1, // count
eventChannel->file); // ptr to FILE object
diskWriteLock.exit();
}
}
void RecordNode::handleEvent(int eventType, MidiMessage& event, int samplePosition) void RecordNode::handleEvent(int eventType, MidiMessage& event, int samplePosition)
{ {
if (eventType == TTL) if (eventType == TTL)
{ {
writeEventBuffer(event, samplePosition); EVERY_ENGINE->writeEvent(event, samplePosition);
} }
else if (eventType == TIMESTAMP) else if (eventType == TIMESTAMP)
{ {
...@@ -781,16 +393,6 @@ void RecordNode::process(AudioSampleBuffer& buffer, ...@@ -781,16 +393,6 @@ void RecordNode::process(AudioSampleBuffer& buffer,
int& nSamples) int& nSamples)
{ {
// TERMINOLOGY:
// buffer -- incoming data stored in AudioSampleBuffer (nSamples long)
// block -- 1024-sample sequence for disk writing (BLOCK_LENGTH long)
// samplesWritten -- number of samples written from the current buffer
// blockIndex -- index within the current block (used outside this function)
// numSamplesToWrite -- number of unwritten samples from the buffer
// CONSTRAINTS:
// samplesWritten must equal nSamples by the end of the process() method
if (isRecording && allFilesOpened) if (isRecording && allFilesOpened)
{ {
...@@ -802,61 +404,7 @@ void RecordNode::process(AudioSampleBuffer& buffer, ...@@ -802,61 +404,7 @@ void RecordNode::process(AudioSampleBuffer& buffer,
if (channelPointers.size() > 0) if (channelPointers.size() > 0)
{ {
EVERY_ENGINE->writeData(buffer,nSamples,timestamp);
while (samplesWritten < nSamples) // there are still unwritten samples in the buffer
{
int numSamplesToWrite = nSamples - samplesWritten; // samples remaining in the buffer
if (blockIndex + numSamplesToWrite < BLOCK_LENGTH) // we still have space in this block
{
for (int i = 0; i < buffer.getNumChannels(); i++)
{
if (channelPointers[i]->getRecordState())
{
// write buffer to disk!
writeContinuousBuffer(buffer.getReadPointer(i,samplesWritten),
numSamplesToWrite,
i);
}
}
// update our variables
samplesWritten += numSamplesToWrite;
timestamp += numSamplesToWrite;
blockIndex += numSamplesToWrite;
}
else // there's not enough space left in this block for all remaining samples
{
numSamplesToWrite = BLOCK_LENGTH - blockIndex;
for (int i = 0; i < buffer.getNumChannels(); i++)
{
if (channelPointers[i]->getRecordState())
{
// write buffer to disk!
writeContinuousBuffer(buffer.getReadPointer(i,samplesWritten),
numSamplesToWrite,
i);
//std::cout << "Record channel " << i << std::endl;
}
}
// update our variables
samplesWritten += numSamplesToWrite;
timestamp += numSamplesToWrite;
blockIndex = 0; // back to the beginning of the block
}
}
} }
// std::cout << nSamples << " " << samplesWritten << " " << blockIndex << std::endl; // std::cout << nSamples << " " << samplesWritten << " " << blockIndex << std::endl;
...@@ -875,41 +423,12 @@ void RecordNode::process(AudioSampleBuffer& buffer, ...@@ -875,41 +423,12 @@ void RecordNode::process(AudioSampleBuffer& buffer,
} }
//HDF5 void RecordNode::registerProcessor(GenericProcessor* sourceNode)
void RecordNode::HDFOpenFiles()
{ {
int lastProc = -1; EVERY_ENGINE->registerProcessor(sourceNode);
int index=-1;
int count = 0;
KWDFile *file;
for (int i=0; i < channelPointers.size(); i++)
{
if (channelPointers[i]->getRecordState())
{
if (lastProc != channelPointers[i]->nodeId)
{
if (index > -1)
{
fileArray[index]->open();
fileArray[index]->startNewRecording(recordingNumber,count);
}
lastProc = channelPointers[i]->nodeId;
index++;
file = new KWDFile(channelPointers[i]->nodeId,rootFolder.getFullPathName() + rootFolder.separatorString);
fileArray.add(file);
count = 0;
}
channelPointers[i]->recordFileId=index;
count++;
}
}
if (index > -1) {
fileArray[index]->open();
fileArray[index]->startNewRecording(recordingNumber,count);
}
} }
void RecordNode::HDFCloseFiles() Channel* RecordNode::getDataChannel(int index)
{ {
fileArray.clear(true); return channelPointers[index];
} }
\ No newline at end of file
...@@ -30,9 +30,8 @@ ...@@ -30,9 +30,8 @@
#include "GenericProcessor.h" #include "GenericProcessor.h"
#include "Channel.h" #include "Channel.h"
#include "RecordEngine.h"
//HDF5
#include "HDF5Recording.h"
#define HEADER_SIZE 1024 #define HEADER_SIZE 1024
...@@ -73,11 +72,14 @@ public: ...@@ -73,11 +72,14 @@ public:
*/ */
void setParameter(int parameterIndex, float newValue); void setParameter(int parameterIndex, float newValue);
void registerProcessor(GenericProcessor* sourceNode);
void addInputChannel(GenericProcessor* sourceNode, int chan); void addInputChannel(GenericProcessor* sourceNode, int chan);
bool enable(); bool enable();
bool disable(); bool disable();
Channel* getDataChannel(int index);
/** Called by the ControlPanel to determine the amount of space /** Called by the ControlPanel to determine the amount of space
left in the current dataDirectory. left in the current dataDirectory.
*/ */
...@@ -105,16 +107,6 @@ public: ...@@ -105,16 +107,6 @@ public:
*/ */
void createNewDirectory(); void createNewDirectory();
/** Creates a new data file for each channel.
*/
void createNewFiles();
/** Creates a new data file for each channel.
*/
void appendTrialNumber(bool);
void updateTrialNumber();
File getDataDirectory() File getDataDirectory()
{ {
return rootFolder; return rootFolder;
...@@ -129,9 +121,6 @@ public: ...@@ -129,9 +121,6 @@ public:
/** Generate a Matlab-compatible datestring */ /** Generate a Matlab-compatible datestring */
String generateDateString(); String generateDateString();
CriticalSection* getLock() {return &diskWriteLock;}
private: private:
/** Keep the RecordNode informed of acquisition and record states. /** Keep the RecordNode informed of acquisition and record states.
...@@ -147,25 +136,11 @@ private: ...@@ -147,25 +136,11 @@ private:
*/ */
File rootFolder; File rootFolder;
/** Holds data that has been converted from float to int16 before
saving.
*/
int16* continuousDataIntegerBuffer;
/** Holds data that has been converted from float to int16 before
saving.
*/
float* continuousDataFloatBuffer;
AudioSampleBuffer zeroBuffer;
/** Integer timestamp saved for each buffer. /** Integer timestamp saved for each buffer.
*/ */
int64 timestamp; int64 timestamp;
/** Integer to keep track of the number samples written in each block */
int blockIndex;
/** Integer to keep track of number of recording sessions in the same file */ /** Integer to keep track of number of recording sessions in the same file */
uint16 recordingNumber; uint16 recordingNumber;
...@@ -173,12 +148,6 @@ private: ...@@ -173,12 +148,6 @@ private:
*/ */
Time timer; Time timer;
/** Opens a single file */
void openFile(Channel* ch);
/** Closes a single file */
void closeFile(Channel* ch);
/** Closes all open files after recording has finished. /** Closes all open files after recording has finished.
*/ */
void closeAllFiles(); void closeAllFiles();
...@@ -189,47 +158,15 @@ private: ...@@ -189,47 +158,15 @@ private:
/** Pointers to all event channels */ /** Pointers to all event channels */
Array<Channel*> eventChannelPointers; Array<Channel*> eventChannelPointers;
/** Generates a header for a given channel */
String generateHeader(Channel* ch);
/** Generates a default directory name, based on the current date and time */ /** Generates a default directory name, based on the current date and time */
String generateDirectoryName(); String generateDirectoryName();
/** Generate filename for a given channel */
void updateFileName(Channel* ch);
/** Cycle through the event buffer, looking for data to save */ /** Cycle through the event buffer, looking for data to save */
void handleEvent(int eventType, MidiMessage& event, int samplePos); void handleEvent(int eventType, MidiMessage& event, int samplePos);
/** Object for holding information about the events file */ /**RecordEngines loaded**/
Channel* eventChannel; OwnedArray<RecordEngine> engineArray;
/** Method for writing continuous buffers to disk.
*/
void writeContinuousBuffer(const float* data, int nSamples, int channel);
/** Method for writing event buffers to disk.
*/
void writeEventBuffer(MidiMessage& event, int samplePos);
void writeRecordMarker(FILE*);
void writeTimestampAndSampleCount(FILE*);
/** Used to indicate the end of each record */
char* recordMarker;
//HDF5
void HDFOpenFiles();
void HDFCloseFiles();
CriticalSection diskWriteLock;
bool appendTrialNum;
int trialNum;
//HDF5
OwnedArray<KWDFile> fileArray;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(RecordNode); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(RecordNode);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment