Skip to content
Snippets Groups Projects
Commit fcd98020 authored by jsiegle's avatar jsiegle
Browse files

Switching to channel-based settings

parent 030c143f
No related branches found
No related tags found
No related merge requests found
......@@ -31,11 +31,11 @@ AudioNode::AudioNode()
settings.numInputs = 128;
settings.numOutputs = 2;
// 64 inputs, 2 outputs (left and right channel)
// 128 inputs, 2 outputs (left and right channel)
setPlayConfigDetails(getNumInputs(),getNumOutputs(),44100.0,128);
leftChan.clear();
rightChan.clear();
//leftChan.clear();
//rightChan.clear();
nextAvailableChannel = 2; // keep first two channels empty
......@@ -60,6 +60,16 @@ AudioProcessorEditor* AudioNode::createEditor()
}
void AudioNode::resetConnections()
{
nextAvailableChannel = 2; // start connections at channel 2
wasConnected = false;
channelPointers.clear();
}
void AudioNode::setChannelStatus(int chan, bool status)
{
......@@ -87,29 +97,50 @@ void AudioNode::enableCurrentChannel(bool state)
}
}
void AudioNode::addInputChannel(GenericProcessor* sourceNode, int chan)
{
if (chan != getProcessorGraph()->midiChannelIndex)
{
int channelIndex = getNextChannel(false);
setPlayConfigDetails(channelIndex+1,0,44100.0,128);
channelPointers.add(sourceNode->channels[chan]);
} else {
// Can't monitor events at the moment!
}
}
void AudioNode::setParameter (int parameterIndex, float newValue)
{
// change left channel, right channel, or volume
if (parameterIndex == 1)
{
// volume level
// volume level
volume = newValue*0.00001f;
} else if (parameterIndex == 100)
{
// add current channel
if (!leftChan.contains(currentChannel))
{
leftChan.add(currentChannel);
rightChan.add(currentChannel);
}
// if (!leftChan.contains(currentChannel))
// {
// leftChan.add(currentChannel);
// rightChan.add(currentChannel);
// }
} else if (parameterIndex == -100)
{
// remove current channel
if (leftChan.contains(currentChannel))
{
leftChan.remove(leftChan.indexOf(currentChannel));
rightChan.remove(rightChan.indexOf(currentChannel));
}
// if (leftChan.contains(currentChannel))
// {
// leftChan.remove(leftChan.indexOf(currentChannel));
// rightChan.remove(rightChan.indexOf(currentChannel));
// }
}
}
......@@ -121,34 +152,35 @@ void AudioNode::process(AudioSampleBuffer &buffer,
//std::cout << "Audio node sample count: " << nSamples << std::endl; ///buffer.getNumSamples() << std::endl;
// clear the left and right channels
buffer.clear(0,0,buffer.getNumSamples());
buffer.clear(1,0,buffer.getNumSamples());
for (int n = 0; n < leftChan.size(); n++)
for (int i = 2; i < buffer.getNumChannels(); i++)
{
buffer.addFrom(0, // destination channel
0, // destination start sample
if (channelPointers[i-2]->isMonitored)
{
buffer.addFrom(0, // destination channel
0, // destination start sample
buffer, // source
leftChan[n], // source channel
i, // source channel
0, // source start sample
buffer.getNumSamples(), // number of samples
volume // gain to apply
);
}
for (int n = 0; n < rightChan.size(); n++)
{
buffer.addFrom(1, // destination channel
0, // destination start sample
buffer.addFrom(1, // destination channel
0, // destination start sample
buffer, // source
rightChan[n], // source channel
i, // source channel
0, // source start sample
buffer.getNumSamples(), // number of samples
volume // gain to apply
);
}
}
}
......@@ -48,24 +48,32 @@ class AudioNode : public GenericProcessor
{
public:
// real member functions:
AudioNode();
~AudioNode();
/** Handle incoming data and decide which channels to monitor
*/
void process(AudioSampleBuffer &buffer, MidiBuffer &midiMessages, int& nSamples);
/** Overrides implementation in GenericProcessor; used to change audio monitoring
parameters on the fly.
*/
void setParameter (int parameterIndex, float newValue);
AudioProcessorEditor* createEditor();
void setChannelStatus(int, bool);
// bool isAudioOrRecordNode() {return true;}
void resetConnections();
void enableCurrentChannel(bool);
// AudioEditor* getEditor() {return audioEditor;}
void addInputChannel(GenericProcessor* source, int chan);
// AudioEditor* getEditor() {return audioEditor;}
ScopedPointer<AudioEditor> audioEditor;
ScopedPointer<AudioEditor> audioEditor;
private:
......@@ -73,6 +81,8 @@ private:
Array<int> rightChan;
float volume;
Array<Channel*> audioChannels;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioNode);
};
......
......@@ -34,6 +34,19 @@ Channel::Channel(GenericProcessor* p, int n) :
createDefaultName();
}
Channel::Channel(const Channel& ch)
{
processor = ch.processor;
isEventChannel = ch.isEventChannel;
isEnabled = ch.isEnabled;
isRecording = false;
isMonitored = false;
sampleRate = ch.sampleRate;
bitVolts = ch.bitVolts;
name = ch.name;
}
String Channel::getName()
{
return name;
......
......@@ -49,8 +49,12 @@ class Channel
{
public:
// Default constructor:
Channel(GenericProcessor* p, int n);
// Copy constructor:
Channel(const Channel& ch);
String getName();
void reset();
......@@ -66,11 +70,15 @@ public:
// pointer to parent processor:
GenericProcessor* processor;
// crucial information:
float sampleRate;
float bitVolts;
// file info (for disk writing):
String filename;
FILE* file;
private:
......
......@@ -127,10 +127,7 @@ int GenericProcessor::getNextChannel(bool increment)
void GenericProcessor::resetConnections()
{
//std::cout << "Resetting connections" << std::endl;
// if (isAudioOrRecordNode())
// nextAvailableChannel = 2;
// else
nextAvailableChannel = 0;
wasConnected = false;
......@@ -206,8 +203,7 @@ void GenericProcessor::setSourceNode(GenericProcessor* sn)
sourceNode = sn;
sn->setDestNode(this);
//setNumInputs(sn->getNumOutputs());
//setSampleRate(sn->getSampleRate());
} else {
// std::cout << " The source node is not new." << std::endl;
}
......@@ -258,8 +254,7 @@ void GenericProcessor::setDestNode(GenericProcessor* dn)
destNode = dn;
dn->setSourceNode(this);
//dn->setNumInputs(getNumOutputs());
//dn->setSampleRate(getSampleRate());
} else {
// std::cout << " The dest node is not new." << std::endl;
}
......@@ -306,22 +301,31 @@ void GenericProcessor::update()
settings.numInputs = settings.numOutputs;
settings.numOutputs = settings.numInputs;
for (int i = 0; i < getNumInputs(); i++)
{
Channel* sourceChan = sourceNode->channels[i];
Channel* ch = new Channel(*sourceChan);
channels.add(ch);
}
} else {
settings.sampleRate = getDefaultSampleRate();
settings.numOutputs = getDefaultNumOutputs();
for (int i = 0; i < getNumOutputs(); i++)
settings.bitVolts.add(getDefaultBitVolts());
{
Channel* ch = new Channel(this, i);
ch->sampleRate = getDefaultSampleRate();
ch->bitVolts = getDefaultBitVolts();
generateDefaultChannelNames(settings.outputChannelNames);
channels.add(ch);
}
}
if (this->isSink())
{
settings.numOutputs = 0;
settings.outputChannelNames.clear();
}
updateSettings(); // custom settings code
......@@ -337,21 +341,21 @@ void GenericProcessor::update()
}
bool GenericProcessor::recordStatus(int chan)
{
// bool GenericProcessor::recordStatus(int chan)
// {
return getEditor()->getRecordStatus(chan);//recordChannels[chan];
// return getEditor()->getRecordStatus(chan);//recordChannels[chan];
}
// }
bool GenericProcessor::audioStatus(int chan)
{
// bool GenericProcessor::audioStatus(int chan)
// {
return getEditor()->getAudioStatus(chan);//recordChannels[chan];
// return getEditor()->getAudioStatus(chan);//recordChannels[chan];
}
// }
// void GenericProcessor::generateDefaultChannelNames(StringArray& names)
// {
......
......@@ -216,33 +216,19 @@ public:
virtual GenericEditor* getEditor() {return editor;}
ScopedPointer<GenericEditor> editor;
GenericProcessor* originalSource;
OwnedArray<Channel*> channels;
OwnedArray<Channel*> eventChannels;
int numInputs;
int numOutputs;
// OBSOLETE PROCESSOR SETTINGS:
// struct ProcessorSettings {
// GenericProcessor* originalSource;
// int numInputs;
// int numOutputs;
// StringArray inputChannelNames;
// StringArray outputChannelNames;
struct ProcessorSettings {
// float sampleRate;
// Array<float> bitVolts;
GenericProcessor* originalSource;
// Array<int> eventChannelIds;
// StringArray eventChannelNames;
// Array<int> eventChannelTypes;
int numInputs;
int numOutputs;
// };
};
//ProcessorSettings settings;
ProcessorSettings settings;
//virtual bool isAudioOrRecordNode() {return false;}
......
......@@ -257,8 +257,7 @@ void ProcessorGraph::updateConnections(Array<SignalChainTabButton*, CriticalSect
{
std::cout << " Connecting to audio and record nodes." << std::endl;
source->setStartChannel(getAudioNode()->getNextChannel(false));
//source->setStartChannel(getAudioNode()->getNextChannel(false));
for (int chan = 0; chan < source->getNumOutputs(); chan++) {
......@@ -273,7 +272,7 @@ void ProcessorGraph::updateConnections(Array<SignalChainTabButton*, CriticalSect
addConnection(source->getNodeId(), // sourceNodeID
chan, // sourceNodeChannelIndex
AUDIO_NODE_ID, // destNodeID
getAudioNode()->getNextChannel(true) + 2); // destNodeChannelIndex
getAudioNode()->getNextChannel(true)); // destNodeChannelIndex
// add 2 to account for 2 output channels
......
......@@ -90,8 +90,8 @@ void RecordNode::resetConnections()
nextAvailableChannel = 0;
wasConnected = false;
continuousChannels.clear();
eventChannels.clear();
channelPointers.clear();
eventChannelPointers.clear();
}
void RecordNode::filenameComponentChanged(FilenameComponent* fnc)
......@@ -116,68 +116,45 @@ void RecordNode::addInputChannel(GenericProcessor* sourceNode, int chan)
if (chan != getProcessorGraph()->midiChannelIndex)
{
setPlayConfigDetails(getNextChannel(false)+1,0,44100.0,128);
Channel newChannel;
int channelIndex = getNextChannel(false);
std::cout << "Record node adding channel." << std::endl;
setPlayConfigDetails(channelIndex+1,0,44100.0,128);
newChannel.nodeId = sourceNode->getNodeId();
newChannel.chan = chan;
newChannel.name = sourceNode->getOutputChannelName(chan);
newChannel.isRecording = sourceNode->recordStatus(chan);
channelPointers.add(sourceNode->channelPointers[chan]);
String filename = rootFolder.getFullPathName();
String filename = rootFolder.getFullPathName();
filename += "/";
filename += newChannel.nodeId;
filename += sourceNode->getNodeId();
filename += "_";
filename += newChannel.name;
filename += channelPointers[channelIndex]->name;
filename += ".continuous";
newChannel.filename = filename;
newChannel.file = 0;
channelPointers[channelIndex]->filename = filename;
channelPointers[channelIndex]->file = 0;
if (newChannel.isRecording)
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::pair<int, Channel> newPair (getNextChannel(false), newChannel);
//std::cout << "adding channel " << getNextChannel(false) << std::endl;
continuousChannels.insert(newPair);
//continuouschannelPointers.insert(newPair);
} else {
std::map<int, Channel> eventChans;
int ID = sourceNode->getNodeId();
for (int n = 0; n < sourceNode->settings.eventChannelIds.size(); n++)
for (int n = 0; n < sourceNode->eventChannels.size(); n++)
{
Channel newChannel;
newChannel.nodeId = ID;
newChannel.chan = sourceNode->settings.eventChannelIds[n];
newChannel.name = sourceNode->settings.eventChannelNames[n];
newChannel.isRecording = true;
newChannel.file = 0;
std::pair<int, Channel> newPair (newChannel.chan, newChannel);
eventChans.insert(newPair);
eventChannelPointers.add(sourceNode->eventChannels[n]);
}
std::pair<int, std::map<int, Channel> > newPair (ID, eventChans);
eventChannels.insert(newPair);
}
}
......@@ -232,21 +209,21 @@ void RecordNode::setParameter (int parameterIndex, float newValue)
rootFolder.createDirectory();
// create / open necessary files
for (int i = 0; i < continuousChannels.size(); i++)
for (int i = 0; i < channelPointers.size(); i++)
{
if (continuousChannels[i].isRecording)
if (channelPointers[i]->isRecording)
{
std::cout << "OPENING FILE: " << continuousChannels[i].filename << std::endl;
std::cout << "OPENING FILE: " << channelPointers[i]->filename << std::endl;
File f = File(continuousChannels[i].filename);
File f = File(channelPointers[i]->filename);
continuousChannels[i].file = fopen(continuousChannels[i].filename.toUTF8(), "a+b");
channelPointers[i]->file = fopen(channelPointers[i]->filename.toUTF8(), "a+b");
if (!f.exists())
{
// create header (needs more details, obviously)
String header = "THIS IS A HEADER.";
fwrite(header.toUTF8(), 1, header.getNumBytesAsUTF8(), continuousChannels[i].file);
fwrite(header.toUTF8(), 1, header.getNumBytesAsUTF8(), channelPointers[i]->file);
}
}
......@@ -275,21 +252,21 @@ void RecordNode::setParameter (int parameterIndex, float newValue)
std::cout << "Toggling channel " << currentChannel << std::endl;
if (newValue == 0.0f) {
continuousChannels[currentChannel].isRecording = false;
channelPointers[currentChannel]->isRecording = false;
if (isRecording) {
std::cout << "CLOSING FILE: " << continuousChannels[currentChannel].filename << std::endl;
fclose(continuousChannels[currentChannel].file);
std::cout << "CLOSING FILE: " << channelPointers[currentChannel]->filename << std::endl;
fclose(channelPointers[currentChannel]->file);
}
}
else {
continuousChannels[currentChannel].isRecording = true;
channelPointers[currentChannel]->isRecording = true;
if (isRecording) {
std::cout << "OPENING FILE: " << continuousChannels[currentChannel].filename << std::endl;
continuousChannels[currentChannel].file =
fopen(continuousChannels[currentChannel].filename.toUTF8(), "a+b");
std::cout << "OPENING FILE: " << channelPointers[currentChannel]->filename << std::endl;
channelPointers[currentChannel]->file =
fopen(channelPointers[currentChannel]->filename.toUTF8(), "a+b");
}
}
}
......@@ -299,12 +276,12 @@ void RecordNode::setParameter (int parameterIndex, float newValue)
void RecordNode::closeAllFiles()
{
for (int i = 0; i < continuousChannels.size(); i++)
for (int i = 0; i < channelPointers.size(); i++)
{
if (continuousChannels[i].isRecording)
if (channelPointers[i]->isRecording)
{
std::cout << "CLOSING FILE: " << continuousChannels[i].filename << std::endl;
fclose(continuousChannels[i].file);
std::cout << "CLOSING FILE: " << channelPointers[i]->filename << std::endl;
fclose(channelPointers[i]->file);
}
}
}
......@@ -350,17 +327,17 @@ void RecordNode::writeContinuousBuffer(float* data, int nSamples, int channel)
fwrite(&timestamp, // ptr
8, // size of each element
1, // count
continuousChannels[channel].file); // ptr to FILE object
channelPointers[channel]->file); // ptr to FILE object
fwrite(&nSamples, // ptr
sizeof(nSamples), // size of each element
1, // count
continuousChannels[channel].file); // ptr to FILE object
channelPointers[channel]->file); // ptr to FILE object
int n = fwrite(continuousDataIntegerBuffer, // ptr
2, // size of each element
nSamples, // count
continuousChannels[channel].file); // ptr to FILE object
channelPointers[channel]->file); // ptr to FILE object
// n must equal "count", otherwise there was an error
}
......@@ -393,7 +370,7 @@ void RecordNode::process(AudioSampleBuffer &buffer,
for (int i = 0; i < buffer.getNumChannels(); i++)
{
if (continuousChannels[i].isRecording)
if (channelPointers[i]->isRecording)
{
// write buffer to disk!
writeContinuousBuffer(buffer.getSampleData(i),
......
......@@ -92,10 +92,6 @@ public:
*/
void resetConnections();
/** Overrides implementation by GenericProcessor.
*/
// bool isAudioOrRecordNode() {return true;}
/** Callback to indicate when user has chosen a new data directory.
*/
void filenameComponentChanged(FilenameComponent*);
......@@ -140,27 +136,31 @@ private:
/** Holds information for a given channel to be recorded to
its own file.
*/
struct Channel
{
int nodeId;
int chan;
String name;
bool isRecording;
String filename;
FILE* file;
};
// struct Channel
// {
// int nodeId;
// int chan;
// String name;
// bool isRecording;
// String filename;
// FILE* file;
// };
/** Closes all open files after recording has finished.
*/
void closeAllFiles();
Array<Channel*> channelPointers;
Array<Channel*> eventChannelPointers;
/** Map of continuous channels.
*/
std::map<int, Channel> continuousChannels;
//std::map<int, Channel> continuousChannels;
/** Map of event channels.
*/
std::map<int, std::map<int,Channel> > eventChannels;
//std::map<int, std::map<int,Channel> > eventChannels;
/** Method for writing continuous buffers to disk.
*/
......
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