view Azi.cpp @ 2:b95d2278c9c4

More inconsequential piddling
author Chris Cannam
date Fri, 25 Jul 2014 18:26:07 +0100
parents 41b09144491b
children 07d63200488c
line wrap: on
line source

#include "Azi.h"

#include <cmath>

using std::vector;

Azi::Azi(float inputSampleRate) :
    Plugin(inputSampleRate),
    m_width(32)
{
}

Azi::~Azi()
{
}

string
Azi::getIdentifier() const
{
    return "azi";
}

string
Azi::getName() const
{
    return "Stereo Plan";
}

string
Azi::getDescription() const
{
    // Return something helpful here!
    return "";
}

string
Azi::getMaker() const
{
    // Your name here
    return "";
}

int
Azi::getPluginVersion() const
{
    // Increment this each time you release a version that behaves
    // differently from the previous one
    return 1;
}

string
Azi::getCopyright() const
{
    // This function is not ideally named.  It does not necessarily
    // need to say who made the plugin -- getMaker does that -- but it
    // should indicate the terms under which it is distributed.  For
    // example, "Copyright (year). All Rights Reserved", or "GPL"
    return "";
}

Azi::InputDomain
Azi::getInputDomain() const
{
    return TimeDomain;
}

size_t
Azi::getPreferredBlockSize() const
{
    return 2048;
}

size_t 
Azi::getPreferredStepSize() const
{
    return 256;
}

size_t
Azi::getMinChannelCount() const
{
    return 2;
}

size_t
Azi::getMaxChannelCount() const
{
    return 2;
}

Azi::ParameterList
Azi::getParameterDescriptors() const
{
    ParameterList list;

    // If the plugin has no adjustable parameters, return an empty
    // list here (and there's no need to provide implementations of
    // getParameter and setParameter in that case either).

    // Note that it is your responsibility to make sure the parameters
    // start off having their default values (e.g. in the constructor
    // above).  The host needs to know the default value so it can do
    // things like provide a "reset to default" function, but it will
    // not explicitly set your parameters to their defaults for you if
    // they have not changed in the mean time.

    return list;
}

float
Azi::getParameter(string identifier) const
{
    return 0;
}

void
Azi::setParameter(string identifier, float value) 
{
}

Azi::ProgramList
Azi::getPrograms() const
{
    ProgramList list;

    // If you have no programs, return an empty list (or simply don't
    // implement this function or getCurrentProgram/selectProgram)

    return list;
}

string
Azi::getCurrentProgram() const
{
    return ""; // no programs
}

void
Azi::selectProgram(string name)
{
}

Azi::OutputList
Azi::getOutputDescriptors() const
{
    OutputList list;

    // See OutputDescriptor documentation for the possibilities here.
    // Every plugin must have at least one output.

    OutputDescriptor d;
    d.identifier = "plan";
    d.name = "Plan";
    d.description = "";
    d.unit = "";
    d.hasFixedBinCount = true;
    d.binCount = m_width * 2 + 1;
    d.hasKnownExtents = false;
    d.isQuantized = false;
    d.sampleType = OutputDescriptor::OneSamplePerStep;
    d.hasDuration = false;
    list.push_back(d);

    return list;
}

bool
Azi::initialise(size_t channels, size_t stepSize, size_t blockSize)
{
    if (channels < getMinChannelCount() ||
	channels > getMaxChannelCount()) return false;

    m_blockSize = blockSize;

    return true;
}

void
Azi::reset()
{
    // Clear buffers, reset stored values, etc
}

float
Azi::rms(const float *buffer, int size)
{
    float sum = 0;
    if (size == 0) {
	return 0;
    }
    for (int i = 0; i < size; ++i) {
	sum += buffer[i] * buffer[i];
    }
    return sqrt(sum / size);
}

Azi::FeatureSet
Azi::process(const float *const *inputBuffers, Vamp::RealTime timestamp)
{
    const float *left = inputBuffers[0];
    const float *right = inputBuffers[1];

    FeatureSet fs;
    Feature f;

    float *mixed = new float[m_blockSize];
    for (int i = 0; i < m_blockSize; ++i) {
	mixed[i] = left[i] + right[i];
    }
    float mixedRms = rms(mixed, m_blockSize);

    float *panned = new float[m_blockSize];

    vector<float> levels;

    for (int j = -m_width; j <= m_width; ++j) {

	float pan = float(j) / m_width;

	float leftGain = 1.f, rightGain = 1.f;
	if (pan > 0.f) leftGain *= 1.f - pan;
	if (pan < 0.f) rightGain *= pan + 1.f;

	if (leftGain < rightGain) {
	
	    float ratio = leftGain / rightGain;
	    for (int i = 0; i < m_blockSize; ++i) {
		panned[i] = left[i] - ratio * right[i];
	    }

	} else {
	
	    float ratio = rightGain / leftGain;
	    for (int i = 0; i < m_blockSize; ++i) {
		panned[i] = right[i] - ratio * left[i];
	    }
	}

	float pannedRms = rms(panned, m_blockSize);
	levels.push_back(mixedRms - pannedRms);
    }

    for (int i = 1; i+1 < int(levels.size()); ++i) {
//	if (levels[i] > levels[i-1] && levels[i] > levels[i+1]) {
	    f.values.push_back(levels[i]);
//	} else {
//	    f.values.push_back(0);
//	}
    }

    delete[] panned;
    delete[] mixed;

    fs[0].push_back(f);

    return fs;
}

Azi::FeatureSet
Azi::getRemainingFeatures()
{
    return FeatureSet();
}