void OriginalRecording::writeData(AudioSampleBuffer& buffer, int nSamples) { int samplesWritten = 0; 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 (getChannel(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 (getChannel(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 } } }
void RecordNode::process(AudioSampleBuffer& buffer, MidiBuffer& events, int& nSamples) { //std::cout << "Record node processing block." << std::endl; //std::cout << "Num channels: " << buffer.getNumChannels() << std::endl; if (isRecording) { //timestamp = timer.getHighResolutionTicks(); // WHY IS THIS AFFECTING THE LFP DISPLAY? //buffer.applyGain(0, nSamples, 5.2438f); // cycle through events -- extract the TTLs and the timestamps checkForEvents(events); // cycle through buffer channels if (channelPointers.size() > 0) { for (int i = 0; i < buffer.getNumChannels(); i++) { if (channelPointers[i]->isRecording) { // write buffer to disk! writeContinuousBuffer(buffer.getSampleData(i), nSamples, i); //std::cout << "Record channel " << i << std::endl; } } } return; } // this is intended to prevent parameter changes from closing files // before recording stops if (signalFilesShouldClose) { closeAllFiles(); signalFilesShouldClose = false; } }
void OriginalRecording::closeFiles() { for (int i = 0; i < fileArray.size(); i++) { if (fileArray[i] != nullptr) { if (blockIndex < BLOCK_LENGTH) { // fill out the rest of the current buffer writeContinuousBuffer(zeroBuffer.getReadPointer(0), BLOCK_LENGTH - blockIndex, i); diskWriteLock.enter(); fclose(fileArray[i]); fileArray.set(i,nullptr); diskWriteLock.exit(); } } } for (int i = 0; i < spikeFileArray.size(); i++) { if (spikeFileArray[i] != nullptr) { diskWriteLock.enter(); fclose(spikeFileArray[i]); spikeFileArray.set(i,nullptr); diskWriteLock.exit(); } } if (eventFile != nullptr) { diskWriteLock.enter(); fclose(eventFile); eventFile = nullptr; diskWriteLock.exit(); } if (messageFile != nullptr) { diskWriteLock.enter(); fclose(messageFile); messageFile = nullptr; diskWriteLock.exit(); } writeXml(); blockIndex = 0; }
void RecordNode::closeAllFiles() { for (int i = 0; i < channelPointers.size(); i++) { if (channelPointers[i]->getRecordState()) { if (blockIndex < BLOCK_LENGTH) { // fill out the rest of the current buffer writeContinuousBuffer(zeroBuffer.getSampleData(0), BLOCK_LENGTH - blockIndex, i); } closeFile(channelPointers[i]); } } closeFile(eventChannel); blockIndex = 0; // back to the beginning of the block }
void RecordNode::process(AudioSampleBuffer& buffer, MidiBuffer& events, 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) { // FIRST: cycle through events -- extract the TTLs and the timestamps checkForEvents(events); // SECOND: cycle through buffer channels int samplesWritten = 0; if (channelPointers.size() > 0) { 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; return; } // this is intended to prevent parameter changes from closing files // before recording stops if (signalFilesShouldClose) { closeAllFiles(); signalFilesShouldClose = false; } }
void RecordNode::setParameter(int parameterIndex, float newValue) { //editor->updateParameterButtons(parameterIndex); // 0 = stop recording // 1 = start recording // 2 = toggle individual channel (0.0f = OFF, anything else = ON) if (parameterIndex == 1) { isRecording = true; // std::cout << "START RECORDING." << std::endl; if (newDirectoryNeeded) { createNewDirectory(); recordingNumber = 0; } else { recordingNumber++; // increment recording number within this directory } if (!rootFolder.exists()) { rootFolder.createDirectory(); String settingsFileName = rootFolder.getFullPathName() + File::separator + "settings.xml"; getEditorViewport()->saveState(File(settingsFileName)); } createNewFiles(); openFile(eventChannel); 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; } else if (parameterIndex == 0) { // std::cout << "STOP RECORDING." << std::endl; if (isRecording) { // close necessary files signalFilesShouldClose = true; } isRecording = false; } else if (parameterIndex == 2) { if (isProcessing) { std::cout << "Toggling channel " << currentChannel << std::endl; if (newValue == 0.0f) { 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 { 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); } } } } } }