login

online now

We have 73 guests and no members online

search

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

TOPIC: Tone Generation

Tone Generation 5 years 2 months ago #267

Hi all,

I am just getting started using Arduino and Ginsing coding. I read through all of the "Getting Started" Manuals and tutorials that I have found, but I'm still struggling finding some examples of some coding.

I am trying to get the GinSing to generate tones in poly mode in order to form a song.

This is my code so far (just trying to form a two note sequence):
#include <GinSing.h>                                           // interface header file
GinSing  GS;                                                   // create the class library from which all methods and data are accessed

#define rcvPin  4                                              // this is the pin used for receiving    ( can be either 4 or 12 )
#define sndPin  3                                              // this is the pin used for transmitting ( can be either 3 or 11 ) 
#define ovfPin  2                                              // this is the pin used for overflow control ( can be either 2 or 10 )

// ---------------------------------------------------------------------------------------------------------------------------------------------

void setup ()
{
  GS.begin ( rcvPin , sndPin , ovfPin );                       // start the device
  
  GinSingPoly * poly = GS.getPoly();                           // get the poly mode interface
  poly->begin ();                                              // enter poly mode

poly->setNote ( 0 , A_4 );
poly->trigger ( 0 );
poly->release ( 0 );
delay ( 300 );

poly->setNote ( 0 , F_3 );
poly->trigger ( 0 );
poly->release ( 0 );
delay ( 300 );
}

void loop () {}
Last Edit: 5 years 2 months ago by administrator.
The administrator has disabled public write access.

Re: Tone Generation 5 years 2 months ago #268

One thing that you might find helpful is the portion of the sample code that is available on the front page ( demo code ). There is also a sample program in the distribution that plays a similar song.

I think your code below is doing a trigger and then immediate release, which will not allow the amplitude envelope to reach a significant value before you taper off - try putting a delay between trigger and release and see if you hear anything.

If you have any more specific questions please feel free to use the forum, we'll get your tune going in no time.

From the demo code example (fragment):
//-----------------------------------------------------------------------------------

void doMusic()
{

 
  // play a ditty
  
  #define NumNotes 10
  GSNote bass[NumNotes] = { C_3, E_3, D_3, F_3, E_3, G_3, E_3, F_3, D_3, E_3  };
  GSNote lead[NumNotes] = { C_6, D_6, E_6, F_6, G_6, G_6, F_6, E_6, D_6, C_6  };
  GSNote treb[NumNotes] = { G_5, E_5, F_5, D_5, E_5, C_5, E_5, D_5, F_5, E_5  };
   
    
  for ( int loopCnt = 0; loopCnt < 4; loopCnt++ )
  {
    for ( int noteIdx = 0; noteIdx < NumNotes; noteIdx++ ) 
    { 
        p->setNote ( 0 , bass [ noteIdx ] ); p->trigger ( 0 );
        p->setNote ( 1 , treb [ noteIdx ] ); p->trigger ( 1 );
        p->setNote ( 2 , lead [ noteIdx ] ); p->trigger ( 2 );
       delay ( 200 );                                        
    }
  }

  // release the voices and wait for the envelopes to stop
    
  p->release ( 0 ); p->release ( 1 ); p->release ( 2 ); 
  delay ( 1000 );
}
Last Edit: 5 years 2 months ago by administrator.
The administrator has disabled public write access.

Re: Tone Generation 5 years 2 months ago #269

Ok, I have been able to use that example code as a template to compose my own songs, but I'm having a problem. When I define the same note back to back, it plays the note once instead of twice.
The administrator has disabled public write access.

Re: Tone Generation 5 years 2 months ago #270

Its probably a result of the way envelope triggering works. When you call trigger() you start the amplitude envelope in its sequence. In most cases it takes a few milliseconds for the envelope to ramp up, so if you call it again right away, it will not produce any sound on the first note unless you have a near zero attack stage. The default envelopes do have a notable attack time so that is probably what is going on. I would suggest you experiment a bit with the ADSR values to see if you can get the attack that you need for quick retriggers.
The administrator has disabled public write access.

Re: Tone Generation 5 years 2 months ago #279

