/*
 * Copyright (c) 2007 Fundació Barcelona Media Universitat Pompeu Fabra
 *
 *
 * 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
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#ifndef AudioBuffer2Stream_hxx
#define AudioBuffer2Stream_hxx

#include <CLAM/InPort.hxx>
#include <CLAM/OutPort.hxx>
#include <CLAM/AudioOutPort.hxx>
#include <CLAM/Processing.hxx>
#include <CLAM/AudioWindowingConfig.hxx>
#include <algorithm>

namespace CLAM
{

/**
 Processing that generates a continuous stream of samples
 by semi-overlapping incomming audio buffers.
 The overlap is controlled by setting smaller HopSize than
 the incomming FFTSize.
 @pre The FFTSize should match the size of the incomming buffers.
 @param HopSize [Config] How many samples the window is advancing each execution 
 @param FFTSize [Config] How many samples the window includes
 @param[in] "Audio buffer"  [Port] The incoming audio buffers
 @param[out] "Audio stream"  [Port] The outgoing audio stream
 @ingroup SpectralProcessingAnalysis
*/

class AudioBuffer2Stream : public Processing
{
public:
	class Config : public ProcessingConfig
	{
		DYNAMIC_TYPE_USING_INTERFACE( Config, 2, ProcessingConfig );
		DYN_ATTRIBUTE( 0, public, unsigned, HopSize);
		DYN_ATTRIBUTE( 1, public, unsigned, BufferSize);
    	protected:
		void DefaultInit()
		{
			AddAll();
			UpdateData();
			SetHopSize(512);
			SetBufferSize(1024);
		}
	};
private:
	InPort<Audio> _in;
	AudioOutPort _out;
	unsigned _hopSize;
	unsigned _bufferSize;
	Config _config;

public:
	const char* GetClassName() const { return "AudioBuffer2Stream"; }
	AudioBuffer2Stream(const Config& config = Config()) 
		: _in("Audio buffer", this)
		, _out("Audio stream", this) 
	{
		Configure( config );
	}
private:
	bool ConcreteConfigure(const ProcessingConfig & c)
	{
		CopyAsConcreteConfig(_config, c);
		_hopSize = _config.GetHopSize();
		_bufferSize = _config.GetBufferSize();
		_out.SetSize( _bufferSize );
		_out.SetHop( _hopSize );
		return true;
	}
public: 
	const ProcessingConfig & GetConfig() const { return _config; }
	bool Do()
	{
		const Audio& in = _in.GetData();
		Audio& out = _out.GetAudio();
		bool toReturn = Do(in, out);
		// Tell the ports this is done
		_in.Consume();
		_out.Produce();
		return toReturn;
	}
	bool Do(const CLAM::Audio & in, CLAM::Audio & out)
	{
		CLAM_ASSERT(_bufferSize==in.GetSize(),
			"AudioBuffer2Stream: Input does not provide the configured window size"); 
		const TData* inpointer = in.GetBuffer().GetPtr();
		TData* outpointer = out.GetBuffer().GetPtr();
		// Zero fill the new incomming hopSize
		std::fill(outpointer+_bufferSize-_hopSize, outpointer+_bufferSize, 0.0);
		// Add the input on the full window
		std::transform(inpointer, inpointer+_bufferSize, outpointer, outpointer, std::plus<TData>());
		return true;
	}

};

} // namespace CLAM
#endif // AudioBuffer2Stream_hxx
