Welcome, Guest
Username: Password: Remember me
  • Page:
  • 1
  • 2

TOPIC: Octaver Pedal.

Octaver Pedal. 5 years 11 months ago #19

  • JR
  • JR's Avatar
  • OFFLINE
  • Senior Member
  • Posts: 77
  • Thank you received: 31
  • Karma: 6
The octaver effect generates an octaved signal which is derived from the original guitar input signal by halving (octave-down) or doubling (octave-up) the frequency. In order to do it, a small portion of the signal is stored in a buffer and then played at half or double rate.

The octaver.ino pedal can do an octave-down and octave-up. The potentiometer 0 controls the mode, the first 1/3 of the turn is octave-down, the middle point is normal sound and the last 1/3 of the turn is octave-up.

To implement the effect two buffers are used in parallel to store the signal and playing it again at double rate. The buffers are written at the same time but they are read with different indexes. When buffer A is starting, buffer B is in the middle point, and therefore when buffer A is in the middle point, buffer B is finishing. Each buffer writes in a different DAC (DAC0 and DAC1) which are hardware summed out of Arduino.
I did this buffer mistmatch in order to avoid the popping effect which is very common in digital pitch shifted effects.
  • Potentiometer0: The rotation selects octave-down, normal or octave-up mode.
  • Potentiometer1: Not used.
  • Potentiometer2: Volume control.
  • Mix Switch: when selected it mixes the original and the octaved signal

octaver.ino
// Licensed under a Creative Commons Attribution 3.0 Unported License.
// Based on rcarduino.blogspot.com previous work.
// www.electrosmash.com/pedalshield
 
/*octaver.ino creates an octave-up or octave-down signal from the original one.*/
 
int in_ADC0, in_ADC1;  //variables for 2 ADCs values (ADC0, ADC1)
int POT0, POT1, POT2, out_DAC0, out_DAC1; //variables for 3 pots (ADC8, ADC9, ADC10)
int LED = 3;
int FOOTSWITCH = 7; 
int TOGGLE = 2; 
 
#define MAX_DELAY 10000
uint16_t sDelayBuffer0[MAX_DELAY-1];
uint16_t sDelayBuffer1[MAX_DELAY-1];
unsigned int write_pt=0;
unsigned int read_pt_A=0, read_pt_B= MAX_DELAY/2;
unsigned int Delay_Depth, increment, divider=0, buffer0, buffer1;
 
void setup()
{
  //turn on the timer clock in the power management controller
  pmc_set_writeprotect(false);
  pmc_enable_periph_clk(ID_TC4);
 
  //we want wavesel 01 with RC 
  TC_Configure(TC1, 1, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK2);
  TC_SetRC(TC1, 1, 238); // sets <> 44.1 Khz interrupt rate 109
  TC_Start(TC1, 1);
 
  // enable timer interrupts on the timer
  TC1->TC_CHANNEL[1].TC_IER=TC_IER_CPCS;
  TC1->TC_CHANNEL[1].TC_IDR=~TC_IER_CPCS;
 
  //Enable the interrupt in the nested vector interrupt controller 
  //TC4_IRQn where 4 is the timer number * timer channels (3) + the channel number 
  //(=(1*3)+1) for timer1 channel1 
  NVIC_EnableIRQ(TC4_IRQn);
 
  //ADC Configuration
  ADC->ADC_MR |= 0x80;   // DAC in free running mode.
  ADC->ADC_CR=2;         // Starts ADC conversion.
  ADC->ADC_CHER=0x1CC0;  // Enable ADC channels 0,1,8,9 and 10  
 
  //DAC Configuration
  analogWrite(DAC0,0);  // Enables DAC0
  analogWrite(DAC1,0);  // Enables DAC0
}
 
void loop()
{
  //Read the ADCs
  while((ADC->ADC_ISR & 0x1CC0)!=0x1CC0);// wait for ADC 0,1,8,9,10 conversion complete.
  in_ADC0=ADC->ADC_CDR[7];               // read data from ADC0
  in_ADC1=ADC->ADC_CDR[6];               // read data from ADC1  
  POT0=ADC->ADC_CDR[10];                 // read data from ADC8        
  POT1=ADC->ADC_CDR[11];                 // read data from ADC9   
  POT2=ADC->ADC_CDR[12];                 // read data from ADC10     
}
 
void TC4_Handler() //Interrupt at 44.1KHz rate (every 22.6us)
{
  TC_GetStatus(TC1, 1); //Clear status interrupt to be fired again.
 
  //Store current readings  
  sDelayBuffer0[write_pt] = in_ADC0;
  sDelayBuffer1[write_pt] = in_ADC1;
 
  //Adjust Delay Depth based in pot2 position.
  Delay_Depth = MAX_DELAY-1;
 
  //Increse/reset delay counter.
  write_pt++;
  if(write_pt >= Delay_Depth) write_pt = 0; 
 
  out_DAC0 = ((sDelayBuffer0[read_pt_A]));
  out_DAC1 = ((sDelayBuffer1[read_pt_B]));
 
  if (POT0>2700)
  { 
    read_pt_A = read_pt_A + 2;
    read_pt_B = read_pt_B + 2;
  }
 else if (POT0>1350)
  {
    read_pt_A = read_pt_A + 1;
    read_pt_B = read_pt_B + 1;
  }
 else
 {
   divider++;
   if (divider>=2)
   {
      read_pt_A = read_pt_A + 1;
      read_pt_B = read_pt_B + 1;
      divider=0;
    }
  }
 
  if(read_pt_A >= Delay_Depth) read_pt_A = 0; 
  if(read_pt_B >= Delay_Depth) read_pt_B = 0; 
 
  //Add volume control with POT2
  out_DAC0=map(out_DAC0,0,4095,1,POT2);
  out_DAC1=map(out_DAC1,0,4095,1,POT2);
 
  //Write the DACs
  dacc_set_channel_selection(DACC_INTERFACE, 0);       //select DAC channel 0
  dacc_write_conversion_data(DACC_INTERFACE, out_DAC0);//write on DAC
  dacc_set_channel_selection(DACC_INTERFACE, 1);       //select DAC channel 1
  dacc_write_conversion_data(DACC_INTERFACE, out_DAC1);//write on DAC
}

You can listen this Octaver effect in SoundCloud.

File Attachment:

File Name: octaver.rar
File Size: 2 KB


There are a lot of ways to implement octavers or pitch-shifting effects. In this code I have implemented a Delay Based Pitch Shifting Algorithm described by D. Goswami, H. Narula and C. Rogers.

To improve the performance and remove the audible popping a fade out technique could be used:
Two 30ms long buffers hold the channel buffers A and B. Both channels begin with a 30ms delay but the gain of channel A starts at one while the gain of channel B is zero. The delay of channel A is steadily decreased and as the delay starts to approach zero, the gain begins to steadily decrease while channel B’s gain begins to increase and its delay decrease. Here the gain of channel A and channel B are both decreasing and increasing respectively at the same rate to maintain their sum at one, keeping a constant amplitude out. This crossover area between the two gains is referred to as crossfading because one channel fades out and the other fades in. The crossfading helps the transition from a close to 0ms delay to 30ms delay seem continuous and smooth.
keep it simple
Last Edit: 5 years 10 months ago by JR.
The administrator has disabled public write access.
The following user(s) said Thank You: AaronMichael

Octaver Pedal. 5 years 11 months ago #20

  • JR
  • JR's Avatar
  • OFFLINE
  • Senior Member
  • Posts: 77
  • Thank you received: 31
  • Karma: 6
There are a lot of ways to implement octavers or pitch-shifting effects. D. Goswami, H. Narula and C. Rogers have the best study about Real-Time DSP Pitch Shifting applicable to Arduino/C programming I have ever read.
I am quoting below the most interesting parts:
2.0. Pitch Shifting Techniques

2.1. Zero-Padding

Zero-padding is very simple pitch shifting method because it adds or removes values at zero crossing to change the pitch. However, it produces artifacts that swamp the signal without intensive interpolation to keep the speech signal’s slope from abruptly changing. Even, without this problem there are still considerable artifacts because the zero-crossings are not necessarily evenly spaced. Overall, the quality is too poor to make up for its simplicity.

2.2. PSOLA (Pitch Synchronous Overlap/Add)

PSOLA (Pitch Synchronous OverLap/Add) uses a pitch detection algorithm to extract single periods and either overlaps or adds a single pitch period to decrease or increase pitch respectively. It changes the pitch without altering format frequencies, consistent with human voice characteristics and is computationally efficient [1]. Several of its assumptions, such as setting the phase equal to zero, are not completely correct though and lead to artifacts. Spectral discontinuities at boundaries also cause artifacts. PSOLA can only be as accurate as the pitch detection algorithm used and the unvoiced regions can be tricky to handle. Yet another problem is that voiced fricatives contain a buzz in their pitch shifted sound [2]. While, PSOLA produces a better sounding pitch shifted speech than the zero-padding method (its intelligibility is good), the artifacts make the sound unnatural and unpleasing for the listen.

2.3. Physical Modeling

Physical modeling tries to completely separate the vocal tract information from the glottal impulses using inverse filtering techniques. The drawbacks of this method are computationally complexity and artifacts produce from the inability to exactly model the inverse filter speech to completely separate vocal tract info from impulses [1]. The artifacts are less noticeable than in methods such as PSOLA but its computational complexity is much greater.

2.4. Frequency Domain Methods

Frequency domain methods (including phase vocoders) must first transform the speech signal into the frequency domain and then transform it back after the pitch is adjusted. These methods contain spectral leakage, which cause the formant frequencies to shift and most require a transformation back to the time domain [1, 3]. Frequency domain models allow for finer pitch shifts at the cost of increased complexity and shifted formants.

2.5. Delay Based

Delay based methods crossfade between two channels with different varying delays and gains to produce a smoothly transitioned pitched shifted signal. They produce only small artifacts so long as large pitch shifts are not used. They are also fast enough to operate in real-time; however, they do shift and smear the formant frequencies [4]. Delay based methods are less computationally complex than frequency domain methods or physical modeling methods and its results have less artifacts than zero-padding or PSOLA so this method was chosen to be implemented for this project. Details of how the delay based method works are described in Section 3.
keep it simple
Last Edit: 5 years 11 months ago by JR.
The administrator has disabled public write access.

Octaver Pedal. 4 years 11 months ago #173

  • jasolag
  • jasolag's Avatar
  • OFFLINE
  • New Member
  • Posts: 5
  • Karma: 1
Hi JR, I tried using the octaver effect and it sounds pretty good. However, there is a delay between the original sound and the modified sound. Is there a way to reduce this latency to the minimum? Thanks.
The administrator has disabled public write access.

Octaver Pedal. 4 years 11 months ago #174

  • JR
  • JR's Avatar
  • OFFLINE
  • Senior Member
  • Posts: 77
  • Thank you received: 31
  • Karma: 6
The easiest way to reduce the latency could be playing with the current code (octaver.ino) parameters.
Try reducing the value of
#define MAX_DELAY 10000
to something smaller like 8000, 5000, 3000, etc...

There are other ways of implement octaver pedals (as mentioned above) but we did not have time yet to play with other codes...
keep it simple
The administrator has disabled public write access.

Octaver Pedal. 4 years 8 months ago #240

  • dwhacks
  • dwhacks's Avatar
  • OFFLINE
  • New Member
  • Posts: 4
  • Thank you received: 1
  • Karma: 0
Would it be possible to run both octaves at the same time and maybe have a volume adjustement for each (like the EHX Micro POG)?

Is we can get the latency to really low levels this would be pretty amazing.
The administrator has disabled public write access.

Octaver Pedal. 3 years 11 months ago #398

Would it be possible to run both octaves at the same time and maybe have a volume adjustement for each (like the EHX Micro POG)?

This is the reason why I ordered the shield a few days ago, I'm still waiting, but I'll probably try building that effect as soon as I get my hands on it!
I know how to handle an Arduino, but unfortunately I do not know anything about sound processing (I'm a visual designer :whistle: ). I'm going to learn a lot of stuff then... So I'm wondering, is there any particular issue in doing that?

:guitargibso
The administrator has disabled public write access.

Octaver Pedal. 3 years 11 months ago #399

  • Ray
  • Ray's Avatar
  • OFFLINE
  • Moderator
  • Posts: 692
  • Thank you received: 146
  • Karma: 41
its a good idea, I never though about doing that but its cool!
It may be some limitation but I reckon that its plausible, just generating both signals and summing them at the end of it...
You can start a new topic once you try to do it so we can contribute ;)
The administrator has disabled public write access.

Octaver Pedal. 3 years 8 months ago #439

  • vittoles
  • vittoles's Avatar
  • OFFLINE
  • New Member
  • Posts: 2
  • Karma: 0
Hi guys!
my name is Dan,just starting in Arduino world.
i wanna mod POT0 to have multiple octave down value.
i mean normal position ,no pitch full clockwise, and maybe 10 "step" to get 2 octave down fully counter clockwise...
how to code that please?
regards.
The administrator has disabled public write access.

Octaver Pedal. 3 years 8 months ago #441

  • Ray
  • Ray's Avatar
  • OFFLINE
  • Moderator
  • Posts: 692
  • Thank you received: 146
  • Karma: 41
Welcome Dan :)
If i understood it correctly ( maybe not :whistle: ) its a very cool idea, the code always gives you 1 octave down or up.
The key part of the code is this:
  if (POT0>2700)
  { 
    read_pt_A = read_pt_A + 2;
    read_pt_B = read_pt_B + 2;
  }
 else if (POT0>1350)
  {
    read_pt_A = read_pt_A + 1;
    read_pt_B = read_pt_B + 1;
  }
 else
 {
   divider++;
   if (divider>=2)
   {
      read_pt_A = read_pt_A + 1;
      read_pt_B = read_pt_B + 1;
      divider=0;
    }
  }

basically:
- if POT0 is full clockwise: reduces the buffer 1 sample
- if POT0 is middle: keeps buffer same size
- if POT0 is full anticlockwise: use a divider to increase de size 1 sample.

try changing the numbers on:
read_pt_A = read_pt_A + 2;
(try a 1, 2, 3, 4) and you have other octaves, although as far as I remember the super high ones sound a bit odd.

you can also change the range of the POT0 (POT0>2700) or (POT0>1350) adding more ranges to more octaves.
The administrator has disabled public write access.

Octaver Pedal. 3 years 8 months ago #444

  • vittoles
  • vittoles's Avatar
  • OFFLINE
  • New Member
  • Posts: 2
  • Karma: 0
my problem is to get 1/2 octave down , 1/3 octave down,1/4 octave down..
i can't find how to divide 1 octave in 5 pot position...
best regards.
The administrator has disabled public write access.
  • Page:
  • 1
  • 2
Time to create page: 0.439 seconds
Powered by Kunena Forum
Joomla SEF URLs by Artio