I have successfully created code that allows for a light sensing LED to "turn on" another LED in light-emitting mode. In other words, the user covers one LED, and the other LED turns on.

I am now trying to get a Ginsing produced poly mode tone to be played when the LED is covered. I have not been able to figure out why my code doesn't work. Let me know if you see any issues:
#include <GinSing.h>                                           
GinSing  GS;                                                   

#define rcvPin  4                                              
#define sndPin  3                                              
#define ovfPin  2 

int sense01 = 0;
int LED01 = 11;
int val01 = 0;
int light1 = 270;

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

void loop()
{
GS.begin ( rcvPin , sndPin , ovfPin );                      
  
  GinSingPoly * poly = GS.getPoly();                          
  poly->begin ();                                             

 

val01 = analogRead(sense01);

Serial.println(val04); 

if (val01 >= light1)
{digitalWrite(LED01, LOW);
}
else {
  digitalWrite(LED01, HIGH);
poly->setNote ( 0 , A_4 );
poly->trigger ( 0 );
delay(500)
poly->release ( 0 );

}
}
Last Edit: 5 years 2 months ago by GTfan.
The administrator has disabled public write access.

Re: Tone Generation 5 years 2 months ago #280

I think the problem may be a result of what happens in the loop() function. This function gets called on the Arduino at a very high rate, and so stuff that happens in there in terms of sound should probably only happen based on a particular event.

The function call to poly->begin() configures the system to work in polyphonic mode, and acts essentially as a reset button - this function need only be called once, or called when you are switching from another mode; so in this case you should put this in your setup() function.

Also in the loop() function you are repeatedly calling trigger and release, but since the loop is executed at a high rate you are essentially releasing and then immediately retriggering the sound as the loop returns. The best way typically to handle this is to put a state variable into the loop and check for state change, and then do the action. For example, you might modify the code in this way:
#include <GinSing.h>                                           
GinSing  GS;                                                   

#define rcvPin  4                                              
#define sndPin  3                                              
#define ovfPin  2 

int sense01 = 0;
int LED01 = 11;
int val01 = 0;
int light1 = 270;
int triggered = 0;

GinSingPoly *poly;

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

  GS.begin ( rcvPin , sndPin , ovfPin );   
  poly = GS.getPoly(); 
}

void loop()
{                

  val01 = analogRead(sense01);

  Serial.println(val04); 

  // turn off light and sound

  if (val01 >= light1 )
  {
    digitalWrite(LED01, LOW);

    if ( triggered == 1 )
    {
      poly->release ( 0 );
      triggered = 0;
    }
  }

  // turn on light and sound

  else {

    digitalWrite(LED01, HIGH);

    if ( triggered == 0 ) 
    {
      poly->setNote ( 0 , A_4 );
      poly->trigger ( 0 );
      triggered = 1;
    }
  }
}

So in this code example the variable "triggered" is used to avoid constantly turning it on and off by checking to see what the last state was, and only doing the action when it needs to change. This hopefully will produce the result you are looking for.
The administrator has disabled public write access.

Re: Tone Generation 5 years 2 months ago #288

Thanks for your help. I have gotten it to work.

However, I now have a new problem. I originally built a circuit with 16 pairs of sensing and emitting LEDs. Each pair was assignmed a tone (from the Arduino Mega 2560 library). I was able to do this successfully.

Now, I am trying to integrate the GinSing's tones to my "LED instrument". I can say that the GinSing is compatable with the Arduino Mega. I have been able to get up to 3 LEDs to play different tones. However, I lack the amount of Analog pins with GinSing (since it was made for the Uno) that I need for 16 different tone generations.

What would you suggest I do to resolve this problem?
The administrator has disabled public write access.
The following user(s) said Thank You: administrator

Re: Tone Generation 5 years 2 months ago #289

Thanks for checking compatibility with the Mega - we expected it to work, but never tested it; I think several people will be happy to hear that.

I'm not sure what you mean by lack of analog pins with GinSing - when the GinSing board is in place, does it block the original header on the Mega so that you cannot use those? The headers on the GinSing board are just passthru, which means that you can use those pins as if they were on the original board, or if not taken by the GinSing board, you can use the ones on the Arduino.
The administrator has disabled public write access.

