Java Synthesizer, Part 13 – Echo

Echo, or reverb, is probably one of the simplest functions to implement so far. I don’t have anything else to pair up with it, so this entry may prove to be the shortest of the group.

Initially, I wanted a buffer array at 64K elements, but Netbeans threw errors when I used a range of 0 to 64,000, so I dropped it down to 32K within the circuit object definition. That’s still 2 seconds of loop time, with a 16,000 sampling rate. So, I’m not going to bother improving the code until the need arises later. Everything else is straightforward. One pointer keeps track of where the next sample will be written in the array, and a second points to where to read from. Reading or writing increments that pointer. The jSlider controls max loop, delay time and decay rate.

The write pointer goes from 0 to 31,999, which gives 2 seconds before the next set of data starts overwriting the old sounds. By changing loop max, I can get the older sounds mixed in with the new ones in less time. The echo playback effect is based on how far “read” lags behind “write”. So, delay time is the number of elements the read pointer is offset from the write pointer, with error checking to ensure that delay time is less than loop max. Finally, when I mix the new data with the old, the decay rate sets how quickly the sounds go to zero. Actually, the rate is just a multiplier, where:

buffer[writePtr] = decay * buffer[writePtr] + newData

Just to keep things simple, the data going into the echo buffer is the finished output from vca1, which then goes to the VCF module if an FFT filter is to be used. The best echo effect is with delayVal around 2000, and decay around 0.25, but the sheer fact that echo works at all is really cool.

echo echo1 = new echo(32000, 10000, 0.75); // int loopVal, int delayVal, double decay

addBuffer for-loop:

for(int pCnt = 0; pCnt < 320; pCnt++){ // Build up the sample
osc2.nextSlice(); // Increment oscillator 2
osc3.setFreq(bender1.out(osc1.freq)); // Pitch bend oscillator 3 relative to oscillator 1’s frequency

hold = (vca1.out( adsr1.nextSlice((osc1.nextSlice() + osc3.nextSlice()) / 2 )) + echo1.readOldEcho())/2; // Mix osc 1 & 2, run through ADSR and amplify with VCA 1

if(! vcf1.filterOn) shortBuffer.put( (short)( hold ) ); // Prep sound engine buffer if not using filter
else vcf1.addToChunk(pCnt, new Complex(hold, 0)); // Using filter. Add data to filter buffer


I don’t know what circuit symbol to use for echo. Suggestions?

Raw formatted textfile here.


Leave a comment

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: