Pages: 1 [2] 3   Go Down
Author Topic: My stab at an Arduino Synth  (Read 7219 times)
0 Members and 1 Guest are viewing this topic.
NY
Offline Offline
Newbie
*
Karma: 0
Posts: 1
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey narbotic

Im trying to modify your code so I can have a bunch of bend sensors control the frequency and the timing so I get random sound based on the sensor but I didnt have any success. I can easily do that by PWM but that doesnt make any interesting sound. Anyways Im gonna include my code for one sensor..If you or anyone can look at it and tell me whats wrong with it Ill appreciate it. again Im not looking for any particular note...Im interested in the noise that it can randomly generate.


#include <math.h>  // requires an Atmega168 chip
#define outpin 4
int val1;
int speakerOut = 4;
int sensor1 = 1;
int freq,t;

void setup() {
      Serial.begin(9600);
      pinMode (speakerOut, OUTPUT);
}


void loop(){
      val1 = analogRead(sensor1);
      freqout((int)val1, t);
        delay(10);
}
 

      void freqout(int freq, int t)
{

  int hperiod;                               //calculate 1/2 period in us
 val1 = 440;
 hperiod = 500000 / freq;              
Serial.println(freq);
Serial.println(hperiod);
 long cycles, i;
 cycles = ((long)freq * (long)t) / 1000;    // calculate cycles
 for (i=0; i<= cycles; i++){              // play note for t ms  
  
    digitalWrite(speakerOut, HIGH);
    delayMicroseconds(hperiod);
    digitalWrite(speakerOut, LOW);
    delayMicroseconds(hperiod);     // - 1 to make up for fractional microsecond in digitaWrite overhead
 }
}
Logged

0
Offline Offline
Sr. Member
****
Karma: 0
Posts: 267
dinosaur cork
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Here's my synth code.
Sorry there's not more comments.

