Index: Flow/Networks/BackEnds/JACKNetworkPlayer.cxx =================================================================== --- Flow/Networks/BackEnds/JACKNetworkPlayer.cxx (revision 13145) +++ Flow/Networks/BackEnds/JACKNetworkPlayer.cxx (working copy) @@ -1,8 +1,11 @@ #include "JACKNetworkPlayer.hxx" #include "PushFlowControl.hxx" +#include "AudioSource.hxx" +#include "AudioSink.hxx" #include + namespace CLAM { @@ -86,55 +89,79 @@ void JACKNetworkPlayer::RegisterInputPorts(const Network& net) { - Network::AudioSources sources=net.getOrderedSources(); CLAM_ASSERT( _sourceJackBindings.empty(), "JACKNetworkPlayer::RegisterInputPorts() : there are already registered input ports"); - SourceJackBinding pair; //Get them from the Network and add it to local list for (Network::AudioSources::const_iterator it=sources.begin(); it!=sources.end(); it++) { - //Get Processing address - pair.source=*it; - pair.source->SetFrameAndHopSize(_jackBufferSize); + std::string processingName = net.GetNetworkId(*it); - //Register port on the JACK server - const std::string & processingName = net.GetNetworkId(*it); - pair.jackPort=jack_port_register (_jackClient, - processingName.c_str(), - JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); + AudioSource::Ports ports = (*it)->GetPorts(); + for(unsigned port = 0; port < ports.size(); ++port) + { + //Get Processing address + SourceJackBinding pair; + pair.source=*it; + pair.source->SetFrameAndHopSize(_jackBufferSize, port); - //Add the pair (jack port, clam jack receiver) to the list - _sourceJackBindings.push_back(pair); + //Register port on the JACK server + std::stringstream portName; + if (ports.size() == 1) + portName << processingName << "." << ports[port].mAudioOut->GetName(); + else + portName << processingName << "_" << port; + + pair.jackPort = jack_port_register(_jackClient, portName.str().c_str(), + JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); + + // the index is used when there are more ports in an audiosource + // to decide which port should receive the data + pair.port = port; + + //Add the pair (jack port, clam jack receiver) to the list + _sourceJackBindings.push_back(pair); + } } } void JACKNetworkPlayer::RegisterOutputPorts(const Network& net) { - Network::AudioSinks sinks=net.getOrderedSinks(); CLAM_ASSERT( _sinkJackBindings.empty(), "JACKNetworkPlayer::RegisterOutputPorts() : there are already registered output ports"); - SinkJackBinding pair; - for (Network::AudioSinks::const_iterator it=sinks.begin(); it!=sinks.end(); it++) { - //Get Processing address - pair.sink=*it; - pair.sink->SetFrameAndHopSize(_jackBufferSize); + std::string processingName = net.GetNetworkId( *it ); - //Register port on the JACK server - const std::string & processingName = net.GetNetworkId( *it ); - pair.jackPort=jack_port_register (_jackClient, - processingName.c_str(), - JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); + CLAM::AudioSink::Ports ports = (*it)->GetPorts(); + for(unsigned port = 0; port < ports.size(); ++port) + { + //Get Processing address + SinkJackBinding pair; + pair.sink=*it; + pair.sink->SetFrameAndHopSize(_jackBufferSize, port); - //Add the pair (jack port, clam jack receiver) to the list - _sinkJackBindings.push_back(pair); + //Register port on the JACK server + std::stringstream portName; + if (ports.size() == 1) + portName << processingName; + else + portName << processingName << "_" << port; + + pair.jackPort=jack_port_register (_jackClient, portName.str().c_str(), + JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); + + pair.port = port; + + //Add the pair (jack port, clam jack receiver) to the list + _sinkJackBindings.push_back(pair); + } + } } @@ -161,7 +188,7 @@ } _sourceJackBindings.clear(); } - + void JACKNetworkPlayer::CopyJackBuffersToGenerators(const jack_nframes_t nframes) { for (SourceJackBindings::iterator it=_sourceJackBindings.begin(); it!=_sourceJackBindings.end(); it++) @@ -170,7 +197,7 @@ jack_default_audio_sample_t *jackInBuffer = (jack_default_audio_sample_t*) jack_port_get_buffer ( it->jackPort, nframes); //Tell the AudioSource where to look for data in its Do() - it->source->SetExternalBuffer( jackInBuffer, nframes ); + it->source->SetExternalBuffer( jackInBuffer, nframes, it->port); } } @@ -182,7 +209,7 @@ jack_default_audio_sample_t *jackOutBuffer = (jack_default_audio_sample_t*) jack_port_get_buffer ( it->jackPort, nframes); //Tell the AudioSource where to copy data consumed in its Do() - it->sink->SetExternalBuffer( jackOutBuffer, nframes); + it->sink->SetExternalBuffer( jackOutBuffer, nframes, it->port); } } Index: Flow/Networks/BackEnds/JACKNetworkPlayer.hxx =================================================================== --- Flow/Networks/BackEnds/JACKNetworkPlayer.hxx (revision 13145) +++ Flow/Networks/BackEnds/JACKNetworkPlayer.hxx (working copy) @@ -3,6 +3,7 @@ #include #include +#include #include "NetworkPlayer.hxx" #include "Network.hxx" #include @@ -21,7 +22,9 @@ } jack_port_t* jackPort; AudioSource* source; + unsigned port; }; + typedef std::vector SourceJackBindings; struct SinkJackBinding { @@ -31,15 +34,17 @@ } jack_port_t* jackPort; AudioSink* sink; + unsigned port; }; - typedef std::vector SourceJackBindings; typedef std::vector SinkJackBindings; + struct JackConnection { std::string processingName; const char ** outsideConnections; }; typedef std::list JackConnections; + private: int _jackSampleRate; int _jackBufferSize; @@ -58,6 +63,9 @@ jack_client_t * _jackClient; std::string _jackClientName; +private: + void AddSourceJackBinding(Network::AudioSources::const_iterator& it, std::string const& name, unsigned index); + public: JACKNetworkPlayer(const std::string & name="CLAM network player"); virtual ~JACKNetworkPlayer(); Index: Processing/AudioSource.cxx =================================================================== --- Processing/AudioSource.cxx (revision 13150) +++ Processing/AudioSource.cxx (working copy) @@ -4,7 +4,8 @@ namespace CLAM { -namespace Hidden + +namespace { static const char* metadata[] = { "key", "AudioSource", @@ -19,39 +20,72 @@ bool AudioSource::Do() { - CLAM::Audio& so=mOut.GetAudio(); - CLAM_DEBUG_ASSERT(!mFloatBuffer || !mDoubleBuffer, "AudioSource: Just one buffer should be set"); - CLAM_DEBUG_ASSERT(mFloatBuffer || mDoubleBuffer, "AudioSource: No external buffer set"); - CLAM_DEBUG_ASSERT(mBufferSize>0, "AudioSource: internal buffer size must be greater than 0"); - CLAM::TData * audioBuffer = so.GetBuffer().GetPtr(); - if (mFloatBuffer) - for (unsigned i=0; iGetAudio(); + CLAM_DEBUG_ASSERT(!port.mFloatBuffer || !port.mDoubleBuffer, "AudioSource: Just one buffer should be set"); + CLAM_DEBUG_ASSERT(port.mFloatBuffer || port.mDoubleBuffer, "AudioSource: No external buffer set"); + CLAM_DEBUG_ASSERT(port.mBufferSize>0, "AudioSource: internal buffer size must be greater than 0"); + CLAM::TData * audioBuffer = so.GetBuffer().GetPtr(); + if (port.mFloatBuffer) + for (unsigned i=0; iGetSize(); i++) + audioBuffer[i] = 0.; + out->Produce(); + } return true; } +void AudioSource::SetExternalBuffer(const float* buf, unsigned nframes, unsigned index) +{ + CLAM_ASSERT(index < _ports.size(), "AudioOutPort index out of range"); + Port& port = _ports[index]; + port.mAudioOut->SetSize(nframes); + port.mAudioOut->SetHop(nframes); + port.mFloatBuffer = buf; + port.mBufferSize = nframes; + port.mDoubleBuffer = 0; +} + +void AudioSource::SetExternalBuffer(const double* buf, unsigned nframes, unsigned index) +{ + CLAM_ASSERT(index < _ports.size(), "AudioOutPort index out of range"); + Port& port = _ports[index]; + port.mAudioOut->SetSize(nframes); + port.mAudioOut->SetHop(nframes); + port.mDoubleBuffer = buf; + port.mBufferSize = nframes; + port.mFloatBuffer = 0; +} + void AudioSource::SetExternalBuffer(const float* buf, unsigned nframes) { - mFloatBuffer = buf; - mBufferSize = nframes; - mDoubleBuffer = 0; - mOut.SetSize(nframes); - mOut.SetHop(nframes); + CLAM_ASSERT(1 == _ports.size(), "AudioOutPort index out of range"); + Port& port = _ports[0]; + port.mAudioOut->SetSize(nframes); + port.mAudioOut->SetHop(nframes); + port.mFloatBuffer = buf; + port.mBufferSize = nframes; + port.mDoubleBuffer = 0; } + void AudioSource::SetExternalBuffer(const double* buf, unsigned nframes) { - mDoubleBuffer = buf; - mBufferSize = nframes; - mFloatBuffer = 0; - mOut.SetSize(nframes); - mOut.SetHop(nframes); + CLAM_ASSERT(1 == _ports.size(), "AudioOutPort index out of range"); + Port& port = _ports[0]; + port.mAudioOut->SetSize(nframes); + port.mAudioOut->SetHop(nframes); + port.mDoubleBuffer = buf; + port.mBufferSize = nframes; + port.mFloatBuffer = 0; } } //namespace CLAM Index: Processing/AudioSink.cxx =================================================================== --- Processing/AudioSink.cxx (revision 13150) +++ Processing/AudioSink.cxx (working copy) @@ -7,7 +7,7 @@ namespace CLAM { -namespace Hidden +namespace { static const char* metadata[] = { "key", "AudioSink", @@ -19,37 +19,72 @@ }; static FactoryRegistrator reg = metadata; } - bool AudioSink::Do() { - const CLAM::Audio& so=mIn.GetAudio(); - CLAM_DEBUG_ASSERT(mFloatBuffer, "No float buffer"); - CLAM_DEBUG_ASSERT(!mDoubleBuffer, "There should not be double buffer"); - CLAM_DEBUG_ASSERT(mBufferSize>0, "internal buffer size must be greater than 0"); - const CLAM::TData * audioBuffer = so.GetBuffer().GetPtr(); - for (unsigned i=0; iGetAudio(); + CLAM_DEBUG_ASSERT(port.mFloatBuffer, "No float buffer"); + CLAM_DEBUG_ASSERT(!port.mDoubleBuffer, "There should not be double buffer"); + CLAM_DEBUG_ASSERT(port.mBufferSize>0, "internal buffer size must be greater than 0"); + const CLAM::TData * audioBuffer = so.GetBuffer().GetPtr(); + for (unsigned i=0; iConsume(); + } + return true; } -void AudioSink::SetExternalBuffer( float* buf, unsigned nframes) +void AudioSink::SetExternalBuffer(float* buf, unsigned nframes, unsigned index) { - mFloatBuffer = buf; - mBufferSize = nframes; - mDoubleBuffer = 0; - mIn.SetSize(nframes); - mIn.SetHop(nframes); + CLAM_ASSERT(index < _ports.size(), "AudioInPort index out of range"); + Port& port = _ports[index]; + port.mAudioIn->SetSize(nframes); + port.mAudioIn->SetHop(nframes); + port.mFloatBuffer = buf; + port.mBufferSize = nframes; + port.mDoubleBuffer = 0; + } -void AudioSink::SetExternalBuffer( double* buf, unsigned nframes) + +void AudioSink::SetExternalBuffer(double* buf, unsigned nframes, unsigned index) { - mDoubleBuffer = buf; - mBufferSize = nframes; - mFloatBuffer = 0; - mIn.SetSize(nframes); - mIn.SetHop(nframes); + CLAM_ASSERT(index < _ports.size(), "AudioInPort index out of range"); + Port& port = _ports[index]; + port.mAudioIn->SetSize(nframes); + port.mAudioIn->SetHop(nframes); + port.mDoubleBuffer = buf; + port.mBufferSize = nframes; + port.mFloatBuffer = 0; } + +void AudioSink::SetExternalBuffer(float* buf, unsigned nframes) +{ + CLAM_ASSERT(1 == _ports.size(), "AudioInPort index out of range"); + Port& port = _ports[0]; + port.mAudioIn->SetSize(nframes); + port.mAudioIn->SetHop(nframes); + port.mFloatBuffer = buf; + port.mBufferSize = nframes; + port.mDoubleBuffer = 0; +} + +void AudioSink::SetExternalBuffer(double* buf, unsigned nframes) +{ + CLAM_ASSERT(1 == _ports.size(), "AudioInPort index out of range"); + Port& port = _ports[0]; + port.mAudioIn->SetSize(nframes); + port.mAudioIn->SetHop(nframes); + port.mDoubleBuffer = buf; + port.mBufferSize = nframes; + port.mFloatBuffer = 0; +} + } //namespace CLAM Index: Processing/AudioSource.hxx =================================================================== --- Processing/AudioSource.hxx (revision 13150) +++ Processing/AudioSource.hxx (working copy) @@ -4,41 +4,142 @@ #include "Processing.hxx" #include "AudioOutPort.hxx" +#include + namespace CLAM { - class AudioSource : public Processing - { - private: - AudioOutPort mOut; - const float* mFloatBuffer; - const double* mDoubleBuffer; - unsigned mBufferSize; - public: - AudioSource(const ProcessingConfig & conf=Config()) - : mOut("AudioOut",this) - , mFloatBuffer(0) - , mDoubleBuffer(0) - , mBufferSize(0) - { - //After being dropped it is ready to run as it does not need any configuration at all - SetExecState(Ready); - } + class AudioSource : public Processing + { + public: + struct Port + { + const float* mFloatBuffer; + const double* mDoubleBuffer; + unsigned mBufferSize; + AudioOutPort* mAudioOut; - void SetFrameAndHopSize(const int val) - { - mOut.SetSize(val); - mOut.SetHop(val); - } - - void SetExternalBuffer(const float* buf, unsigned nframes ); - void SetExternalBuffer(const double* buf, unsigned nframes ); + Port() {} - bool Do(); - - const char* GetClassName() const { return "AudioSource";} + explicit Port(AudioOutPort* p) + : mFloatBuffer(0), mDoubleBuffer(0), mBufferSize(0), mAudioOut(p) + { + } + }; + typedef std::vector Ports; - }; + private: + class Config : public ProcessingConfig + { + DYNAMIC_TYPE_USING_INTERFACE( Config, 1, ProcessingConfig ); + DYN_ATTRIBUTE( 0, public, int, NSources); + protected: + void DefaultInit() + { + AddAll(); + UpdateData(); + SetNSources(1); + }; + void LoadFrom(Storage & storage) + { + ProcessingConfig::LoadFrom(storage); + if (not HasNSources()) + { + AddNSources(); + UpdateData(); + SetNSources(1); + } + } + }; + + private: + Config _config; + Ports _ports; + + public: + AudioSource(const ProcessingConfig & config=Config()) + { + //After being dropped it is ready to run as it does not need any configuration at all + //SetExecState(Ready); + Configure( config ); + } + + ~AudioSource() + { + for (unsigned port = 0; port < _ports.size(); ++port) + delete _ports[port].mAudioOut; + } + + void SetFrameAndHopSize(const int val) + { + CLAM_ASSERT(1 == _ports.size(), "AudioOutPort out of range"); + Port& port = _ports[0]; + port.mAudioOut->SetSize(val); + port.mAudioOut->SetHop(val); + } + + void SetFrameAndHopSize(const int val, unsigned index) + { + CLAM_ASSERT(index < _ports.size(), "AudioOutPort index out of range"); + Port& port = _ports[index]; + port.mAudioOut->SetSize(val); + port.mAudioOut->SetHop(val); + } + + void SetExternalBuffer(const float* buf, unsigned nframes, unsigned index); + void SetExternalBuffer(const double* buf, unsigned nframes, unsigned index); + + void SetExternalBuffer(const float* buf, unsigned nframes); + void SetExternalBuffer(const double* buf, unsigned nframes); + + bool Do(); + + const char* GetClassName() const { return "AudioSource";} + + const ProcessingConfig & GetConfig() const + { + return _config; + } + + bool ConcreteConfigure(const ProcessingConfig& config) + { + CopyAsConcreteConfig(_config, config); + unsigned sources = _config.GetNSources(); + + ResizePorts(sources); + + return true; + } + + Ports & GetPorts() { return _ports; } + + private: + void ResizePorts(unsigned sources) + { + if (sources == _ports.size()) + return; + + if (sources < _ports.size()) + { + for (unsigned port = sources; port < _ports.size(); ++port) + delete _ports[port].mAudioOut; + + _ports.resize(sources); + } + + if (sources > _ports.size()) + { + for (unsigned port = _ports.size(); port < sources; ++port) + _ports.push_back(Port(new AudioOutPort(Portname(port), this))); + } + } + + std::string const Portname(unsigned port) const + { + std::ostringstream os; + os << port; + return os.str(); + } + }; } //namespace CLAM #endif - Index: Processing/AudioSink.hxx =================================================================== --- Processing/AudioSink.hxx (revision 13150) +++ Processing/AudioSink.hxx (working copy) @@ -4,35 +4,90 @@ #include "Processing.hxx" #include "AudioInPort.hxx" +#include + namespace CLAM { class AudioSink : public Processing { + public: + struct Port + { + float* mFloatBuffer; + double* mDoubleBuffer; + unsigned mBufferSize; + AudioInPort* mAudioIn; + + Port(){} //resize needs a default constructor + + explicit Port(AudioInPort* p) + : mFloatBuffer(0), mDoubleBuffer(0), mBufferSize(0), mAudioIn(p) + { + } + }; + typedef std::vector Ports; + + private: + class Config : public ProcessingConfig + { + DYNAMIC_TYPE_USING_INTERFACE( Config, 1, ProcessingConfig ); + DYN_ATTRIBUTE( 0, public, int, NSinks); + protected: + void DefaultInit() + { + AddAll(); + UpdateData(); + SetNSinks(1); + }; + void LoadFrom(Storage & storage) + { + ProcessingConfig::LoadFrom(storage); + if (not HasNSinks()) + { + AddNSinks(); + UpdateData(); + SetNSinks(1); + } + } + }; + private: - AudioInPort mIn; - float* mFloatBuffer; - double* mDoubleBuffer; - unsigned mBufferSize; + Config _config; + Ports _ports; public: - AudioSink(const ProcessingConfig & conf=Config()) - : mIn("AudioIn",this) - , mFloatBuffer(0) - , mDoubleBuffer(0) - , mBufferSize(0) + AudioSink(const ProcessingConfig & config=Config()) { //After being dropped it is ready to run as it does not need any configuration at all - SetExecState(Ready); + //SetExecState(Ready); + Configure( config ); } + ~AudioSink() + { + for (unsigned port = 0; port < _ports.size(); ++port) + delete _ports[port].mAudioIn; + } + /// @deprecated Delegated to SetExternalBuffer - void SetFrameAndHopSize(const int val) - { - mIn.SetSize(val); - mIn.SetHop(val); - } + void SetFrameAndHopSize(const int val) + { + CLAM_ASSERT(1 == _ports.size(), "AudioInPort index out of range"); + Port& port = _ports[0]; + port.mAudioIn->SetSize(val); + port.mAudioIn->SetHop(val); + } - ~AudioSink() {} + void SetFrameAndHopSize(const int val, unsigned index) + { + CLAM_ASSERT(index < _ports.size(), "AudioInPort index out of range"); + Port& port = _ports[index]; + port.mAudioIn->SetSize(val); + port.mAudioIn->SetHop(val); + } + + void SetExternalBuffer(float* buf, unsigned nframes, unsigned index); + void SetExternalBuffer(double* buf, unsigned nframes, unsigned index); void SetExternalBuffer(float* buf, unsigned nframes ); void SetExternalBuffer(double* buf, unsigned nframes ); @@ -41,6 +96,52 @@ const char* GetClassName() const { return "AudioSink";} + const ProcessingConfig & GetConfig() const + { + return _config; + } + + bool ConcreteConfigure(const ProcessingConfig& config) + { + CopyAsConcreteConfig(_config, config); + unsigned sinks = _config.GetNSinks(); + + ResizePorts(sinks); + + return true; + } + + Ports& GetPorts() { return _ports; } + + private: + void ResizePorts(unsigned sinks) + { + if (sinks == _ports.size()) + return; + + if (sinks < _ports.size()) + { + for (unsigned port = sinks; port < _ports.size(); ++port) + delete _ports[port].mAudioIn; + + _ports.resize(sinks); + } + + if (sinks > _ports.size()) + { + for (unsigned port = _ports.size(); port < sinks; ++port) + _ports.push_back(Port(new AudioInPort(Portname(port), this))); + } + } + + std::string const Portname(unsigned port) const + { + std::ostringstream os; + os << port; + return os.str(); + } + + }; } //namespace CLAM