Re: Tone Generation 5 years 2 months ago #291

I have access to all of the pins on the Mega, but I was under the impression that I can only get GinSing tone output by directly connecting to one of the pins on the GinSing. Is this correct?
The administrator has disabled public write access.

Re: Tone Generation 5 years 2 months ago #292

The GinSing shield communicates to the Arduino using either 1,2, or 3 pins, which is allocated based on the headers on the shield. On the mega, this would by default correspond to pins 2,3,4 as per the jumpers, but all other pins are available for use in your application.

Basically the GinSing code opens up a serial connection using send, receive, and overflow signals from the Arduino. The GinSing code on the Arduino uses the specified pins for this communication - all other pins are left untouched by GinSing.
The administrator has disabled public write access.

Re: Tone Generation 5 years 2 months ago #295

Right, so if the GinSing uses 3 predetermined pins that leaves us with 6 analog inputs and 11 digital outputs. So, I can only use 6 input pins for my LED sounds.

I need 16 different sounds to my LED circuit, but it appears that this will be impossible due to lack of pins.
The administrator has disabled public write access.

Re: Tone Generation 5 years 2 months ago #296

If I understand the Mega, you should have plenty of I/O. The Arduino website says:

The Arduino Mega 2560 is a microcontroller board based on the ATmega2560 (datasheet). It has 54 digital input/output pins (of which 14 can be used as PWM outputs), 16 analog inputs, ...

The GinSing shield would only take:

2 ( digital ) or 10 ( pwm )
3 ( pwm ) or 11 ( pwm )
4 ( digital ) or 12 ( digital )

This should not take away any analog inputs, and at most 2 digital I/O.
?
The administrator has disabled public write access.

Re: Tone Generation 5 years 2 months ago #297

