Another coding question... (about echoing)
-
- KVRist
- Topic Starter
- 234 posts since 20 Mar, 2004 from Ontario, Canada
I know I had another topic just going.. so please forgive me for being such a pain.
Anyways... I'm trying to allow a user to have control over the number of echoes that should be heard.
So... I have a buffer for "delayed" samples, but I though maybe I would have another array which would keep track of how many times each buffered sample gets played.
Then, if the number of times some sample has been "echoed" passes some user-defined limit, then I wouldn't echo the sample again.
I'm not the best at coming up with algorithms... so I would appreciate any feedback as to whether I'm going in the right direction or not.
Thanks for your patience with me!
Anyways... I'm trying to allow a user to have control over the number of echoes that should be heard.
So... I have a buffer for "delayed" samples, but I though maybe I would have another array which would keep track of how many times each buffered sample gets played.
Then, if the number of times some sample has been "echoed" passes some user-defined limit, then I wouldn't echo the sample again.
I'm not the best at coming up with algorithms... so I would appreciate any feedback as to whether I'm going in the right direction or not.
Thanks for your patience with me!
-
- KVRist
- 334 posts since 18 Apr, 2005 from Sweden
If I were to write an echo plugin, this is the basic algorithm I would use:
Your algorithm isn't bad, but every ounce of CPU time counts in VST coding, so don't use extra memory or CPU cycles if you don't have to.
Hope this gives some food for thought. =)
Code: Select all
while(--sampleFrames) {
for(int i = 0; i < num_echos; i++) {
buffer[buffer_index + (i * delay_time)] +=
(*inputs) / num_echos;
}
buffer_index++;
(*outputs++) = (*inputs++) + buffer[buffer_index];
}
Your algorithm isn't bad, but every ounce of CPU time counts in VST coding, so don't use extra memory or CPU cycles if you don't have to.
Hope this gives some food for thought. =)
-
- KVRist
- Topic Starter
- 234 posts since 20 Mar, 2004 from Ontario, Canada
Thanks - i'll study your suggestion and get back to you.
-
- KVRian
- 922 posts since 26 Mar, 2003 from Guildford, England
you'll need to wrap the buffer index or it will crash, and also clear the buffer just after reading from sa location.
also, yo must make sure that num_echos * delay does nopt exceed the buffer size.
also, yo must make sure that num_echos * delay does nopt exceed the buffer size.
-
- KVRist
- Topic Starter
- 234 posts since 20 Mar, 2004 from Ontario, Canada
What do you mean by this exactly?texture wrote:and also clear the buffer just after reading from sa location.
-
- KVRist
- Topic Starter
- 234 posts since 20 Mar, 2004 from Ontario, Canada
This is what I'm working with so far... it's not working, but it's not crashing (at least).
mSize is 44100 in this case, and the buffer length is the same.
Code: Select all
float curr = 0;
int delay_time = 1000;
int num_echoes = 5;
while (--sampleFrames >= 0)
{
curr = (*in1++);
int index = 0;
for(int i=0; i < num_echoes; i++)
{
index = mCursor + (i * delay_time);
if (index >= mSize)
index %= mSize;
mBuffer[index] += curr / (float)num_echoes;
}
mCursor++;
if (mCursor >= mSize)
mCursor = 0;
(*out1++) = curr + mBuffer[mCursor];
(*out2++) = curr + mBuffer[mCursor];
}
-
- KVRian
- 922 posts since 26 Mar, 2003 from Guildford, England
what about this:
Code: Select all
#include <vector>
template <typename T>
class FixedEchoUnit
{
public:
FixedEchoUnit(size_t size)
: buffer_(size, T(0)) // set to 'size' and initialise with '0'
, feedback_(0)
, index_(0)
, repeats_(1)
, delay_samples_(0)
{
}
bool set_repeats(unsigned repeats);
bool set_delay_samples(unsigned samples);
void set_feedback(float feedback) { feedback_ = feedback; }
inline unsigned get_repeats() const { return repeats_; }
inline unsigned get_delay_samples() const { return delay_; }
inline unsigned get_size() const { return buffer_.size(); }
void process(T input, T& output);
private:
typedef std::vector<T> buffer_type;
typedef typename buffer_type::iterator iterator;
inline size_t wrap(const size_t& v) const { return (v >= get_size()) ? (v - get_size()) : v; }
inline bool check_valid_params(unsigned repeats, unsigned delay_samples) const {
return ((repeats * delay_samples) <= buffer_.size());
}
buffer_type buffer_;
T feedback_;
size_t index_;
unsigned repeats_;
unsigned delay_samples_;
};
template <typename T>
inline void
FixedEchoUnit<T>::process(T input, T& output)
{
output = buffer_[index_] + input;
buffer_[index_] = 0;
size_t idx = index_;
unsigned echo = repeats_;
while (echo-- > 0) {
input *= feedback_;
idx = wrap(idx + delay_samples_);
buffer_[idx] += input;
}
index_ = wrap(++index_);
}
// returns false if the repeats value would have been invalid.
template <typename T>
inline bool
FixedEchoUnit<T>::set_repeats(unsigned repeats)
{
bool r = false;
if (check_valid_params(repeats, delay_samples_)) {
repeats_ = repeats;
r = true;
}
return r;
}
// returns false if the delay time would have been invalid.
template <typename T>
inline bool
FixedEchoUnit<T>::set_delay_samples(unsigned samples)
{
bool r = false;
if (check_valid_params(repeats_, samples)) {
delay_samples_ = samples;
r = true;
}
return r;
}
// in the plugin class
// you'll need to initialise them in the
// initialisation list of the construtor
// and then call set_delay, set_repeats
// and set_feedback to give them resaonable values.
FixedEchoUnit<float> echo_left_;
FixedEchoUnit<float> echo_right_;
// process replacing:
while(--sampleFrames >= 0)
{
echo_left_.process(*in1, *out1);
echo_right_.process(*in2, *out2);
++in1;
++in2;
++out1;
++out2;
}
-
- KVRist
- Topic Starter
- 234 posts since 20 Mar, 2004 from Ontario, Canada
I appreciate you trying to help - but I'm trying to agonize through this so I can wrap my head around it. Also, I'm doing it for a school assignment so I can't really copy your code anyways. I'll try to understand it though to see what's going on.
Thanks again.
Thanks again.
-
- KVRist
- Topic Starter
- 234 posts since 20 Mar, 2004 from Ontario, Canada
Finally!! I got it working!
Thanks for all of your input. I don't know what I'd do without this forum!
Thanks for all of your input. I don't know what I'd do without this forum!