It has a bunch of pots hooked up to A/D
and an encoder (to change programs - on pins 2 & ??

I have an R2R (4 bit) ladder on board, but haven't tried it out yet - it needs some serious pin rearranging to get the R2R on better pins for bitmath manipulation.



Code:
// Synth code by Paul Badger   2007
#include <math.h>

#define outpin 9 // high order output

//analog inputs
#define pitchPot 5
#define modPot  4  
#define speedPot 1
#define phasePot 2
#define jukePot  3

#define stopPin 5

#define LEDbit0 10
#define LEDbit1 11
#define LEDbit2 12
#define LEDbit3 13

int randomWalkLowRange;
int randomWalkHighRange;



int val, runlevel;
volatile int encoder0PinA = 2;
volatile int encoder0PinB = 4;
volatile unsigned int encoder0Pos = 0;
int n = LOW;

int ptime, range, strt, inc;
int   k,  x, dur, freq, t,;
int i, j;
int sens, adder;

float ps, fpitch;         // variable for pow pitchShift routine

float noteval;
//note values
float A     = 14080;
float AS    = 14917.2;
float B     = 15804.3;
float C     = 16744;
float CS    = 17739.7;
float D     = 18794.5;
float DS    = 19912.1;
float E     = 21096.2;
float F     = 22350.6;
float FS    = 23679.6;
float G     = 25087.7;
float GS    = 26579.5;
float A2    = 28160;
float A2S   = 29834.5;
float B2    = 31608.5;
float C2    = 33488.1;
float C2S   = 35479.4;
float D2    = 37589.1;
float D2S   = 39824.3;
float E2    = 42192.3;
float F2    = 44701.2;
float F2S   = 47359.3;
float G2    = 50175.4;
float G2S   = 53159;
float A3    = 56320;
//rhythm values
int wh = 1024;
int h  = 512;
int dq = 448;
int q = 256;
int qt = 170;
int de = 192;
int e = 128;
int et = 85;
int dsx = 96;
int sx = 64;
int thx = 32;



float majScale[] = {
  A,  B,  CS,  D,  E,  FS,  GS,  A2,   B2,  C2S,  D2,  E2,  F2S,  G2S,  A3};
  float minScale[] = {
  A,  B,  C,  D,  E,  F,  GS,  A2,   B2,  C2,  D2,  E2,  F2,  G2S,  A3};
float creme[] =  {
  A,  CS,  D, CS,  D,  E,  CS,  D,   CS,  B,   A};
float cremeDur[] = {
  q,  q,  qt, qt,  qt,  q,  q,  qt,   qt, qt,  q};

void setup() {
  pinMode(outpin, OUTPUT);
  Serial.begin(9600);

  pinMode(LEDbit0, OUTPUT);
  pinMode(LEDbit1, OUTPUT);
  pinMode(LEDbit2, OUTPUT);
  pinMode(LEDbit3, OUTPUT);

  pinMode(stopPin, INPUT);
  digitalWrite(stopPin, HIGH);   // turn on pullups

  pinMode(encoder0PinA, INPUT);
  digitalWrite(encoder0PinA, HIGH);   // turn on pullups
  pinMode(encoder0PinB, INPUT);
  digitalWrite(encoder0PinB, HIGH);   // turn on pullups

  attachInterrupt(0, doEncoder, CHANGE);  // encoder pin on interrupt 0 - pin 2
  Serial.println("start");

  pinMode(outpin, INPUT); // turn off audio out
}


void loop(){


  runlevel = encoder0Pos;
  switch (runlevel){
  case 0:

  case 1:
    doJoker1();
    break;
  case 2:
    doScale2();
    break;
  case 3:
    doArp3();
    break;
  case 4:
    doCreme4();
    break;
  case 5:
    doCreme5();
    break;
    case 6:
    doScale6();
    break;
  
  }
}

//*******************************************************
void doJoker1(){
  sens = analogRead(pitchPot);
  //sens =500;  // hardwire for testing
  adder = max((sens/5),1);

  for (x=sens; x<=(sens + (analogRead(speedPot) * 5)) ; x+=analogRead(jukePot)){    
    if ( digitalRead(stopPin) == 0){
      break;
    }                    
    noteval = x;    // transpose scale up 12 tones - pow function generates transpostion
    dur = 100;
    freqout((int)noteval, sens/47);

    // delay(10);
  }
  delay(analogRead(modPot));
}
// endJoker1 ****************************************************
/*void arp2(){
 sens = analogRead(pitchPot);
 range = abs(512 - sens) * 4.0;
 strt =  sens * 1;
 inc=abs(512 - sens);
 if (inc == 0){
 inc = 1;
 }
 
 for (x=strt; ( x > (strt / 4)) && (x < (inc * 30)); x* = (1 + ((sens - 512) / 1023.00))){                      
 noteval = x;    // transpose scale up 12 tones - pow function generates transpostion
 dur = 100;
 freqout((int)noteval, inc);
 
 //   if ((abs(sens - analogRead(0))) > 2){ break;}
 }
 delay(analogRead(modPot);
 }  */

// end  ***************************************************

void doScale2(){
  ps = ((float)analogRead(jukePot)) * 24.0 / 1023.0;         // choose new transpose interval every loop
  for(x= 0; x<=15; x++){  
    if ( digitalRead(stopPin) == 0){
      break;
    }                  
    noteval = (majScale[x] / (float)(analogRead(pitchPot))) * pow(2,ps);    // transpose scale up 12 tones - pow function generates transpostion
    dur = analogRead(speedPot);
    freqout((int)noteval, dur);

    delay(analogRead(modPot));
  }
}

/****************************************************/

void doArp3(){
  Serial.println("arp");

  fpitch = (float)analogRead(pitchPot) / 64;
  Serial.print("fpitch = ");
  Serial.println(fpitch, DEC);
  if (fpitch == 0){
    fpitch = 1;
  }
  strt = pow(2, fpitch);
  Serial.print("strt = ");
  Serial.println(strt, DEC);

  for(x=strt; x<= strt * 4; strt = (strt * ( 1 + ((float)analogRead(jukePot)/1023)))){  
    if ( digitalRead(stopPin) == 0){
      break;
    }                  
    dur = analogRead(speedPot);
    freqout(strt, dur);
    delay(analogRead(modPot));
  }
}
/****************************************************/
void doCreme4(){
  randomWalkLowRange = 0;
  randomWalkHighRange = 10;

  i = randomWalk(analogRead(speedPot) / 32);
  noteval = creme[i] / ((float)analogRead(pitchPot));
  dur = ((cremeDur[i] * (float)analogRead(jukePot)) / 64.0);
  freqout(noteval, dur);
  delay(analogRead(modPot));
« Last Edit: September 27, 2007, 09:23:30 pm by paulb » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 38
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Paul;

I looked at your synth code but it does not compile as listed. It appears to me that in  several places you call functions which are not there. Could you elucidate on this listing a little?
Logged

0
Offline Offline
Sr. Member
****
Karma: 0
Posts: 267
dinosaur cork
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Sorry, There seems to be a nasty glitch in the forum software that reacts to comment lines in code or something
Funny behavior. Either there's a limit to the size you can paste into the editor or something else is reacting to (comments maybe) something in my code.


I started an "Arduino Synth" page on the playground - find the code there.

http://www.arduino.cc/playground/Main/ArduinoSynth
« Last Edit: October 06, 2007, 11:53:35 am by paulb » Logged

Breda Netherlands
Offline Offline
Newbie
*
Karma: 0
Posts: 17
Arduino rocks (some fine day...)
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Not a lot of action in this thread. What a shame. I just left this comment at http://narbotic.net.

I get loads of ideas that will take ages to implement (considering my 2-week arduino ownership) , you may want to cooperate? I just saw your sketch.

Here's your oscillator:
for (i=0; i<= cycles; i++){ // play note for t ms
digitalWrite(speakerOut, HIGH);
delayMicroseconds(hperiod);
digitalWrite(speakerOut, LOW);
delayMicroseconds(hperiod - 1);


On the fly PWM implementation idea: Declare PulsWidth parameter
Shorten the HIGH period , lengthen the LOW period by (PulsWidth)
Have PulsWidth read from analogPin
Make PulsWidth LFO from “Fading” sketch: http://www.arduino.cc/en/Tutorial/Fading

There's a proper synth parameter for you. If you have more analogIn's available (or select DigitalIn switches) you can combine Pulswidth parameters, so PulsWidth will be: PulsWidth read from analogPin + LFO derived value + LFO speed ( by varying increment/deminish amount at  "Fading" portion).

Now if someone could apply this to the enigmatic pitch determenation scheme we can have pitchbend and vibrato....

A first seed on a "Waveform generator" will be posted elsewhere, as this is no longer appropriate for the "Exhibition" section.

I do hope to make this a joint project, my sketch making so far is minimal to say the least.


« Last Edit: June 03, 2008, 07:47:18 am by electri-fire » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 31
What's that sound?
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Unfortunately I haven't had much time to work on this project lately - but glad to hear you're interested!

Those coding ideas sound good -  I'll trying running some of them when i get the chance.


if you haven't seen it already, check out the APP shield from critter & guitari -
http://www.critterandguitari.com/home/store/arduino-piano.php

the code is a bit hard to follow if you don't speak AVR/C, but it's makes some great sounds

Logged

Breda Netherlands
Offline Offline
Newbie
*
Karma: 0
Posts: 17
Arduino rocks (some fine day...)
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Well, I have a lot of reading up to do I've noticed, been getting my head around the method of having a fast clock timer/counter, and setting up a compare threshold to put out a pulse once the threshold is reached. Much higher frequencies can be reached this way. I hoping to find way to reset the timer.
Tutorial here:
http://www.evilmadscientist.com/article.php/avrdac
 
Another route I've come across is playing samples, as in Sebastian Tomczak's sketches (ArduinoBeats, ArduinoDrumMachine)

I haven't quite understood yet what's happening there as well, but I imagine an eight bit waveform sample could be played looped? And then have options like dial in a waveform with analogIn, generate some random bytes or make some presets like sinus, triangle, sawUp, sawDown, some blockwaves with different pulswidth. You can't morph between two bytes can you? I guess not, no such thing as half a bit . You could have a small array of bytes to alternate, wave-sequence or whatever.
Then you can morph between two waveforms once you have figered out wich byte puts out what, but this seems a mega project. Not my cup of tea for the time being.
I've got some 4051 (de)multiplexers now, need to make a board with these and some R2R DA converters, 386 amp and small speaker. Someone might design a shield for this. Seems a usefull addition to me.

The mind overflows with options, but too often I get reminded of my electronics an programming incompetence, so spend lots of time reading stuff on arduino.cc lately.

> if you haven't seen it already, check out the APP shield from critter & guitari -  
http://www.critterandguitari.com/home/store/arduino-piano.php ,
the code is a bit hard to follow if you don't speak AVR/C, but it's makes some great sounds

I've been checking out your site and flicker stuff.  Nice. You've been very productive.


Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 31
What's that sound?
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Electri-fire - check out this protoshield mini-project I put up on the Make:blog.  It's just an R/2R DAC without a buffer or anything special, you might find the sine generator sketch @ the bottom interesting.

http://blog.makezine.com/archive/2008/05/makeit_protodac_shield_fo.html?CMP=OTC-0D6B48984890

To play a waveform - set up an array containing bytes that make up the wave you want
 then you can write each byte to pins 0-7 all at once with "PORTD="
 the time in between each byte can be variable determined by an analogRead value

I guess that's the extent of my current technique smiley
Logged

Breda Netherlands
Offline Offline
Newbie
*
Karma: 0
Posts: 17
Arduino rocks (some fine day...)
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I was trying to avoid the portstuff for now, hence the CD4051 (de)multiplexers. These put out one bit at a time so the result may be vastly different.  It's good to see the R2R DAC put enough through for a headphone. I can still add the amp later.

For single cycle waveform playing an array of 32 bytes seems more than sufficient. I have another cool idea.

Draw_Waveform: press "record", draw a waveform from analogIn, press "end record". Depending on how fast you draw you get a different number of samples each recording. Put these in a temporary array, count the number of samples. Now devide this number by x, to get 32 (roughly).

How's that done by the way?

Next take evey x'th sample from the temporary array, put them in the 32 byte waveform array, maybe do some smoothing, play looped.

There's no smiley for "impatient" I'm afraid....
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 31
What's that sound?
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
There's no smiley for "impatient" I'm afraid....
lol - I think I see where you're coming from now.  If you're relatively new to this coding (like me) - a bunch of ideal techniques come to mind and the implementation is still a big "?"

The sampling technique sounds interesting - are you just talking about basic waveforms: sine, triangle, saw, etc?
Logged

Breda Netherlands
Offline Offline
Newbie
*
Karma: 0
Posts: 17
Arduino rocks (some fine day...)
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Are you just talking about basic waveforms: sine, triangle, saw, etc?

Partly. Basic waveforms could ofcause be generated with some math functions, but..xssqkrr.. need to scratch now, sorry, math allergy you know?  ;D
You were gonna say that, weren't you?

I will maybe have to resort to that later, for now I will stick to the Array strategy.
But yes, also some preset classic waveforms.  
I want all oscillators to be compatible with each other and make some modular options to choose from.

To do:  

Moph_Waveform: have two "input" WaveArrays, like from the Draw_Waveform function and a selection from the preset arrays.
Read two arrays simultaniously, average both values, put out the avarage in the actual output wavetable.
Now find a way to do a "weighted morph" with a fader at analogIn, so we can have waveA with the fader to the left, waveB with the fader to the right, mixes in between.
Another option: interpolation: play byte
  • from waveA, byte [1] from waveB, byte [3] from waveA , etc, keep alternating till [31] and start over.

Shift_Phase: have waveA static for convenience, find a way to alter the loop startpoint of waveB, and have it wrap to byte
  • when byte [31] has been reached.
Combined with Moph_Waveform yields comb filter and PWM effects.

Then I'm done, except for the smoothing function. Combined this could be FAT.

I do hope it will not tax the arduino beyond it's capability. We still need some room to actually play the notes!
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 31
What's that sound?
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

yes very true - math was never my best subject  smiley

I was thinking of combining 2 waves via averaging as well.  I have a feeling there must be a fairly straightforward way to do this.  And ideally we'd like to skew(?) the average with a reading from a pot/analog pin.

I made some arrays for the basic waveforms already - I'll clean them up a bit and post them here
« Last Edit: June 08, 2008, 08:46:13 pm by Narbotic » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 31
What's that sound?
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

wow - my immediate math knowledge is sucking pretty bad of late :o

to average the 2 array entries:

((sineArray + triangleArray)  / 2)  = average

but weighting/skewing  them i still don't know
« Last Edit: June 08, 2008, 10:46:43 pm by Narbotic » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 31
What's that sound?
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

hmm - would this work?

Code:
//specify weightvalue as a floating point number
float weightValue;
float weightRemainder;

void loop(){

//convert to percentage of 100
weightValue = (analogRead(potPin) / 1024);

//find the weightValue's remainder out of 1
weightRemainder = (1 - weightValue);

//find the weighted average
(((weightValue * sineArray[i]) + (weightRemainder * triangleArray[i])) / 2)  == weighted average;
Logged

Las Vegas, NV
Offline Offline
God Member
*****
Karma: 0
Posts: 507
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Not quite.

1) weightValue = (analogRead(potPin) / 1023);

2) (weightValue * sineArray) + (weightRemainder * triangleArray)  == weighted average;
i.e. don't divide by 2

- Ben
Logged


Pages: 1 [2] 3   Go Up
Jump to: