view Azi.cpp @ 1:41b09144491b

Start to calculate some roughly stereo-related things
author Chris Cannam
date Fri, 25 Jul 2014 17:50:08 +0100
parents d960c4931501
children b95d2278c9c4
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 0; // 0 means "I can handle any block size"
}

size_t 
Azi::getPreferredStepSize() const
{
    return 0; // 0 means "anything sensible"; in practice this
              // means the same as the block size for TimeDomain
              // plugins, or half of it for FrequencyDomain plugins
}

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];

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

    FeatureSet fs;
    Feature f;

    float *unpanned = new float[m_blockSize];

    vector<float> levels;

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

	float unpan = float(j) / m_width;

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

	for (int i = 0; i < m_blockSize; ++i) {
	    unpanned[i] = (leftGain * left[i]) - (rightGain * right[i]);
	}

	float unpannedRms = rms(unpanned, m_blockSize);
	levels.push_back((mixedRms - unpannedRms) / mixedRms);
    }

    for (int i = 1; i+1 < int(levels.size()); ++i) {
	f.values.push_back(1.f - levels[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[] unpanned;
    delete[] mixed;

    fs[0].push_back(f);

    return fs;
}

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