// ----------------------------------------------------------
float ofxAudioUnitTap::getRMS(unsigned int channel)
// ----------------------------------------------------------
{
	getSamplesFromChannel(_tempBuffer, channel);
	float rms;
	vDSP_rmsqv(&_tempBuffer[0], 1, &rms, _tempBuffer.size());
	return rms;
}
bool ofxAudioUnitFftNode::getPhase(std::vector<float> &outPhase)
{
	getSamplesFromChannel(_sampleBuffer, 0);
	
	if(_sampleBuffer.size() < _N) {
		outPhase.clear();
		return false;
	}
	
	PerformFFT(&_sampleBuffer[0], _window, _fftData, _fftSetup, _N);
	
	vDSP_zvphas(&_fftData, 1, &_sampleBuffer[0], 1, _N / 2);
	
	outPhase.assign(_sampleBuffer.begin(), _sampleBuffer.begin() + (_N / 2));
	return true;
}
// ----------------------------------------------------------
void ofxAudioUnitTap::getSamples(StereoSamples &outData) const
// ----------------------------------------------------------
{
	getSamplesFromChannel(outData.left, 0);
	getSamplesFromChannel(outData.right, 0);
}
// ----------------------------------------------------------
void ofxAudioUnitTap::getSamples(MonoSamples &outData, unsigned int channel) const
// ----------------------------------------------------------
{
	getSamplesFromChannel(outData, channel);
}
// ----------------------------------------------------------
void ofxAudioUnitTap::getSamples(MonoSamples &outData) const
// ----------------------------------------------------------
{
	getSamplesFromChannel(outData, 0);
}
void ofxAudioUnitTap::getRightSamples(MonoSamples &outData) const {
	getSamplesFromChannel(outData, 1);
}
bool ofxAudioUnitFftNode::getAmplitude(std::vector<float> &outAmplitude)
{
	getSamplesFromChannel(_sampleBuffer, 0);
	
	// return empty if we don't have enough samples yet
	if(_sampleBuffer.size() < _N) {
		outAmplitude.clear();
		return false;
	}
	
	// normalize input waveform
	if(_outputSettings.normalizeInput) {
		float timeDomainMax;
		vDSP_maxv(&_sampleBuffer[0], 1, &timeDomainMax, _N);
		vDSP_vsdiv(&_sampleBuffer[0], 1, &timeDomainMax, &_sampleBuffer[0], 1, _N);
	}
	
	PerformFFT(&_sampleBuffer[0], _window, _fftData, _fftSetup, _N);
	
	// get amplitude
	vDSP_zvmags(&_fftData, 1, _fftData.realp, 1, _N/2);
	
	// normalize magnitudes
	float two = 2.0;
	vDSP_vsdiv(_fftData.realp, 1, &two, _fftData.realp, 1, _N/2);

	// scale output according to requested settings
	if(_outputSettings.scale == OFXAU_SCALE_LOG10) {
		for(int i = 0; i < (_N / 2); i++) {
			_fftData.realp[i] = log10f(_fftData.realp[i] + 1);
		}
	} else if(_outputSettings.scale == OFXAU_SCALE_DECIBEL) {
		float ref = 1.0;
		vDSP_vdbcon(_fftData.realp, 1, &ref, _fftData.realp, 1, _N / 2, 1);
		
		float dbCorrectionFactor = 0;
		switch (_outputSettings.window) {
			case OFXAU_WINDOW_HAMMING:
				dbCorrectionFactor = DB_CORRECTION_HAMMING;
				break;
			case OFXAU_WINDOW_HANNING:
				dbCorrectionFactor = DB_CORRECTION_HAMMING;
				break;
			case OFXAU_WINDOW_BLACKMAN:
				dbCorrectionFactor = DB_CORRECTION_HAMMING;
				break;
		}
		
		vDSP_vsadd(_fftData.realp, 1, &dbCorrectionFactor, _fftData.realp, 1, _N / 2);
	}
	
	// restrict minimum to 0
	if(_outputSettings.clampMinToZero) {
		float min = 0.0;
		float max = INFINITY;
		vDSP_vclip(_fftData.realp, 1, &min, &max, _fftData.realp, 1, _N / 2);
	}
	
	// normalize output between 0 and 1
	if(_outputSettings.normalizeOutput) {
		float max;
		vDSP_maxv(_fftData.realp, 1, &max, _N / 2);
		if(max > 0) {
			vDSP_vsdiv(_fftData.realp, 1, &max, _fftData.realp, 1, _N / 2);
		}
	}
	
	outAmplitude.assign(_fftData.realp, _fftData.realp + _N/2);
	return true;
}