Mercurial > hg > devuvuzelator
view devuvuzelator-ladspa.cpp @ 19:0cdedb2fab81 tip
* OS/X build fixes
author | Chris Cannam |
---|---|
date | Fri, 18 Jun 2010 11:18:49 +0100 |
parents | e7e8a8f57f35 |
children |
line wrap: on
line source
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ #include "devuvuzelator-ladspa.h" #include <alloca.h> #include <iostream> #include <cmath> #include "params.h" const char *const Devuvuzelator::portNames[PortCount] = { "Input", "Output", "latency", "Fundamental frequency (Hz)", "Bandwidth of fundamental (Hz)", "Number of partials", "Reduction (%)", }; const LADSPA_PortDescriptor Devuvuzelator::ports[PortCount] = { LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO, LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO, LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL, LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL, }; const LADSPA_PortRangeHint Devuvuzelator::hints[PortCount] = { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { LADSPA_HINT_DEFAULT_LOW | LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, 50, 770 }, { LADSPA_HINT_DEFAULT_MIDDLE | LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, 20, 100 }, { LADSPA_HINT_DEFAULT_MIDDLE | LADSPA_HINT_INTEGER | LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, 0, 6 }, { LADSPA_HINT_DEFAULT_MIDDLE | LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, 0, 100 }, }; const LADSPA_Properties Devuvuzelator::properties = LADSPA_PROPERTY_HARD_RT_CAPABLE; const LADSPA_Descriptor Devuvuzelator::ladspaDescriptor = { 0xf0b374, // "Unique" ID "devuvuzelator", // Label properties, "Devuvuzelator", // Name "Queen Mary, University of London", // Maker "BSD", // Copyright PortCount, ports, portNames, hints, 0, // Implementation data instantiate, connectPort, activate, run, 0, // Run adding 0, // Set run adding gain deactivate, cleanup }; const LADSPA_Descriptor * Devuvuzelator::getDescriptor(unsigned long index) { if (index == 0) return &ladspaDescriptor; return 0; } Devuvuzelator::Devuvuzelator(int sampleRate) : m_sampleRate(sampleRate), m_input(0), m_output(0), m_platency(0), m_pfundamental(0), m_pbandwidth(0), m_pharmonics(0), m_preduction(0), m_fftsize(FFTSIZE), m_winsize(WINSIZE), m_increment(m_winsize/2), m_filtersecs(FILTERSECS), m_fill(0), m_read(0) { m_buffer = new float[m_winsize]; m_outacc = new float[m_winsize * 2]; m_window = new double[m_winsize]; m_real = new double[m_fftsize]; m_imag = new double[m_fftsize]; m_medians = new MedianFilter<double> *[m_fftsize/2+1]; for (int i = 0; i < m_winsize; ++i) { m_window[i] = 0.5 - 0.5 * cos(2 * M_PI * i / m_winsize); } for (int i = 0; i < m_fftsize/2+1; ++i) { m_medians[i] = 0; } m_fundamental = 230; m_bandwidth = 60; m_harmonics = 3; m_reduction = 50; std::cerr << "note: latency = " << (float(m_winsize) / m_sampleRate)*1000 << " msec" << std::endl; reset(); } Devuvuzelator::~Devuvuzelator() { delete[] m_buffer; delete[] m_outacc; delete[] m_real; delete[] m_imag; delete[] m_window; for (int i = 0; i < m_fftsize/2+1; ++i) { delete m_medians[i]; } delete[] m_medians; } LADSPA_Handle Devuvuzelator::instantiate(const LADSPA_Descriptor *, unsigned long rate) { Devuvuzelator *devuvu = new Devuvuzelator(rate); return devuvu; } void Devuvuzelator::connectPort(LADSPA_Handle handle, unsigned long port, LADSPA_Data *location) { Devuvuzelator *devuvu = (Devuvuzelator *)handle; float **ports[PortCount] = { &devuvu->m_input, &devuvu->m_output, &devuvu->m_platency, &devuvu->m_pfundamental, &devuvu->m_pbandwidth, &devuvu->m_pharmonics, &devuvu->m_preduction, }; *ports[port] = (float *)location; } void Devuvuzelator::activate(LADSPA_Handle handle) { Devuvuzelator *devuvu = (Devuvuzelator *)handle; devuvu->reset(); } void Devuvuzelator::run(LADSPA_Handle handle, unsigned long samples) { Devuvuzelator *devuvu = (Devuvuzelator *)handle; devuvu->runImpl(samples); } void Devuvuzelator::deactivate(LADSPA_Handle handle) { activate(handle); // both functions just reset the plugin } void Devuvuzelator::cleanup(LADSPA_Handle handle) { delete (Devuvuzelator *)handle; } void Devuvuzelator::reset() { for (int i = 0; i < m_winsize; ++i) { m_buffer[i] = 0.f; } for (int i = 0; i < m_winsize*2; ++i) { m_outacc[i] = 0.f; } m_fill = 0; m_read = 0; for (int i = 0; i < m_fftsize/2+1; ++i) { if (m_medians[i]) m_medians[i]->reset(); } } void Devuvuzelator::updateParameters() { if (m_platency) *m_platency = m_winsize; if (m_pfundamental) m_fundamental = *m_pfundamental; if (m_pbandwidth) m_bandwidth = *m_pbandwidth; if (m_pharmonics) m_harmonics = *m_pharmonics; if (m_preduction) m_reduction = *m_preduction; } void Devuvuzelator::runImpl(unsigned long sampleCount) { if (!m_input || !m_output) return; updateParameters(); int ii = 0; int oi = 0; const int sc = sampleCount; float tmp_input; while (ii < sc) { tmp_input = m_input[ii++]; m_output[oi++] = m_outacc[m_read++]; if (m_fill == m_winsize) { processFrame(); for (int j = m_increment; j < m_winsize; ++j) { m_buffer[j - m_increment] = m_buffer[j]; } for (int j = m_increment; j < m_winsize*2; ++j) { m_outacc[j - m_increment] = m_outacc[j]; } for (int j = m_winsize*2 - m_increment; j < m_winsize*2; ++j) { m_outacc[j] = 0.f; } m_fill -= m_increment; m_read -= m_increment; } m_buffer[m_fill++] = tmp_input; } } void Devuvuzelator::processFrame() { double *frame = (double *)alloca(m_fftsize * sizeof(double)); for (int i = 0; i < m_fftsize; ++i) { frame[i] = 0.0; } int ix = m_fftsize - m_winsize/2; while (ix < 0) ix += m_fftsize; for (int i = 0; i < m_winsize; ++i) { frame[ix++] += m_buffer[i] * m_window[i]; if (ix == m_fftsize) ix = 0; } fft(m_fftsize, false, frame, 0, m_real, m_imag); processSpectralFrame(); for (int i = 0; i < m_fftsize/2-1; ++i) { m_real[m_fftsize-i-1] = m_real[i+1]; m_imag[m_fftsize-i-1] = -m_imag[i+1]; } double *spare = (double *)alloca(m_fftsize * sizeof(double)); fft(m_fftsize, true, m_real, m_imag, frame, spare); ix = m_fftsize - m_winsize/2; while (ix < 0) ix += m_fftsize; for (int i = 0; i < m_winsize; ++i) { m_outacc[m_winsize + i] += frame[ix++]; if (ix == m_fftsize) ix = 0; } } const LADSPA_Descriptor * ladspa_descriptor(unsigned long ix) { return Devuvuzelator::getDescriptor(ix); }