annotate 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
rev   line source
Chris@1 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@1 2
Chris@9 3 #include "devuvuzelator-ladspa.h"
Chris@9 4
Chris@1 5 #include <alloca.h>
Chris@1 6 #include <iostream>
Chris@1 7 #include <cmath>
Chris@1 8
Chris@9 9 #include "params.h"
Chris@1 10
Chris@1 11 const char *const
Chris@1 12 Devuvuzelator::portNames[PortCount] =
Chris@1 13 {
Chris@1 14 "Input",
Chris@1 15 "Output",
Chris@4 16 "latency",
Chris@1 17 "Fundamental frequency (Hz)",
Chris@1 18 "Bandwidth of fundamental (Hz)",
Chris@1 19 "Number of partials",
Chris@4 20 "Reduction (%)",
Chris@1 21 };
Chris@1 22
Chris@1 23 const LADSPA_PortDescriptor
Chris@1 24 Devuvuzelator::ports[PortCount] =
Chris@1 25 {
Chris@1 26 LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO,
Chris@1 27 LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
Chris@4 28 LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL,
Chris@1 29 LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL,
Chris@1 30 LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL,
Chris@1 31 LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL,
Chris@1 32 LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL,
Chris@1 33 };
Chris@1 34
Chris@1 35 const LADSPA_PortRangeHint
Chris@1 36 Devuvuzelator::hints[PortCount] =
Chris@1 37 {
Chris@1 38 { 0, 0, 0 },
Chris@1 39 { 0, 0, 0 },
Chris@4 40 { 0, 0, 0 },
Chris@1 41 { LADSPA_HINT_DEFAULT_LOW |
Chris@4 42 LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, 50, 770 },
Chris@1 43 { LADSPA_HINT_DEFAULT_MIDDLE |
Chris@1 44 LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, 20, 100 },
Chris@1 45 { LADSPA_HINT_DEFAULT_MIDDLE | LADSPA_HINT_INTEGER |
Chris@1 46 LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, 0, 6 },
Chris@1 47 { LADSPA_HINT_DEFAULT_MIDDLE |
Chris@4 48 LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, 0, 100 },
Chris@1 49 };
Chris@1 50
Chris@1 51 const LADSPA_Properties
Chris@1 52 Devuvuzelator::properties = LADSPA_PROPERTY_HARD_RT_CAPABLE;
Chris@1 53
Chris@1 54 const LADSPA_Descriptor
Chris@1 55 Devuvuzelator::ladspaDescriptor =
Chris@1 56 {
Chris@16 57 0xf0b374, // "Unique" ID
Chris@1 58 "devuvuzelator", // Label
Chris@1 59 properties,
Chris@1 60 "Devuvuzelator", // Name
Chris@1 61 "Queen Mary, University of London", // Maker
Chris@11 62 "BSD", // Copyright
Chris@1 63 PortCount,
Chris@1 64 ports,
Chris@1 65 portNames,
Chris@1 66 hints,
Chris@1 67 0, // Implementation data
Chris@1 68 instantiate,
Chris@1 69 connectPort,
Chris@1 70 activate,
Chris@1 71 run,
Chris@1 72 0, // Run adding
Chris@1 73 0, // Set run adding gain
Chris@1 74 deactivate,
Chris@1 75 cleanup
Chris@1 76 };
Chris@1 77
Chris@1 78 const LADSPA_Descriptor *
Chris@1 79 Devuvuzelator::getDescriptor(unsigned long index)
Chris@1 80 {
Chris@1 81 if (index == 0) return &ladspaDescriptor;
Chris@1 82 return 0;
Chris@1 83 }
Chris@1 84
Chris@1 85 Devuvuzelator::Devuvuzelator(int sampleRate) :
Chris@1 86 m_sampleRate(sampleRate),
Chris@1 87 m_input(0),
Chris@1 88 m_output(0),
Chris@4 89 m_platency(0),
Chris@4 90 m_pfundamental(0),
Chris@4 91 m_pbandwidth(0),
Chris@4 92 m_pharmonics(0),
Chris@4 93 m_preduction(0),
Chris@1 94 m_fftsize(FFTSIZE),
Chris@4 95 m_winsize(WINSIZE),
Chris@4 96 m_increment(m_winsize/2),
Chris@9 97 m_filtersecs(FILTERSECS),
Chris@1 98 m_fill(0),
Chris@1 99 m_read(0)
Chris@1 100 {
Chris@4 101 m_buffer = new float[m_winsize];
Chris@4 102 m_outacc = new float[m_winsize * 2];
Chris@4 103 m_window = new double[m_winsize];
Chris@1 104 m_real = new double[m_fftsize];
Chris@1 105 m_imag = new double[m_fftsize];
Chris@4 106 m_medians = new MedianFilter<double> *[m_fftsize/2+1];
Chris@1 107
Chris@4 108 for (int i = 0; i < m_winsize; ++i) {
Chris@4 109 m_window[i] = 0.5 - 0.5 * cos(2 * M_PI * i / m_winsize);
Chris@1 110 }
Chris@4 111 for (int i = 0; i < m_fftsize/2+1; ++i) {
Chris@4 112 m_medians[i] = 0;
Chris@4 113 }
Chris@4 114
Chris@4 115 m_fundamental = 230;
Chris@4 116 m_bandwidth = 60;
Chris@4 117 m_harmonics = 3;
Chris@4 118 m_reduction = 50;
Chris@4 119
Chris@4 120 std::cerr << "note: latency = " << (float(m_winsize) / m_sampleRate)*1000 << " msec" << std::endl;
Chris@1 121
Chris@1 122 reset();
Chris@1 123 }
Chris@1 124
Chris@1 125 Devuvuzelator::~Devuvuzelator()
Chris@1 126 {
Chris@1 127 delete[] m_buffer;
Chris@1 128 delete[] m_outacc;
Chris@1 129 delete[] m_real;
Chris@1 130 delete[] m_imag;
Chris@1 131 delete[] m_window;
Chris@4 132 for (int i = 0; i < m_fftsize/2+1; ++i) {
Chris@4 133 delete m_medians[i];
Chris@4 134 }
Chris@4 135 delete[] m_medians;
Chris@1 136 }
Chris@1 137
Chris@1 138 LADSPA_Handle
Chris@1 139 Devuvuzelator::instantiate(const LADSPA_Descriptor *, unsigned long rate)
Chris@1 140 {
Chris@1 141 Devuvuzelator *devuvu = new Devuvuzelator(rate);
Chris@1 142 return devuvu;
Chris@1 143 }
Chris@1 144
Chris@1 145 void
Chris@1 146 Devuvuzelator::connectPort(LADSPA_Handle handle,
Chris@1 147 unsigned long port, LADSPA_Data *location)
Chris@1 148 {
Chris@1 149 Devuvuzelator *devuvu = (Devuvuzelator *)handle;
Chris@1 150
Chris@1 151 float **ports[PortCount] = {
Chris@1 152 &devuvu->m_input,
Chris@1 153 &devuvu->m_output,
Chris@4 154 &devuvu->m_platency,
Chris@4 155 &devuvu->m_pfundamental,
Chris@4 156 &devuvu->m_pbandwidth,
Chris@4 157 &devuvu->m_pharmonics,
Chris@4 158 &devuvu->m_preduction,
Chris@1 159 };
Chris@1 160
Chris@1 161 *ports[port] = (float *)location;
Chris@1 162 }
Chris@1 163
Chris@1 164 void
Chris@1 165 Devuvuzelator::activate(LADSPA_Handle handle)
Chris@1 166 {
Chris@1 167 Devuvuzelator *devuvu = (Devuvuzelator *)handle;
Chris@1 168 devuvu->reset();
Chris@1 169 }
Chris@1 170
Chris@1 171 void
Chris@1 172 Devuvuzelator::run(LADSPA_Handle handle, unsigned long samples)
Chris@1 173 {
Chris@1 174 Devuvuzelator *devuvu = (Devuvuzelator *)handle;
Chris@1 175 devuvu->runImpl(samples);
Chris@1 176 }
Chris@1 177
Chris@1 178 void
Chris@1 179 Devuvuzelator::deactivate(LADSPA_Handle handle)
Chris@1 180 {
Chris@1 181 activate(handle); // both functions just reset the plugin
Chris@1 182 }
Chris@1 183
Chris@1 184 void
Chris@1 185 Devuvuzelator::cleanup(LADSPA_Handle handle)
Chris@1 186 {
Chris@1 187 delete (Devuvuzelator *)handle;
Chris@1 188 }
Chris@1 189
Chris@1 190 void
Chris@1 191 Devuvuzelator::reset()
Chris@1 192 {
Chris@4 193 for (int i = 0; i < m_winsize; ++i) {
Chris@1 194 m_buffer[i] = 0.f;
Chris@1 195 }
Chris@4 196 for (int i = 0; i < m_winsize*2; ++i) {
Chris@1 197 m_outacc[i] = 0.f;
Chris@1 198 }
Chris@1 199 m_fill = 0;
Chris@1 200 m_read = 0;
Chris@4 201 for (int i = 0; i < m_fftsize/2+1; ++i) {
Chris@4 202 if (m_medians[i]) m_medians[i]->reset();
Chris@4 203 }
Chris@4 204 }
Chris@4 205
Chris@4 206 void
Chris@4 207 Devuvuzelator::updateParameters()
Chris@4 208 {
Chris@4 209 if (m_platency) *m_platency = m_winsize;
Chris@4 210 if (m_pfundamental) m_fundamental = *m_pfundamental;
Chris@4 211 if (m_pbandwidth) m_bandwidth = *m_pbandwidth;
Chris@4 212 if (m_pharmonics) m_harmonics = *m_pharmonics;
Chris@4 213 if (m_preduction) m_reduction = *m_preduction;
Chris@1 214 }
Chris@1 215
Chris@1 216 void
Chris@1 217 Devuvuzelator::runImpl(unsigned long sampleCount)
Chris@1 218 {
Chris@1 219 if (!m_input || !m_output) return;
Chris@4 220 updateParameters();
Chris@1 221
Chris@1 222 int ii = 0;
Chris@1 223 int oi = 0;
Chris@1 224 const int sc = sampleCount;
Chris@1 225
Chris@14 226 float tmp_input;
Chris@14 227
Chris@1 228 while (ii < sc) {
Chris@1 229
Chris@14 230 tmp_input = m_input[ii++];
Chris@14 231
Chris@4 232 m_output[oi++] = m_outacc[m_read++];
Chris@1 233
Chris@4 234 if (m_fill == m_winsize) {
Chris@1 235
Chris@1 236 processFrame();
Chris@1 237
Chris@4 238 for (int j = m_increment; j < m_winsize; ++j) {
Chris@1 239 m_buffer[j - m_increment] = m_buffer[j];
Chris@1 240 }
Chris@1 241
Chris@4 242 for (int j = m_increment; j < m_winsize*2; ++j) {
Chris@1 243 m_outacc[j - m_increment] = m_outacc[j];
Chris@1 244 }
Chris@1 245
Chris@4 246 for (int j = m_winsize*2 - m_increment; j < m_winsize*2; ++j) {
Chris@1 247 m_outacc[j] = 0.f;
Chris@1 248 }
Chris@1 249
Chris@1 250 m_fill -= m_increment;
Chris@1 251 m_read -= m_increment;
Chris@1 252 }
Chris@1 253
Chris@14 254 m_buffer[m_fill++] = tmp_input;
Chris@1 255 }
Chris@1 256 }
Chris@1 257
Chris@1 258 void
Chris@1 259 Devuvuzelator::processFrame()
Chris@1 260 {
Chris@1 261 double *frame = (double *)alloca(m_fftsize * sizeof(double));
Chris@1 262 for (int i = 0; i < m_fftsize; ++i) {
Chris@4 263 frame[i] = 0.0;
Chris@4 264 }
Chris@4 265
Chris@4 266 int ix = m_fftsize - m_winsize/2;
Chris@4 267 while (ix < 0) ix += m_fftsize;
Chris@4 268 for (int i = 0; i < m_winsize; ++i) {
Chris@4 269 frame[ix++] += m_buffer[i] * m_window[i];
Chris@1 270 if (ix == m_fftsize) ix = 0;
Chris@1 271 }
Chris@1 272
Chris@1 273 fft(m_fftsize, false, frame, 0, m_real, m_imag);
Chris@1 274
Chris@1 275 processSpectralFrame();
Chris@1 276
Chris@1 277 for (int i = 0; i < m_fftsize/2-1; ++i) {
Chris@3 278 m_real[m_fftsize-i-1] = m_real[i+1];
Chris@3 279 m_imag[m_fftsize-i-1] = -m_imag[i+1];
Chris@1 280 }
Chris@1 281
Chris@1 282 double *spare = (double *)alloca(m_fftsize * sizeof(double));
Chris@1 283 fft(m_fftsize, true, m_real, m_imag, frame, spare);
Chris@1 284
Chris@4 285 ix = m_fftsize - m_winsize/2;
Chris@4 286 while (ix < 0) ix += m_fftsize;
Chris@4 287 for (int i = 0; i < m_winsize; ++i) {
Chris@4 288 m_outacc[m_winsize + i] += frame[ix++];
Chris@1 289 if (ix == m_fftsize) ix = 0;
Chris@1 290 }
Chris@1 291 }
Chris@1 292
Chris@1 293 const LADSPA_Descriptor *
Chris@1 294 ladspa_descriptor(unsigned long ix)
Chris@1 295 {
Chris@1 296 return Devuvuzelator::getDescriptor(ix);
Chris@1 297 }
Chris@1 298