User:Fabien Labeyrie/Clapping Arduino Modulo: Difference between revisions

From XPUB & Lens-Based wiki
No edit summary
No edit summary
 
(16 intermediate revisions by the same user not shown)
Line 1: Line 1:
==Clapping Arduino==
[[Category:prototyping]]
[[Category:2011_P1.01]]
__NOTOC__
__NOEDITSECTION__


The following exercise puts [http://en.wikipedia.org/wiki/Steve_Reich Steve Reich] into an [http://en.wikipedia.org/wiki/Arduino italian chip], using its ''tone'' functionality. As a result, it should be able to play the [http://en.wikipedia.org/wiki/Clapping_Music clapping music] by itself.   
<div style="width:600px">
==<span style="color:#0B0080">Clapping Arduino</span>==
<hr style="height:5px; margin-top:-15px; background-color:#FFF">
<br />
 
The following exercise puts [http://en.wikipedia.org/wiki/Steve_Reich Steve Reich] into an [http://en.wikipedia.org/wiki/Arduino italian chip], using its [http://arduino.cc/en/Reference/Tone ''tone''] functionality. As a result, it should be able to play the [http://en.wikipedia.org/wiki/Clapping_Music clapping music] by itself.   
 
<br />
==<div style="margin-top:30px">Version I :  two speakers and two loops</div>==
<hr style="height:5px; margin-top:-15px; background-color:#FFF">


===Version I :  two speakers and two loops===
====How does it work ?====
====How does it work ?====
The ''Clapping music'' consists in one pattern being played and shifted by two people. We will use two speakers to differentiate the two musical lines and to produce a stereo effect. The Arduino board will dispatch the ''tone'' information to the speakers thanks to two nested ''for'' loops and two ''if'' conditions. <ref>This code couldn't have been completed without the help of [http://pzwart3.wdka.hro.nl/wiki/User:Birgit_bachler Birgit].</ref>  
The ''Clapping music'' consists in one pattern being played and shifted by two people. We will use two speakers to differentiate the two musical lines and to produce a stereo effect. The Arduino board will dispatch the ''tone'' information to the speakers thanks to two nested ''for'' loops and two ''if'' conditions. <ref>The first code couldn't have been completed without the help of [http://pzwart3.wdka.hro.nl/wiki/User:Birgit_bachler Birgit].</ref>  


=====Technologies involved=====
=====Technologies involved=====
Line 11: Line 22:


=====Steps=====
=====Steps=====
*Tone function in arduino can't play note simultaneously, so we have to trick human sound perception in order to make us believe two very close sounds are played at the same time.
<div style="margin-left:-55px; margin-top:10px;">
#&nbsp;&nbsp;&nbsp;&nbsp;We are defining the pattern
#&nbsp;&nbsp;&nbsp;&nbsp;Each speaker will act as a different channel
#&nbsp;&nbsp;&nbsp;&nbsp;The pattern is being repeated and shifted
#&nbsp;&nbsp;&nbsp;&nbsp;Because the ''tone'' function in Arduino cannot play several notes simultaneously, we are tricking human sound perception : two sounds played one after the other very quickly (10 milliseconds in this example) will be interpreted by our brain as simultaneous.
</div>


===It's fucking too late to do some wiki stuff so I'm gonna continue tomorrow===
<br />
====Source code====


'''Code'''
<source lang="c">


<source lang="c">
// This is telling the board which pin to use as an output
int speakerHigh = 8;
int speakerHigh = 8;
int speakerLow = 7;
int speakerLow = 7;
// This will be the frequency of the notes
int noteValue = 3000;
int noteValue = 3000;


// This will be the duration of the notes and the pause between them
int theDelay = 10;
int theDelay = 10;
 
// This is the pattern
char pat[] = "xxx xx x xx ";
char pat[] = "xxx xx x xx ";
// This is the pattern lenght
int patlen = strlen(pat);
int patlen = strlen(pat);
   
   
void setup(){}
void setup(){}  
  void loop (){
void loop (){
 
  for (int iLine=0; iLine<patlen; iLine++){
      
      
     // The following loop will be performed completly first, then launched again by the previous one.
     // This tells the program to begin a new measure after twelve notes have been played
     for (int iBeat=0; iBeat<patlen; iBeat++){
     for (int iLine=0; iLine<patlen; iLine++){
      
      
        // Each beat will be assigned a number value
      // The following loop will be completed first, then launched again by the previous one.
        int iNote = iBeat+iLine;
      for (int iNote1=0; iNote1<patlen; iNote1++){
       
     
       
          // iNote2, the second channel, will be assigned a value resulting from the addition of the two nested loops
          // When the number value is bigger than 11, it's been resetted to 0  
          int iNote2 = iNote1+iLine;
          if (iNote > (patlen-1)){
         
            iNote = iBeat-patlen+iLine;
            // If iNote2 is bigger than 11, it's been resetted to 0 to correpond to a position in the pattern 
            if (iNote2 > (patlen-1)){
              iNote2 = iNote1-patlen+iLine;
            }
 
          // Channel one
          // Each note value with a position in the pattern, checking if it refers to an "x" or a blank space
          if (pat[iNote1] == 'x') {
            // We have to shut the other speaker in order to make this one play
            noTone(speakerHigh);
            // The note is finally played
            tone(speakerLow, noteValue, theDelay);
            delay(theDelay);
           }
           }
          // Channel two
          // The second channel is played 10 milliseconds after the first, simulating a simultaneous playing.
          if (pat[iNote2] == 'x') {
            noTone(speakerLow);
            tone(speakerHigh, noteValue, theDelay);
          }
 
      delay(theDelay*theDelay);   
    } 
  }
}
</source>
<br />
==<div style="margin-top:30px">Version II : C code and the modulo</div>==
<hr style="height:5px; margin-top:-15px; background-color:#FFF">
====How does it work ?====
Because the previous code is not as efficient as it can get, we will see how it can be optimised in C. Instead of sending it to the Arduino board, we will create a visual output in the linux shell. The result will show a list of X and blank spaces.
=====Technologies involved=====
[http://en.wikipedia.org/wiki/C_%28programminhttp://en.wikipedia.org/wiki/Wikipedia:Manual_of_Styleg_language%29 C].
=====Steps=====
<div style="margin-left:-55px; margin-top:10px;">
#&nbsp;&nbsp;&nbsp;&nbsp;This time we are really using nested loops but without any ''if''.
#&nbsp;&nbsp;&nbsp;&nbsp;Changing the pattern is made possible by assigning to a variable a value that depends on two integer in two different loops. Whereas one of the integer will change every cycle in the smaller loop, the bigger loop that contains the other integer will change its value only when the smaller loop is over.
#&nbsp;&nbsp;&nbsp;&nbsp;One key point of this code is the ''modulo''.
</div>
=====What is the modulo ?=====
The ''modulo'' (a.k.a. %), will give the remainder of a division.
''Example'' :<br />
5%4 = 1 (divide 5 per 4 and 1 will remain)<br />
5%3 = 2 (divide 5 per 4 and 2 will remain)<br />
5%6 = no effect (divide 5 per 6 and you have no remainder)
It is useful to get rid of too many ''if'' conditions. By using ''i%12'', the output will never be more than 12. If ''i'' goes higher than twelve, the result of ''i%12'' will be the reminder, i.e. it will go from 1 to 12 again.
<br />
====Source code====
<source lang="C">
#include "stdio.h"
#include "string.h"


        // Channel one
char pat[] = "xxx xx x xx ";
        if (pat[iBeat] == 'x') {
int patlen;
          // We have to shut the other speaker in order to make this one play
// When iShift is going up, the second channel pattern is changed
          noTone(speakerHigh);
int iShift = 0;
          tone(speakerLow, noteValue, theDelay);
// iRepeat make each measure repeating twelve times
          delay(theDelay);
int iRepeat = 0;
        }
// iNote creates the pattern in the first channel
        // The second channel is played 10 milliseconds after the first, simulating a simultaneous playing by using a higher pitched note.
int iNote = 0;
        if (pat[iNote] == 'x') {
// iNote2 creates the pattern in the second channel
          noTone(speakerLow);
int iNote2 = 0;
          tone(speakerHigh, noteValue, theDelay);
 
         }
int main(){
  patlen = strlen(pat);
     delay(theDelay*theDelay);  
 
    
  // This will shift the pattern and create a new measure
  while (iShift <= patlen) {
 
    // This will repeat each mesure twelve times
    while (iRepeat < patlen) {  
 
      // This will play each measure twelve times
      while ( iNote < patlen) {
 
        // Because iShift increase at each new measure, the pattern will be shifted accordingly
        iNote2 = iNote+iShift;
        // We print the first channel, and the second channel
        printf("%c%c\n", pat[iNote], pat[iNote2%12]);
         iNote++;
      }
      iRepeat++;
      iNote=0;
    }
     iShift++;
     iRepeat = 0;
   }
   }
}
}
</source>
</source>


<br />
<references />
<references />
</div>

Latest revision as of 23:07, 6 April 2011



Clapping Arduino



The following exercise puts Steve Reich into an italian chip, using its tone functionality. As a result, it should be able to play the clapping music by itself.


Version I : two speakers and two loops


How does it work ?

The Clapping music consists in one pattern being played and shifted by two people. We will use two speakers to differentiate the two musical lines and to produce a stereo effect. The Arduino board will dispatch the tone information to the speakers thanks to two nested for loops and two if conditions. [1]

Technologies involved

The Arduino program is very close to C.

Steps
  1.     We are defining the pattern
  2.     Each speaker will act as a different channel
  3.     The pattern is being repeated and shifted
  4.     Because the tone function in Arduino cannot play several notes simultaneously, we are tricking human sound perception : two sounds played one after the other very quickly (10 milliseconds in this example) will be interpreted by our brain as simultaneous.


Source code

// This is telling the board which pin to use as an output
int speakerHigh = 8;
int speakerLow = 7;

// This will be the frequency of the notes
int noteValue = 3000;

// This will be the duration of the notes and the pause between them
int theDelay = 10;

// This is the pattern 
char pat[] = "xxx xx x xx ";

// This is the pattern lenght
int patlen = strlen(pat);
 
void setup(){} 
  void loop (){
    
    // This tells the program to begin a new measure after twelve notes have been played 
    for (int iLine=0; iLine<patlen; iLine++){
    
      // The following loop will be completed first, then launched again by the previous one.
      for (int iNote1=0; iNote1<patlen; iNote1++){
      
          // iNote2, the second channel, will be assigned a value resulting from the addition of the two nested loops
          int iNote2 = iNote1+iLine;
          
            // If iNote2 is bigger than 11, it's been resetted to 0 to correpond to a position in the pattern  
            if (iNote2 > (patlen-1)){
              iNote2 = iNote1-patlen+iLine;
            }
  
          // Channel one 
          // Each note value with a position in the pattern, checking if it refers to an "x" or a blank space
          if (pat[iNote1] == 'x') {
            // We have to shut the other speaker in order to make this one play
            noTone(speakerHigh);
            // The note is finally played
            tone(speakerLow, noteValue, theDelay);
            delay(theDelay);
          }
          // Channel two
          // The second channel is played 10 milliseconds after the first, simulating a simultaneous playing.
          if (pat[iNote2] == 'x') {
            noTone(speakerLow);
            tone(speakerHigh, noteValue, theDelay);
          }
   
      delay(theDelay*theDelay);    
    }  
  }
}


Version II : C code and the modulo


How does it work ?

Because the previous code is not as efficient as it can get, we will see how it can be optimised in C. Instead of sending it to the Arduino board, we will create a visual output in the linux shell. The result will show a list of X and blank spaces.

Technologies involved

C.

Steps
  1.     This time we are really using nested loops but without any if.
  2.     Changing the pattern is made possible by assigning to a variable a value that depends on two integer in two different loops. Whereas one of the integer will change every cycle in the smaller loop, the bigger loop that contains the other integer will change its value only when the smaller loop is over.
  3.     One key point of this code is the modulo.
What is the modulo ?

The modulo (a.k.a. %), will give the remainder of a division.

Example :
5%4 = 1 (divide 5 per 4 and 1 will remain)
5%3 = 2 (divide 5 per 4 and 2 will remain)
5%6 = no effect (divide 5 per 6 and you have no remainder)

It is useful to get rid of too many if conditions. By using i%12, the output will never be more than 12. If i goes higher than twelve, the result of i%12 will be the reminder, i.e. it will go from 1 to 12 again.


Source code

#include "stdio.h"
#include "string.h"

char pat[] = "xxx xx x xx ";
int patlen;
// When iShift is going up, the second channel pattern is changed
int iShift = 0;
// iRepeat make each measure repeating twelve times
int iRepeat = 0;
// iNote creates the pattern in the first channel
int iNote = 0;
// iNote2 creates the pattern in the second channel
int iNote2 = 0;

int main(){
  patlen = strlen(pat);

  // This will shift the pattern and create a new measure
  while (iShift <= patlen) {	 

    // This will repeat each mesure twelve times
    while (iRepeat < patlen) { 

      // This will play each measure twelve times
      while ( iNote < patlen) {

        // Because iShift increase at each new measure, the pattern will be shifted accordingly 
        iNote2 = iNote+iShift;
        // We print the first channel, and the second channel
        printf("%c%c\n", pat[iNote], pat[iNote2%12]);
        iNote++;
      }
      iRepeat++;
      iNote=0;
    }
    iShift++;
    iRepeat = 0;
  }
}


  1. The first code couldn't have been completed without the help of Birgit.