@@ -1,6 +1,6 @@ | |||||
/* Graph Sort | /* Graph Sort | ||||
* Copyleft (C) 2002 David Griffiths <dave@pawfal.org> | * Copyleft (C) 2002 David Griffiths <dave@pawfal.org> | ||||
* | |||||
* | |||||
* This program is free software; you can redistribute it and/or modify | * 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 | * it under the terms of the GNU General Public License as published by | ||||
* the Free Software Foundation; either version 2 of the License, or | * the Free Software Foundation; either version 2 of the License, or | ||||
@@ -23,8 +23,9 @@ | |||||
////////////////////////////////////////////////////////// | ////////////////////////////////////////////////////////// | ||||
GraphSort::GraphSort() | |||||
GraphSort::GraphSort(bool UseTestSort) | |||||
{ | { | ||||
m_UseTestSort=UseTestSort; | |||||
} | } | ||||
GraphSort::~GraphSort() | GraphSort::~GraphSort() | ||||
@@ -37,13 +38,118 @@ void GraphSort::Clear() | |||||
m_Graph.clear(); | m_Graph.clear(); | ||||
} | } | ||||
const list<int> &GraphSort::GetSortedList() | const list<int> &GraphSort::GetSortedList() | ||||
{ | { | ||||
return m_Sorted; | return m_Sorted; | ||||
} | } | ||||
void GraphSort::Sort() | void GraphSort::Sort() | ||||
{ | |||||
m_UseTestSort?TestSort():OrigSort(); | |||||
} | |||||
void GraphSort::TestSort() | |||||
{ | |||||
m_Sorted.clear(); | |||||
list<int> Candidates; | |||||
#ifdef GRAPHSORT_TRACE | |||||
cerr<<"finding seed candidates"<<endl; | |||||
#endif | |||||
for (map<int,Node>::iterator i=m_Graph.begin(); | |||||
i!=m_Graph.end(); i++) | |||||
{ | |||||
// all nodes need these vars reset | |||||
i->second.UnsatisfiedOutputs = i->second.Outputs.size(); | |||||
i->second.IsSorted = false; | |||||
if (i->second.Outputs.empty() || i->second.IsTerminal) | |||||
{ | |||||
// terminals and roots are seed candidates | |||||
Candidates.push_back(i->first); | |||||
i->second.IsCandidate=true; | |||||
#ifdef GRAPHSORT_TRACE | |||||
cerr<<i->first<<" is seed candidate"<<endl; | |||||
#endif | |||||
} | |||||
else | |||||
{ | |||||
i->second.IsCandidate = false; | |||||
} | |||||
} | |||||
while (!Candidates.empty()) | |||||
{ | |||||
int NodeToSort; | |||||
bool FoundNodeToSort=false; | |||||
// look for an ideal candidate | |||||
for (list<int>::iterator i = Candidates.begin(); | |||||
i!=Candidates.end() && !FoundNodeToSort; i++) | |||||
{ | |||||
if (!m_Graph[*i].UnsatisfiedOutputs) | |||||
{ | |||||
NodeToSort=*i; | |||||
FoundNodeToSort=true; | |||||
#ifdef GRAPHSORT_TRACE | |||||
cerr<<"sorted "<<NodeToSort<<" (ideal)"<<endl; | |||||
#endif | |||||
} | |||||
} | |||||
if (!FoundNodeToSort) | |||||
{ | |||||
// The latest, ie closest to the outputs, feedback source is | |||||
// first on the candidate list. (There may be several equally | |||||
// late candidates, but the first will do fine in that case). | |||||
NodeToSort=*Candidates.begin(); | |||||
#ifdef GRAPHSORT_TRACE | |||||
cerr<<"sorted "<<NodeToSort<<" (feedback)"<<endl; | |||||
#endif | |||||
} | |||||
// put the chosen candidate on the sort list | |||||
Candidates.remove(NodeToSort); | |||||
m_Sorted.push_back(NodeToSort); | |||||
m_Graph[NodeToSort].IsCandidate=false; | |||||
m_Graph[NodeToSort].IsSorted=true; | |||||
// all nodes which fed the candidate... | |||||
for (list<int>::iterator i=m_Graph[NodeToSort].Inputs.begin(); | |||||
i!=m_Graph[NodeToSort].Inputs.end(); i++) | |||||
{ | |||||
// ...have another satisfied output... | |||||
m_Graph[*i].UnsatisfiedOutputs--; | |||||
if(!m_Graph[*i].IsCandidate && !m_Graph[*i].IsSorted) | |||||
{ | |||||
// ..and are promoted to candidate if they haven't been already | |||||
Candidates.push_back(*i); | |||||
m_Graph[*i].IsCandidate=true; | |||||
#ifdef GRAPHSORT_TRACE | |||||
cerr<<*i<<" is now a candidate"<<endl; | |||||
#endif | |||||
} | |||||
} | |||||
} | |||||
#ifdef GRAPHSORT_TRACE | |||||
for(list<int>::iterator i=m_Sorted.begin(); | |||||
i!=m_Sorted.end(); i++) | |||||
{ | |||||
cerr<<*i<<" "; | |||||
} | |||||
cerr<<endl; | |||||
#endif | |||||
} | |||||
void GraphSort::OrigSort() | |||||
{ | { | ||||
// walk back from all the roots | // walk back from all the roots | ||||
m_Sorted.clear(); | m_Sorted.clear(); | ||||
@@ -207,6 +313,7 @@ void GraphSort::RemoveConnection(int SID, int DID) | |||||
cerr<<"removed "<<DID<<endl; | cerr<<"removed "<<DID<<endl; | ||||
#endif | #endif | ||||
} | } | ||||
Sort(); | Sort(); | ||||
} | } | ||||
@@ -1,6 +1,6 @@ | |||||
/* Graph sort | /* Graph sort | ||||
* Copyleft (C) 2002 David Griffiths <dave@pawfal.org> | * Copyleft (C) 2002 David Griffiths <dave@pawfal.org> | ||||
* | |||||
* | |||||
* This program is free software; you can redistribute it and/or modify | * 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 | * it under the terms of the GNU General Public License as published by | ||||
* the Free Software Foundation; either version 2 of the License, or | * the Free Software Foundation; either version 2 of the License, or | ||||
@@ -25,15 +25,26 @@ | |||||
#ifndef GRAPH_SORT | #ifndef GRAPH_SORT | ||||
#define GRAPH_SORT | #define GRAPH_SORT | ||||
#define GRAPHSORT_USE_TEST_SORT_BY_DEFAULT | |||||
using namespace std; | using namespace std; | ||||
class GraphSort | class GraphSort | ||||
{ | { | ||||
public: | public: | ||||
GraphSort(); | |||||
#ifdef GRAPHSORT_USE_TEST_SORT_BY_DEFAULT | |||||
GraphSort(bool UseTestSort=true); | |||||
#else | |||||
GraphSort(bool UseTestSort=false); | |||||
#endif | |||||
~GraphSort(); | ~GraphSort(); | ||||
const list<int> &GetSortedList(); | const list<int> &GetSortedList(); | ||||
void Sort(); | void Sort(); | ||||
void TestSort(); | |||||
void OrigSort(); | |||||
void AddConnection(int SID, bool STerminal, int DID, bool DTerminal); | void AddConnection(int SID, bool STerminal, int DID, bool DTerminal); | ||||
void RemoveConnection(int SID, int DID); | void RemoveConnection(int SID, int DID); | ||||
void Clear(); | void Clear(); | ||||
@@ -44,13 +55,19 @@ public: | |||||
list<int> Inputs; | list<int> Inputs; | ||||
list<int> Outputs; | list<int> Outputs; | ||||
bool IsTerminal; | bool IsTerminal; | ||||
// temporaries used during sort | |||||
int UnsatisfiedOutputs; | |||||
bool IsCandidate; | |||||
bool IsSorted; | |||||
}; | }; | ||||
private: | private: | ||||
void RecursiveWalk(int node); | void RecursiveWalk(int node); | ||||
bool m_UseTestSort; | |||||
map<int,Node> m_Graph; | map<int,Node> m_Graph; | ||||
list<int> m_Sorted; | |||||
list<int> m_Sorted; | |||||
}; | }; | ||||
#endif | #endif | ||||
@@ -58,7 +58,8 @@ m_Move(0), | |||||
m_LastMove(0), | m_LastMove(0), | ||||
m_Snap(false), | m_Snap(false), | ||||
m_SnapDegrees(45), | m_SnapDegrees(45), | ||||
m_PosMarkerCount(0) | |||||
m_PosMarkerCount(0), | |||||
cb_Move(NULL) | |||||
{ | { | ||||
box(FL_NO_BOX); | box(FL_NO_BOX); | ||||
m_MidX=(w/2)+x; | m_MidX=(w/2)+x; | ||||
@@ -352,7 +353,7 @@ int Fl_Loop::handle(int event) | |||||
while (m_Move > m_Length) m_Move -= m_Length; | while (m_Move > m_Length) m_Move -= m_Length; | ||||
// do the move | // do the move | ||||
cb_Move(this,m_LastMove-m_Move); | |||||
if (cb_Move) cb_Move(this,m_LastMove-m_Move); | |||||
m_LastMove=m_Move; | m_LastMove=m_Move; | ||||
} | } | ||||
@@ -48,6 +48,7 @@ public: | |||||
bool Completed() {return (m_Count==m_Passes); } | bool Completed() {return (m_Count==m_Passes); } | ||||
float GetAngle() {return m_Angle;} | float GetAngle() {return m_Angle;} | ||||
void SetAngle(float s) {m_Angle=s;} | |||||
int GetLoop() {return m_Loop;} | int GetLoop() {return m_Loop;} | ||||
int GetPass() {return m_Passes;} | int GetPass() {return m_Passes;} | ||||
void SetSnap(bool s) {m_Snap=s;} | void SetSnap(bool s) {m_Snap=s;} | ||||
@@ -45,6 +45,13 @@ public: | |||||
SpiralLoopPlugin(); | SpiralLoopPlugin(); | ||||
virtual ~SpiralLoopPlugin(); | virtual ~SpiralLoopPlugin(); | ||||
struct TriggerInfo | |||||
{ | |||||
int Channel; | |||||
float Time; | |||||
bool Triggered; | |||||
}; | |||||
virtual PluginInfo &Initialise(const HostInfo *Host); | virtual PluginInfo &Initialise(const HostInfo *Host); | ||||
virtual SpiralGUIType *CreateGUI(); | virtual SpiralGUIType *CreateGUI(); | ||||
virtual void Execute(); | virtual void Execute(); | ||||
@@ -92,6 +99,7 @@ public: | |||||
const float GetVolume() { return m_Volume; } | const float GetVolume() { return m_Volume; } | ||||
const float GetCurrentAngle() { return m_LoopPoint?(m_Pos/m_LoopPoint)*360.0f:0; } | const float GetCurrentAngle() { return m_LoopPoint?(m_Pos/m_LoopPoint)*360.0f:0; } | ||||
const string& GetSampleName() { return m_Sample; } | const string& GetSampleName() { return m_Sample; } | ||||
vector<TriggerInfo> *GetTriggerVec() { return &m_TriggerVec; } | |||||
void Cut(int Start, int End); | void Cut(int Start, int End); | ||||
void Copy(int Start, int End); | void Copy(int Start, int End); | ||||
@@ -151,13 +159,6 @@ private: | |||||
char m_SampleBuffer[TRANSBUF_SIZE]; | char m_SampleBuffer[TRANSBUF_SIZE]; | ||||
long m_SampleSize; | long m_SampleSize; | ||||
struct TriggerInfo | |||||
{ | |||||
int Channel; | |||||
float Time; | |||||
bool Triggered; | |||||
}; | |||||
vector<TriggerInfo> m_TriggerVec; | vector<TriggerInfo> m_TriggerVec; | ||||
@@ -229,8 +229,36 @@ void SpiralLoopPluginGUI::UpdateValues(SpiralPlugin *o) | |||||
m_Volume->value(Plugin->GetVolume()); | m_Volume->value(Plugin->GetVolume()); | ||||
m_Speed->value(Plugin->GetSpeed()); | m_Speed->value(Plugin->GetSpeed()); | ||||
m_Length->value(Plugin->GetLoopLength()/m_SampleSize); | |||||
m_LoopGUI->SetLength(Plugin->GetLoopLength()); | |||||
if(m_SampleSize!=0) | |||||
{ | |||||
m_Length->value(Plugin->GetLoopLength()/m_SampleSize); | |||||
m_LoopGUI->SetLength(Plugin->GetLoopLength()); | |||||
} | |||||
else | |||||
{ | |||||
m_LoopGUI->SetLength(0); | |||||
} | |||||
vector<SpiralLoopPlugin::TriggerInfo> *TrigVec=Plugin->GetTriggerVec(); | |||||
int ID=0; | |||||
for (vector<SpiralLoopPlugin::TriggerInfo>::iterator i=TrigVec->begin(); | |||||
i!=TrigVec->end(); i++) | |||||
{ | |||||
Fl_Trigger *NewTrigger = new Fl_Trigger(parent()->x(), parent()->y(), 20, 20); | |||||
NewTrigger->SetCentreX(150); | |||||
NewTrigger->SetCentreY(150); | |||||
NewTrigger->SetCentreRadius(125); | |||||
if(m_SampleSize!=0) NewTrigger->SetAngle(i->Time*360.0f); | |||||
NewTrigger->SetID(ID); | |||||
NewTrigger->SetChannel(i->Channel); | |||||
NewTrigger->callback((Fl_Callback*)cb_Trigger); | |||||
m_LoopGUI->add(NewTrigger); | |||||
m_TriggerVec.push_back(NewTrigger); | |||||
NewTrigger->redraw(); | |||||
m_LoopGUI->redraw(); | |||||
ID++; | |||||
} | |||||
} | } | ||||
void SpiralLoopPluginGUI::Update() | void SpiralLoopPluginGUI::Update() | ||||
@@ -360,7 +388,8 @@ inline void SpiralLoopPluginGUI::cb_Trig_i(Fl_Button* o, void* v) | |||||
m_LoopGUI->add(NewTrigger); | m_LoopGUI->add(NewTrigger); | ||||
m_TriggerVec.push_back(NewTrigger); | m_TriggerVec.push_back(NewTrigger); | ||||
NewTrigger->redraw(); | NewTrigger->redraw(); | ||||
m_LoopGUI->redraw(); | |||||
m_GUICH->Set("Start",NewTrigger->GetID()); | m_GUICH->Set("Start",NewTrigger->GetID()); | ||||
m_GUICH->Set("End",NewTrigger->GetChannel()); | m_GUICH->Set("End",NewTrigger->GetChannel()); | ||||
m_GUICH->Set("Length",0); | m_GUICH->Set("Length",0); | ||||
@@ -104,6 +104,8 @@ void audioloop(void* o) | |||||
#include <libgen.h> | #include <libgen.h> | ||||
#endif | #endif | ||||
#include "GraphSort.h" | |||||
int main(int argc, char **argv) | int main(int argc, char **argv) | ||||
{ | { | ||||
#if __APPLE__ | #if __APPLE__ | ||||
@@ -211,6 +213,7 @@ int main(int argc, char **argv) | |||||
//pthread_cancel(loopthread); | //pthread_cancel(loopthread); | ||||
delete synth; | delete synth; | ||||
return 1; | return 1; | ||||
} | } | ||||