So, you are saying that if I connect my LEDs only to the Arduino Mega pins ( that aren't jumped with the GinSing), then I can generate GinSing sound from them?
The administrator has disabled public write access.

Re: Tone Generation 5 years 2 months ago #298

Well, I think there is definitely a disconnect somewhere here. Lets see if I can clarify it a bit.

The GinSing board produces analog audio output on the 1/8" jack or speaker terminals on the board. The sound is generated by controlling any/all of the 6 on-chip waveform oscillators that all get mixed down to the audio output in the Babblebot IC on the GinSing board. The control of the oscillators ( or DCOs ) is done by setting memory registers within the Babblebot IC - the registers get set using a serial interafce and a simple set of commands. These commands are sent from the Arduino to the GinSing board using 1,2, or 3 pins connected through as per the jumper settings on the GinSing board.

So, the only Arduino pins used by the GinSing shield are the 3 used for serial communication. Theoretically you don't need all 3 ( send, receive, overflow ) - for example, if you are not going to read data the GinSing you don't need the receive pin at all; likewise if you control the speed you send data to the GinSing shield you don't need the oveflow pin either.

The GinSing software that runs on the Arduino manages this communication and sets the Babblebot registers using a simple function interface. No pins are used for audio output as that comes from the audio jack on the GinSing shield. Although you can directly set the registers ( via writeRegister() ), you can also use the logical interfaces, such as synth mode to set them through the interface.

Now, although there are only 6 DCOs you can mix to the output, you can re-use those DCOs to produce different sound as needed. In effect, you are limited to 6 simultaneous output sounds, and you can control what those are.

In the simplest example, you could change the frequency of a single DCO based on which input is being triggered - this would allow you to change musical notes for example, but you would only be able to produce one note ( not a chord for example ). Although this limits the input processing, it does allow you to create very complex waveforms using other DCOs to modulate the basic one ( i.e. vibrato, tremolo, etc. )

In a more complex example, you could allocate 1-6 DCOs to allow for both chord and lead as long as no more than six notes were played at the same time. This is effectively what poly mode is - six DCOs configured to generate 6 voices using the same tonal parameters. Each DCO is capable of having its own pitch, waveform, and envelope ( although the latter two are generally kept the same to make the DCOs interchangeable ). If you require more than six simultaneous notes to be played at the same time, you would probably want to implement a simple voice stealing algorithm that would stop one note in favor of another - for example you might keep a timer running for each DCO, and if a new note is needed use the DOC that has been running the longest.

Hopefully that gives you a bit more information that might be relevant to your project.
The administrator has disabled public write access.

Re: Tone Generation 5 years 2 months ago #299

Ok, you have answered my question.

I successfully got tone output in my single LED circuit. However, I am now having trouble getting different tone output on two different LEDs.

When I cover a single LED, I get no sound. When I cover both LEDs, I get both sounds. What could be the problem? Here is my code:

#include <GinSing.h>                                           
GinSing  GS;                                                   

#define rcvPin  4                                              
#define sndPin  3                                              
#define ovfPin  2 

int sense01 = 0;
int sense02 = 3;

int LED01 = 8;
int LED02 = 9;
int val01 = 0;
int val02 = 0;
int light1 = 270;
int triggered = 0;

GinSingPoly *poly;

void setup()
{  
  
  Serial.begin(9600);
  pinMode(LED01, OUTPUT);
  pinMode(LED02, OUTPUT);
  
  GS.begin ( rcvPin , sndPin , ovfPin );
  poly = GS.getPoly(); 

}

void loop()
{                                         

 

val01 = analogRead(sense01);
val02 = analogRead(sense02);

Serial.println(val01); 

if (val01 >= light1)
{
  digitalWrite(LED01, LOW);
  if ( triggered == 1 )
    {
      poly->release ( 0 );
      triggered = 0;
    }
}
else {
  digitalWrite(LED01, HIGH);
  if ( triggered == 0 ) 
    {
      poly->setNote ( 0 , C_7 );
      poly->trigger ( 0 );
      triggered = 1;
    }
}

if (val02 >= light1)
{
  digitalWrite(LED02, LOW);
  if ( triggered == 1 )
    {
      poly->release ( 0 );
      triggered = 0;
    }
}
else {
  digitalWrite(LED02, HIGH);
  if ( triggered == 0 ) 
    {
      poly->setNote ( 0 , G_7 );
      poly->trigger ( 0 );
      triggered = 1;
    }
}
}
The administrator has disabled public write access.

Re: Tone Generation 5 years 2 months ago #300

The first argument to the polymode functions are the voice ( DCO ) value. It appears that both of your conditionals are using the same DCO. The following code, for example is controlling DCO #0 ( can be 0-5 ):
   poly->setNote ( 0 , C_7 );
   poly->trigger ( 0 );

See page 36 of the reference manual for more information.
The administrator has disabled public write access.

Re: Tone Generation 5 years 2 months ago #304

So, does that mean that I would have an issue getting more than 6 different "LED tones" on my instrument?
The administrator has disabled public write access.

Re: Tone Generation 5 years 2 months ago #305

Only more than 6 at any given time. Most musical instruments never need more than 6 simultaneous tones, although it is possible with some on rare occasions ( i.e. a piano player playing 6 notes at the same time ).
The administrator has disabled public write access.

Re: Tone Generation 5 years 2 months ago #306

So in your previous reply, are you suggesting I use different DCO values for my two different musical notes or using different DCO values for "set_note" and trigger?
The administrator has disabled public write access.

Re: Tone Generation 5 years 2 months ago #307

Well, I guess both. When you trigger any of the 6 DCOs, you address them using the oscillator index ( 0-5 ), indicating which DCO you want to have make a new note. Since you have only 6, you will have to determine what happens when you want to play more than 6 simultaneously.

When you have selected which DCO you want to play a note, you specify the note using setNote for that DCO. For example, the first six notes that come in can use DCOs 0-5 directly. If you release a note before the 7th note is played, you can reuse that DCO by calling setNote() and trigger() again to play the new note.

In effect, you probably want to have a status array ( 0-5 ) that represents some information about each DCO, such as if it is being used to play a note, and how long its been playing. Given this, when a new note is required, you can check this array to determine if any are available directly, or if you need to steal one that is already playing for the incoming note.
The administrator has disabled public write access.
  • Page:
  • 1
  • 2
Time to create page: 0.410 seconds