login

online now

We have 85 guests and no members online

search

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

TOPIC: Tone Generation

Re: Tone Generation 5 years 2 months ago #308

Ok, I understand what you are saying. However, I am unsure how to implment that concept into my code. Could you point me in the direction of any tutorials or examples that I could use as an example to write this code?
The administrator has disabled public write access.

Re: Tone Generation 5 years 2 months ago #311

You may be able to download some relevant code by googling for "voice stealing algorithms", although they will not be a direct port to the Arduino. The process should be fairly simple, though. Here is a bit of code (untested) that should give you an idea of the process. When you need to play a new note, you can call the function getNextVoice() that gives you a voice index which you can use to call setNote() and trigger(). This code simply keeps track of the time each voice was triggered, and either returns the first untriggered voice, or the voice that has been playing the longest:


unsigned long trigTimes[6] = { 0, 0, 0, 0, 0, 0 };


int getNextVoice()
{
  int foundVoiceIdx = -1;                      // voice index that will be used
  unsigned long curTime = millis();            // get the current time
  unsigned long longestTrigTime = curTime;     // longest running trigger time

  // loop through the trigger times for each voice and find either an open
  // voice ( time = 0 ) or the one that has the smallest trigger time and
  // hence has been running the longest

  for ( int voiceIdx =0; voiceIdx < 6; voiceIdx++ ) {

      voiceTrigTime = trigTimes [ voiceIdx ];


     // if the tigger time is zero its not been used so allocate that one
     // and stop looking any further

     if ( voiceTrigTime == 0 ) { 
        foundVoiceIdx = voiceIdx; 
        break; 
     }

    
     // if its not zero then its been triggered before, so find the one that
     // has the shortest time value ( the oldest one triggered )

     else if ( voiceTrigTime < longestTrigTime ) { 
        foundVoiceIdx = voiceIdx;
        longestTrigTime = voiceTrigTime;
     }

   }

   // update the trigger time on the new voice to now

   if ( foundVoiceIdx != -1 ) trigTimes [ foundVoiceIdx ] = curTime;
   return ( foundVoiceIdx );

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

Re: Tone Generation 5 years 2 months ago #312

Ok, so I would include a new function that performs the "voice steal" into my code.

How would I call this funtion? I am thinking that I could call it in my void loop() where I usually call the note.
if (val01 >= light1)
{
  digitalWrite(LED01, LOW);
  if ( triggered == 1 )
    {
      poly->release ( 0 );
      triggered = 0;
    }
}
else {
  digitalWrite(LED01, HIGH);
  if ( triggered == 0 ) 
    {
      poly->setNote ( foundVoiceIdx , C_7 );
      poly->trigger ( foundVoiceIdx );
      triggered = 1;
    }
}

Maybe something like this would work?
Last Edit: 5 years 2 months ago by GTfan.
The administrator has disabled public write access.

Re: Tone Generation 5 years 2 months ago #313

OK, so here is some code that might help you out. This is similar to what you had, except that I created a data structure to store the information and state of each input/output device. Make sure to fill out ALL 16 definitions in the setupButtons() function. I have not tested this, but hopefully the functions and variables should be commented well enough to groc.

#include <GinSing.h>                        // synth header file                                         
GinSing  GS;                                // synth poly mode interface


// Create a button structure that stores the state of the input, output, and sound. There should
// be one of these for each input/output button that will be processed. Trigger state is based on
// the voiceID ( NoTrigger means its off, any other value means its on )

struct MyButton {
  
  int    inputPin;         // hardware pin that corresponds to this input pin
  int    outputPin;        // hardware pin that corresponds to this output pin
  int    voiceID;          // polyphonic voice used to create sound for this button
  GSNote note;             // musical note associated with ths button
  
};

#define NumButtons       16                // # of supported button input/outputs
#define NumVoices        6                 // # of voices used in the synth
#define ButtonThreshold 270                // the on/off threshold for state change
#define NoVoice         255                // indicates no voice being used for a button

MyButton buttons [ NumButtons ];           // information about each button

unsigned long trigTimes[6] = { 0, 0, 0, 0, 0, 0 };   // used for voice stealing

GinSingPoly  *poly;                         // synth poly mode interface


void processButton ( int buttonIdx );       // forward delcaration

// ------------------------------------------------------------------------------------------------------
// setup - initialization entry point for program
// ------------------------------------------------------------------------------------------------------

void setup()
{  
  
  Serial.begin(9600);                     // for debugging only
 
  setupButtons();                         // configure hardware input/output
  setupSynth();                           // configure synthesizer
  
}


// ------------------------------------------------------------------------------------------------------
// setupButtons -- configure the hardware assignments for the buttons
// ------------------------------------------------------------------------------------------------------


void setupButtons()
{
  
  // input pin ( analog pin )         output pin ( digital pin for LED )     musical note 
  // -----------------------------    -----------------------------------    -----------------------
     buttons[0] . inputPin  = 0;      buttons[0] . outputPin = 8;            buttons[0] . note = C_3;
     buttons[1] . inputPin  = 3;      buttons[1] . outputPin = 9;            buttons[1] . note = D_3;


  // configure I/O
  
  for ( int buttonIdx = 0; buttonIdx < NumButtons; buttonIdx++ ) {
    
    MyButton *button = & buttons [ buttonIdx ];
    
    pinMode ( button -> outputPin , OUTPUT );
    digitalWrite ( button -> outputPin , LOW );
    
    button -> voiceID = NoVoice;
    
  }
}


// ------------------------------------------------------------------------------------------------------
// setupSynth -- configure GinSing synth for operation
// ------------------------------------------------------------------------------------------------------

void setupSynth()
{

  #define rcvPin  4                           // synth receive pin
  #define sndPin  3                           // synth send pin                        
  #define ovfPin  2                           // synth oveflow pint
  
  // start the synth and get poly mode
  
  GS.begin ( rcvPin , sndPin , ovfPin );
  poly = GS.getPoly(); 
 
}


// ------------------------------------------------------------------------------------------------------
// loop -- program continuous entry point ( called AFAP )
// ------------------------------------------------------------------------------------------------------

void loop()
{                                         

 // process all inputs
 
   for ( int buttonIdx = 0; buttonIdx < NumButtons; buttonIdx++ ) processButton ( buttonIdx );
 
}

// ------------------------------------------------------------------------------------------------------
// processButton -- process input changes to buttons
// ------------------------------------------------------------------------------------------------------

void processButton ( int buttonIdx )
{
  MyButton * button = & buttons [ buttonIdx ];
  
  // read button state
  
  int analogVal = analogRead ( button -> inputPin );
  
  
  // check for trigger 
  
  if ( analogVal > ButtonThreshold && button -> voiceID == NoVoice ) {
    
    // set output LED state
    
    digitalWrite ( button -> outputPin , HIGH );
    
    // get a voice and play it for this button
    
    button -> voiceID = getNextVoice();
    poly -> setNote ( button -> voiceID , button -> note );
    poly  -> trigger  ( button -> voiceID );
    
  }
  
  
  // check for release
  
  else if ( analogVal < ButtonThreshold && button -> voiceID != NoVoice ) {
    
    // set output LED state
    
    digitalWrite ( button -> outputPin , LOW );
    
    // release the voice
    
    poly -> release ( button -> voiceID );
    button -> voiceID = NoVoice;
  }
}


// ------------------------------------------------------------------------------------------------------
// getNextVoice -- get the next available voice for playing a note
// ------------------------------------------------------------------------------------------------------

int getNextVoice()
{
  int foundVoiceIdx = -1;                      // voice index that will be used
  unsigned long curTime = millis();            // get the current time
  unsigned long longestTrigTime = curTime;     // longest running trigger time

  // loop through the trigger times for each voice and find either an open
  // voice ( time = 0 ) or the one that has the smallest trigger time and
  // hence has been running the longest

  for ( int voiceIdx =0; voiceIdx < 6; voiceIdx++ ) {

      unsigned long voiceTrigTime = trigTimes [ voiceIdx ];


     // if the tigger time is zero its not been used so allocate that one
     // and stop looking any further

     if ( voiceTrigTime == 0 ) { 
        foundVoiceIdx = voiceIdx; 
        break; 
     }

    
     // if its not zero then its been triggered before, so find the one that
     // has the shortest time value ( the oldest one triggered )

     else if ( voiceTrigTime < longestTrigTime ) { 
        foundVoiceIdx = voiceIdx;
        longestTrigTime = voiceTrigTime;
     }

   }

   // update the trigger time on the new voice to now

   if ( foundVoiceIdx != -1 ) trigTimes [ foundVoiceIdx ] = curTime;
   return ( foundVoiceIdx );

}
The administrator has disabled public write access.

Re: Tone Generation 5 years 2 months ago #314

Ok, I tried the code with 2 LEDs. I changed "NumButtons" to 2. My problem is that the LEDs stayed on as long as they weren't covered. When I covered the LEDs, they turned off.

Also, I only heard sound when I covered both. I tried toggling some of the "HIGH" and "LOW" definitions, as well as changing the threshold and NoVoice values.

I am unsure what else to change. I haven't tried with more than 6 LEDs, but I wouldn't think that I have to. Anymore suggestions?
The administrator has disabled public write access.

Re: Tone Generation 5 years 2 months ago #315

I probably flipped the threshold check. I did not test the code, so Serial.print() may be a good friend. Also it should work as you say with just two. What happens with one?
Last Edit: 5 years 2 months ago by administrator.
The administrator has disabled public write access.
  • Page:
  • 1
  • 2
Time to create page: 0.365 seconds