annotate devuvuzelator-vst.cpp @ 9:a1539d4e3b08

* Tidy code, start doc
author Chris Cannam
date Sat, 12 Jun 2010 13:08:33 +0100
parents e15ebd222c63
children 1e6360396b6c
rev   line source
Chris@0 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@9 3 #include "devuvuzelator-vst.h"
Chris@9 4
Chris@2 5 #define _USE_MATH_DEFINES
Chris@9 6 #include <cmath>
Chris@0 7 #include <iostream>
Chris@2 8 #include <cstdio>
Chris@0 9
Chris@9 10 #include "params.h"
Chris@2 11
Chris@2 12 #define snprintf _snprintf
Chris@2 13 #define alloca _alloca
Chris@0 14
Chris@1 15 // VST params 0->1
Chris@1 16
Chris@0 17 void
Chris@0 18 Devuvuzelator::setParameter(VstInt32 index, float value)
Chris@0 19 {
Chris@1 20 switch (index) {
Chris@4 21 case 0: m_fundamental = 50 + 720 * value; break;
Chris@4 22 case 1: m_bandwidth = 20 + 80 * value; break;
Chris@4 23 case 2: m_harmonics = int(value * 6 + 0.5); break;
Chris@4 24 case 3: m_reduction = 100 * value; break;
Chris@1 25 }
Chris@0 26 }
Chris@0 27
Chris@0 28 float
Chris@0 29 Devuvuzelator::getParameter(VstInt32 index)
Chris@0 30 {
Chris@1 31 switch (index) {
Chris@4 32 case 0: return (m_fundamental - 50) / 720;
Chris@4 33 case 1: return (m_bandwidth - 20) / 80;
Chris@4 34 case 2: return (m_harmonics / 6.f);
Chris@4 35 case 3: return m_reduction / 100;
Chris@1 36 }
Chris@4 37 return 0;
Chris@0 38 }
Chris@0 39
Chris@0 40 // NB! The max name length for VST parameter names, labels
Chris@0 41 // (i.e. units) and display values (i.e. string renderings of current
Chris@0 42 // value) is a rather amazing 8 bytes
Chris@0 43
Chris@0 44 void
Chris@0 45 Devuvuzelator::getParameterLabel(VstInt32 index, char *label)
Chris@0 46 {
Chris@0 47 const char *units[NumParams] = {
Chris@0 48 "Hz",
Chris@0 49 "Hz",
Chris@0 50 "",
Chris@4 51 "%",
Chris@0 52 };
Chris@0 53
Chris@0 54 vst_strncpy(label, units[index], kVstMaxParamStrLen);
Chris@0 55 }
Chris@0 56
Chris@0 57 void
Chris@0 58 Devuvuzelator::getParameterDisplay(VstInt32 index, char *label)
Chris@0 59 {
Chris@4 60 switch (index) {
Chris@4 61 case 0: snprintf(label, kVstMaxParamStrLen, "%f", m_fundamental); break;
Chris@4 62 case 1: snprintf(label, kVstMaxParamStrLen, "%f", m_bandwidth); break;
Chris@4 63 case 2: snprintf(label, kVstMaxParamStrLen, "%d", m_harmonics); break;
Chris@4 64 case 3: snprintf(label, kVstMaxParamStrLen, "%f", m_reduction); break;
Chris@4 65 }
Chris@0 66 }
Chris@0 67
Chris@0 68 void
Chris@0 69 Devuvuzelator::getParameterName(VstInt32 index, char *label)
Chris@0 70 {
Chris@0 71 const char *names[NumParams] = {
Chris@0 72 "Pitch",
Chris@0 73 "B/W",
Chris@0 74 "Partials",
Chris@0 75 "Reductn",
Chris@0 76 };
Chris@0 77
Chris@0 78 vst_strncpy(label, names[index], kVstMaxParamStrLen);
Chris@0 79 }
Chris@0 80
Chris@0 81 Devuvuzelator::Devuvuzelator(audioMasterCallback cb) :
Chris@0 82 AudioEffect(cb, 0, NumParams),
Chris@0 83 m_sampleRate(0),
Chris@0 84 m_input(0),
Chris@0 85 m_output(0),
Chris@0 86 m_fftsize(FFTSIZE),
Chris@7 87 m_winsize(WINSIZE),
Chris@5 88 m_increment(m_winsize/2),
Chris@9 89 m_filtersecs(FILTERSECS),
Chris@0 90 m_fill(0),
Chris@0 91 m_read(0)
Chris@0 92 {
Chris@4 93 m_buffer = new float[m_winsize];
Chris@4 94 m_outacc = new float[m_winsize * 2];
Chris@4 95 m_window = new double[m_winsize];
Chris@9 96 m_frame = new double[m_fftsize];
Chris@9 97 m_spare = new double[m_fftsize];
Chris@0 98 m_real = new double[m_fftsize];
Chris@0 99 m_imag = new double[m_fftsize];
Chris@4 100 m_medians = new MedianFilter<double> *[m_fftsize/2+1];
Chris@0 101
Chris@4 102 for (int i = 0; i < m_winsize; ++i) {
Chris@4 103 m_window[i] = 0.5 - 0.5 * cos(2 * M_PI * i / m_winsize);
Chris@4 104 }
Chris@4 105 for (int i = 0; i < m_fftsize/2+1; ++i) {
Chris@4 106 m_medians[i] = 0;
Chris@0 107 }
Chris@0 108
Chris@4 109 m_fundamental = 230;
Chris@0 110 m_bandwidth = 60;
Chris@0 111 m_harmonics = 3;
Chris@4 112 m_reduction = 30;
Chris@0 113
Chris@2 114 setUniqueID('qmvz');
Chris@0 115 setNumInputs(1);
Chris@0 116 setNumOutputs(1);
Chris@0 117 canProcessReplacing(true);
Chris@0 118 canDoubleReplacing(false);
Chris@0 119
Chris@0 120 reset();
Chris@0 121 }
Chris@0 122
Chris@0 123 Devuvuzelator::~Devuvuzelator()
Chris@0 124 {
Chris@0 125 delete[] m_buffer;
Chris@0 126 delete[] m_outacc;
Chris@9 127 delete[] m_frame;
Chris@9 128 delete[] m_spare;
Chris@0 129 delete[] m_real;
Chris@0 130 delete[] m_imag;
Chris@0 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@0 136 }
Chris@0 137
Chris@0 138 void
Chris@0 139 Devuvuzelator::reset()
Chris@0 140 {
Chris@4 141 for (int i = 0; i < m_winsize; ++i) {
Chris@0 142 m_buffer[i] = 0.f;
Chris@0 143 }
Chris@4 144 for (int i = 0; i < m_winsize*2; ++i) {
Chris@0 145 m_outacc[i] = 0.f;
Chris@0 146 }
Chris@0 147 m_fill = 0;
Chris@0 148 m_read = 0;
Chris@4 149 for (int i = 0; i < m_fftsize/2+1; ++i) {
Chris@4 150 if (m_medians[i]) m_medians[i]->reset();
Chris@4 151 }
Chris@0 152 }
Chris@0 153
Chris@0 154 void
Chris@0 155 Devuvuzelator::runImpl(unsigned long sampleCount)
Chris@0 156 {
Chris@0 157 if (!m_input || !m_output) return;
Chris@0 158
Chris@4 159 const int sc = sampleCount;
Chris@0 160
Chris@9 161 float *output = m_output;
Chris@9 162 if (m_input == m_output) {
Chris@9 163 output = (float *)alloca(sampleCount * sizeof(float));
Chris@9 164 }
Chris@0 165
Chris@9 166 int oi = 0;
Chris@9 167 for (int ii = 0; ii < sc; ++ii) {
Chris@0 168
Chris@9 169 output[oi++] = m_outacc[m_read++];
Chris@4 170 if (m_fill == m_winsize) {
Chris@0 171
Chris@0 172 processFrame();
Chris@0 173
Chris@4 174 for (int j = m_increment; j < m_winsize; ++j) {
Chris@0 175 m_buffer[j - m_increment] = m_buffer[j];
Chris@0 176 }
Chris@0 177
Chris@4 178 for (int j = m_increment; j < m_winsize*2; ++j) {
Chris@0 179 m_outacc[j - m_increment] = m_outacc[j];
Chris@0 180 }
Chris@0 181
Chris@4 182 for (int j = m_winsize*2 - m_increment; j < m_winsize*2; ++j) {
Chris@0 183 m_outacc[j] = 0.f;
Chris@0 184 }
Chris@0 185
Chris@8 186 m_fill = m_fill - m_increment;
Chris@8 187 m_read = m_read - m_increment;
Chris@0 188 }
Chris@9 189 m_buffer[m_fill] = m_input[ii];
Chris@9 190 ++m_fill;
Chris@8 191 }
Chris@0 192
Chris@9 193 if (m_input == m_output) {
Chris@9 194 for (int i = 0; i < sc; ++i) m_output[i] = output[i];
Chris@9 195 }
Chris@0 196 }
Chris@0 197
Chris@0 198 void
Chris@0 199 Devuvuzelator::processFrame()
Chris@0 200 {
Chris@0 201 for (int i = 0; i < m_fftsize; ++i) {
Chris@8 202 m_frame[i] = 0.0;
Chris@4 203 }
Chris@4 204
Chris@4 205 int ix = m_fftsize - m_winsize/2;
Chris@4 206 while (ix < 0) ix += m_fftsize;
Chris@4 207 for (int i = 0; i < m_winsize; ++i) {
Chris@8 208 m_frame[ix++] += m_buffer[i] * m_window[i];
Chris@0 209 if (ix == m_fftsize) ix = 0;
Chris@0 210 }
Chris@0 211
Chris@8 212 fft(m_fftsize, false, m_frame, 0, m_real, m_imag);
Chris@0 213
Chris@9 214 processSpectralFrame();
Chris@0 215
Chris@0 216 for (int i = 0; i < m_fftsize/2-1; ++i) {
Chris@3 217 m_real[m_fftsize-i-1] = m_real[i+1];
Chris@3 218 m_imag[m_fftsize-i-1] = -m_imag[i+1];
Chris@0 219 }
Chris@0 220
Chris@8 221 fft(m_fftsize, true, m_real, m_imag, m_frame, m_spare);
Chris@0 222
Chris@4 223 ix = m_fftsize - m_winsize/2;
Chris@4 224 while (ix < 0) ix += m_fftsize;
Chris@4 225 for (int i = 0; i < m_winsize; ++i) {
Chris@8 226 m_outacc[m_winsize + i] += m_frame[ix++];
Chris@0 227 if (ix == m_fftsize) ix = 0;
Chris@0 228 }
Chris@0 229 }
Chris@0 230
Chris@0 231 AudioEffect *createEffectInstance(audioMasterCallback audioMaster)
Chris@0 232 {
Chris@0 233 return new Devuvuzelator(audioMaster);
Chris@0 234 }
Chris@0 235
Chris@1 236