Calculating decay by 60db time for comb delay?

DSP, Plugin and Host development discussion.
RELATED
PRODUCTS

Post

Here's what my delay looks like when it's not supposed to be working 'in chunks' - ie, this is meant to process the entire file.

Code: Select all

	public short[] combProcess(short input[]){

		short[] output = new short [input.length + delaySamples];
		int outputSample = 0;

		// For each sample in the output array
		for (int n=0; n < output.length; n++){

			// delayedPosition is only set once n is large enough
			int delayedPosition = n-delaySamples;

			if (delayedPosition < 0) {
				delayedInput = 0;
				delayedOutput = 0;
			}
			else {
				delayedInput = input[delayedPosition];
				delayedOutput = output[delayedPosition];
			}

			short inputSample = 0;

			if (n<input.length){
			   inputSample = input[n];
			}

			if (filter.equals("Standard Feedback Filter")){
				outputSample = (int)((inputSample) + (feedbackFactor*delayedOutput/100));
			}
			else{
				outputSample = (int)((delayedInput) + (feedbackFactor*delayedOutput/100));
			}

			// Limits outputSample to max 16bit (short) value
			int limit = outputSample;
			if (limit > 32767){
				limit = 32767;
			}
			else if (limit < -32767){
				limit = -32767;
			}

			// Turns int back into short value in output array after manipulation and limiting
			output[n] = (short)limit;

		}// End of for loop
	  return output;
	 }
Sorry to keep posting code :(

I don't really see how circular buffers are gonna help :?

Post

wtf :) pseudo-pseudo-code:

Code: Select all

process(indata, outdata, length)
{
  for(i = 0; i < length; ++i)
  {
    delay[i] = indata[i]
    outdata[i] = delay[(circularIndex - delayLength) % delayBufferLength];
    ++circularIndex;
    if(circularIndex >= delayBufferLength)
      circularIndex = 0;
  }
}
This can be optimised to get rid of the if-statement and the % operator though. But start out without optimising.
Stefan H Singer
Musician, coder and co-founder of We made you look Web agency

Post

stefancrs wrote:wtf :) pseudo-pseudo-code:

Code: Select all

process(indata, outdata, length)
{
  for(i = 0; i < length; ++i)
  {
    delay[i] = indata[i]
    outdata[i] = delay[(circularIndex - delayLength) % delayBufferLength];
    ++circularIndex;
    if(circularIndex >= delayBufferLength)
      circularIndex = 0;
  }
}
This can be optimised to get rid of the if-statement and the % operator though. But start out without optimising.
hi

thanks - i just edited one of my posts to say:

'if i load in a file 20 seconds long, it is split up into chunks of 1second, then fired chunk by chunk to the delay unit. the delay unit has to process each chunk and then fire them off to the next unit.

that is why you need a buffering system. '

the chunks know nothing about each other, as each chunk means a new run through a method. so that's why you need to buffer the end echoes from the last chunk and add them to the current/incoming chunk.

does that make more sense for why i'm doing it this way?

am i still mad?

i understand the code you guys have given me. but i can't access the file all at once, and i can't access it continuously...

Post

You don't need to access it all at once or conti.. what? you mean that you can't access it block by block? Like, first you get chunk 1 from it and then not chunk 2?
Stefan H Singer
Musician, coder and co-founder of We made you look Web agency

Post

stefancrs wrote:You don't need to access it all at once or conti.. what? you mean that you can't access it block by block? Like, first you get chunk 1 from it and then not chunk 2?
sorry for not being clear - yeah, the combProcess method is called over and over, each time the next chunk comes in

Post

So what is the problem? Why can't the comb object have a delay-buffer in itself like in my example? The code I posted works with arbritrary sized chunks, the delay from the last chunk will automatically "move on" to the next one.
Stefan H Singer
Musician, coder and co-founder of We made you look Web agency

Post

will your method return/output chunks of equal size to the ones that go in?

Post

I don't understand the problem. Just keep the delay buffer and counter as members of the class that does this, instead of having them local to the method...

edit: and yes, the way stefancrs suggested will not change the chunk size. Why should it? Essentially, it's code that works sample by sample, executed as many times as there are samples in the chunk.

Post

heh - the problem is probably just in my head - that sounds like a good idea guys

keep the delay buffer and counters in the class not in the method and it will remember them each time a new chunk comes in.

i should be able to just change my code to make the varaibles global, right?

Post

avoid global variables, use normal members and instantiate a comb object. apart from that, yes.
Stefan H Singer
Musician, coder and co-founder of We made you look Web agency

Post

The Beatsmith wrote:will your method return/output chunks of equal size to the ones that go in?
btw, in what way could this be any clearer than in my example? I read "length" number of samples from input and write "length" number of samples to output.
Stefan H Singer
Musician, coder and co-founder of We made you look Web agency

Post

The Beatsmith wrote:heh - the problem is probably just in my head
Yes, I think you simply don't see the wood for the trees :)

Your method is absolutely overcomplicated.

Try something like this (sorry, only pseudo java...):

Code: Select all

class delay
{
    delay( int indelaysamples, float infeedback, float inmix )
    {
       mix = inmix;
       feedback = infeedback;
       delayPointer = 0;
       delaysamples = indelaysamples;

       // clear buffer
    }

    float[] process ( int chunkSize, float[] inSamples )
    {
        float out[ chunkSize ];

        for ( int i = 0; i < chunkSize, i++ )
        {
            float in = inSamples[ i ];
            float del = delayBuffer[ delayPointer ];

            out[ i ] = in + mix * ( del - in );
            delayBuffer[ delayPointer++ ] = in + feedback * del;

            delayPointer %= delaysamples

        }
        return out;
    }
   
    int delayPointer;
    int delaysamples;
    float delayBuffer[ maxDelay ]; 
    float feedback;
    float mix;
}

Quickly scribbled, incomplete, buggy, but that's about all it takes.

Cheers,

;) Urs

Post

thanks for all your help on this guys

now got the delay working well :)

the only problem i'm getting is the 'logic' of getting the end echoes added on, after the file has stopped playing back. here's the code for my delay:

Code: Select all

	public short[] combProcessChunked(short input[]){

		short[] outputArray = new short[input.length];
		short[] finalEchoes = new short[input.length];

		int totalLength = (input.length + delayLength);
		int samplesToMove = Math.min(outputArray.length, sustainSampleCount);

		short[] finalEchoes = new short[samplesToMove];

		// Do the processing
		for (int i=0; i < input.length; i++) {

			double inputSample = (double) input[i];
			double delaySample = delayBuffer[readIndex++];

			// Output is from delay buffer

			// Apply gain and feedback to sample
			inputSample += (delaySample * feedbackFactor) / 100; //* gain;

			// Store sample in delay buffer
			outputArray[i] = (short)(inputSample + (delaySample - inputSample));
			delayBuffer[writeIndex++] = (short)inputSample;

			// Update buffer indices
			readIndex  %= delayBufferSize;
			writeIndex %= delayBufferSize;
		}
		return outputArray;
}
And to do the echo, it would be much the same, type of thing, but using outputArray[n] += (short)delaySample;

But i can't figure out how to get a suitable 'if' statement to say 'if you've reached the end of file then just output the echoes'. I could do it in the for loop, 'if i>input.length' but then i'm already in the for loop... i dunno, perhaps i'm being dim (again), but is there another clever/simple way of doing this?

Sorry, i'm knackered hope you can understand what the problem is. Thank you!

Eddie

Post Reply

Return to “DSP and Plugin Development”