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