kwave  18.07.70
PitchShiftFilter.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  PitchShiftFilter.cpp - filter for modifying the "pitch_shift"
3  -------------------
4  begin : Wed Nov 28 2007
5  copyright : (C) 2007 by Thomas Eschenbacher
6  email : Thomas.Eschenbacher@gmx.de
7 
8  based on synth_pitch_shift_impl.cc from the aRts project
9 
10  copyright (C) 2000 Jeff Tranter <tranter@pobox.com>
11  (C) 1999 Stefan Westerfeld <stefan@space.twc.de>
12 
13  ***************************************************************************/
14 
15 /***************************************************************************
16  * *
17  * This program is free software; you can redistribute it and/or modify *
18  * it under the terms of the GNU General Public License as published by *
19  * the Free Software Foundation; either version 2 of the License, or *
20  * (at your option) any later version. *
21  * *
22  ***************************************************************************/
23 
24 #include "config.h"
25 #include <complex>
26 #include <math.h>
27 
28 #include "libkwave/Sample.h"
29 #include "libkwave/Utils.h"
30 
31 #include "PitchShiftFilter.h"
32 
33 //***************************************************************************
35  :Kwave::SampleSource(Q_NULLPTR), m_buffer(blockSize()),
36  m_speed(1.0), m_frequency(0.5), m_dbuffer(),
37  m_lfopos(0), m_b1pos(0), m_b2pos(0), m_b1inc(0), m_b2inc(0),
38  m_b1reset(false), m_b2reset(false), m_dbpos(0)
39 {
40  initFilter();
41 }
42 
43 //***************************************************************************
45 {
46 }
47 
48 //***************************************************************************
50 {
51  emit output(m_buffer);
52 }
53 
54 //***************************************************************************
56 {
57  m_dbuffer.resize(MAXDELAY);
58  for (m_dbpos = 0; m_dbpos < MAXDELAY; m_dbpos++)
59  m_dbuffer[m_dbpos] = 0;
60 
61  m_dbpos = 0;
62  m_lfopos = 0;
63 
64  if (m_speed <= float(1.0)) {
65  m_b1pos = m_b2pos = 0.0;
66  m_b1inc = m_b2inc = 1.0f - m_speed;
67  } else {
68  /* not yet sure what would be a nice initialization here? */
69  m_b1pos = m_b2pos = 0.0;
70  m_b1inc = m_b2inc = 0.0;
71  }
72 }
73 
74 //***************************************************************************
76 {
77  const Kwave::SampleArray &in = data;
78 
79  Q_ASSERT(Kwave::toInt(in.size()) <= m_dbuffer.size());
80  bool ok = m_buffer.resize(in.size());
81  Q_ASSERT(ok);
82  Q_UNUSED(ok);
83 
84  const float pi2 = 2 * float(M_PI);
85  const float lfoposinc = static_cast<float>(m_frequency);
86 
87  for (unsigned int pos = 0; pos < m_buffer.size(); pos++) {
88  /*
89  * fill delay buffer with the input signal
90  */
91  m_dbuffer[m_dbpos] = sample2float(in[pos]);
92 
93  m_lfopos += lfoposinc;
94  m_lfopos -= floorf(m_lfopos);
95 
96  if (m_lfopos < float(0.25)) {
97  m_b1reset = m_b2reset = false;
98  }
99 
100  /*
101  * _speed < 1.0 (downpitching)
102  *
103  * start with current sample and increase delay slowly
104  *
105  * _speed > 1.0 (uppitching)
106  *
107  * start with a sample from long ago and slowly decrease delay
108  */
109  if (!m_b1reset && m_lfopos > float(0.25)) {
110  if (m_speed <= float(1.0)) {
111  m_b1pos = 0;
112  m_b1inc = 1.0f - m_speed;
113  } else {
114  m_b1inc = 1.0f - m_speed;
115  m_b1pos = 10.0f + ((- m_b1inc) * (1.0f / lfoposinc));
116  /* 10+ are not strictly necessary */
117  }
118  m_b1reset = true;
119  }
120 
121  if (!m_b2reset && (m_lfopos > 0.75f)) {
122  if (m_speed <= float(1.0)) {
123  m_b2pos = 0;
124  m_b2inc = 1.0f - m_speed;
125  } else{
126  m_b2inc = 1.0f - m_speed;
127  m_b2pos = 10.0f + ((-m_b2inc) * (1.0f / lfoposinc));
128  /* 10+ are not strictly necessary */
129  }
130  m_b2reset = true;
131  }
132 
133  m_b1pos += m_b1inc;
134  m_b2pos += m_b2inc;
135 
136  int position, position1;
137  float error, int_pos;
138 
139  /*
140  * Interpolate value from buffer position 1
141  */
142  error = modff(m_b1pos, &int_pos);
143 
144  position = m_dbpos - Kwave::toInt(int_pos);
145  if (position < 0)
146  position += MAXDELAY;
147  position1 = position - 1;
148  if (position1 < 0)
149  position1 += MAXDELAY;
150 
151  const float b1value = m_dbuffer[position] * (1 - error) +
152  m_dbuffer[position1] * error;
153 
154  /*
155  * Interpolate value from buffer position 2
156  */
157  error = modff(m_b2pos,&int_pos);
158 
159  position = m_dbpos - Kwave::toInt(int_pos);
160  if (position < 0)
161  position += MAXDELAY;
162  position1 = position-1;
163  if ( position1 < 0)
164  position1 += MAXDELAY;
165 
166  const float b2value = m_dbuffer[position] * (1 - error) +
167  m_dbuffer[position1] * error;
168 
169  /*
170  * Calculate output signal from these two buffers
171  */
172 
173  const float lfo = (sinf(pi2 * m_lfopos) + 1.0f) / 2.0f;
174 
175  /* position sin lfo variable
176  *------------------------------------------------------------------
177  * lfo value: 0.25 1 1 => buffer 2 is used
178  * 0.75 -1 0 => buffer 1 is used
179  */
180 
181  m_buffer[pos] = float2sample(b1value * (1.0f - lfo) + b2value * lfo);
182 
183  /*
184  * increment delay buffer position
185  */
186  m_dbpos++;
187  if (m_dbpos == MAXDELAY)
188  m_dbpos = 0;
189  }
190 
191 }
192 
193 //***************************************************************************
194 void Kwave::PitchShiftFilter::setSpeed(const QVariant speed)
195 {
196  float new_speed = QVariant(speed).toFloat();
197  if (qFuzzyCompare(new_speed, m_speed)) return; // nothing to do
198 
199  m_speed = new_speed;
200  initFilter();
201 }
202 
203 //***************************************************************************
204 void Kwave::PitchShiftFilter::setFrequency(const QVariant freq)
205 {
206  float new_freq = QVariant(freq).toFloat();
207  if (qFuzzyCompare(new_freq, m_frequency)) return; // nothing to do
208 
209  m_frequency = new_freq;
210  initFilter();
211 }
212 
213 //***************************************************************************
214 //***************************************************************************
Definition: App.h:33
QVector< float > m_dbuffer
int toInt(T x)
Definition: Utils.h:127
static float sample2float(const sample_t s)
Definition: Sample.h:65
virtual ~PitchShiftFilter() Q_DECL_OVERRIDE
Kwave::SampleArray m_buffer
virtual void goOn() Q_DECL_OVERRIDE
void output(Kwave::SampleArray data)
unsigned int size() const
void input(Kwave::SampleArray data)
static sample_t float2sample(const float f)
Definition: Sample.h:57
void setFrequency(const QVariant freq)
void setSpeed(const QVariant speed)
bool resize(unsigned int size) Q_REQUIRED_RESULT