clapping_music_for_robots
Différences
Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente | ||
clapping_music_for_robots [2022/03/14 09:29] – Simon Deplat | clapping_music_for_robots [2022/03/14 11:15] (Version actuelle) – Simon Deplat | ||
---|---|---|---|
Ligne 21: | Ligne 21: | ||
L' | L' | ||
- | Dans sa première version, elle a eu une idée géniale : déclarer deux boucles différentes pour chacun des servos, et indiquer de manière brute la partition en assignant les temps d' | + | Dans sa première version, elle a eu une idée géniale : **déclarer deux boucles différentes pour chacun des servos, et indiquer de manière brute la partition en assignant les temps d' |
Malheureusement, | Malheureusement, | ||
Ligne 27: | Ligne 27: | ||
Plus grave encore, il n'est en fait **pas possible de déclarer deux boucles différentes dans l' | Plus grave encore, il n'est en fait **pas possible de déclarer deux boucles différentes dans l' | ||
- | L' | + | L' |
+ | |||
+ | =====Partition à raie===== | ||
+ | Je lui ai donc pointé du doigt quelque chose de presque magique : **il est possible de considérer une //Array// comme une partition**. | ||
+ | |||
+ | Si nous prenons l' | ||
+ | |||
+ | < | ||
+ | [ 1, 0, 0, 1, 0, 0, 1, 0 ] | ||
+ | </ | ||
+ | |||
+ | On peut y voir **une représentation d'une partition rythmique représentant la clave ||: Noire pointée - Noire pointée - Noire :||** si l'on itère régulièrement dessus, ne jouant une note que si l' | ||
+ | |||
+ | On peut étendre ce principe plus loin, en modifiant le // | ||
+ | |||
+ | Un séquenceur probabiliste : | ||
+ | |||
+ | < | ||
+ | [ 1, 0, 0.5, 1, 0, 0.5, 1, 0.25 ] | ||
+ | </ | ||
+ | |||
+ | Ou des durée de notes : | ||
+ | |||
+ | < | ||
+ | [ 1, 0, 0.5, 1, 0, 0.5, 1, 0.25 ] | ||
+ | </ | ||
+ | |||
+ | Mais du coup, **pas les deux en même temps** si le contenu de l'// | ||
+ | |||
+ | Un dernier exemple, la basse d' | ||
+ | |||
+ | < | ||
+ | [ 60, 67, 64, 67 ] | ||
+ | </ | ||
+ | |||
+ | =====écalageD===== | ||
+ | Dans cette optique, j'ai indiqué à l' | ||
+ | |||
+ | Elle m'a rétorqué qu'en fait, **vu qu'on accède à l'// | ||
+ | |||
+ | **Ce qui est tout-à-fait vrai, et même pertinent en terme algorithmique.** Cela pose un problème de dépassement car le décalage demandera à un moment d' | ||
+ | |||
+ | Cependant, je lui ai conseillé dans un premier temps de **reconstruire la seconde voix de manière algorithmique pour que l'// | ||
+ | |||
+ | =====Représentation===== | ||
+ | Cette orientation était avant tout didactique : je pense qu'il est mieux d' | ||
+ | |||
+ | Je laisse ici de côté la solution de reconstruction de la bonne partition à chaque changement pour me concentrer sur **les solutions alternatives, | ||
+ | |||
+ | La première solution pour résoudre le problème est la suivante : | ||
+ | |||
+ | Nous commençons par dupliquer notre partition : | ||
+ | |||
+ | {{ :: | ||
+ | |||
+ | Si vous y réfléchissez, | ||
+ | |||
+ | Maintenant, voici comme est décrite notre partition en terme algorithmique : | ||
+ | |||
+ | {{ :: | ||
+ | |||
+ | À chaque fin de cycles, on augmente le décalage de la seconde voix, et on le remet à zéro s'il atteint le nombre de temps de la clave initiale. | ||
+ | |||
+ | Ce qui semble étrange, c'est que **cette méthode introduit une asymétrie de représentation des deux voix**. Une information supplémentaire est nécessaire pour situer la voix II : son décalage par rapport à l' | ||
+ | |||
+ | Ce n'est pas le cas avec la représentation " | ||
+ | |||
+ | {{ :: | ||
+ | |||
+ | **Les deux font pourtant référence au même objet.** La première solution est efficiente en terme de calcul. La seconde est plus facile à comprendre pour les humains. | ||
+ | |||
+ | Voici le code associé à cet algorithme, qui, à la place de servomoteurs, | ||
+ | |||
+ | < | ||
+ | int ledPin1 = 2; | ||
+ | int ledPin2 = 3; | ||
+ | |||
+ | int msBetweenBeats = 200; | ||
+ | |||
+ | int initialScore[] = { 1, 0, 0, 1, 0, 0, 1, 0 }; | ||
+ | int score[16]; | ||
+ | |||
+ | int currentBeat = 0; | ||
+ | |||
+ | int numberOfBeats; | ||
+ | |||
+ | int currentCycleRepetition = 0; | ||
+ | int numberOfCycleRepetitions = 4; | ||
+ | int currentCycle = 0; | ||
+ | |||
+ | void setup() { | ||
+ | Serial.begin(9600); | ||
+ | |||
+ | pinMode( ledPin1, OUTPUT ); | ||
+ | pinMode( ledPin2, OUTPUT ); | ||
+ | |||
+ | numberOfBeats = sizeof( initialScore ) / sizeof( initialScore[0] ); | ||
+ | |||
+ | for( int i = 0; i < ( numberOfBeats * 2 ); i++ ) { | ||
+ | score[ i ] = initialScore[ i%numberOfBeats ]; | ||
+ | }; | ||
+ | |||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | |||
+ | Serial.println( score[ currentBeat + currentCycle ] ); | ||
+ | |||
+ | if( score[ currentBeat ] == 1 ) { | ||
+ | digitalWrite( ledPin1, HIGH ); | ||
+ | }; | ||
+ | |||
+ | if( score[ currentBeat + currentCycle ] == 1 ) { | ||
+ | digitalWrite( ledPin2, HIGH ); | ||
+ | }; | ||
+ | |||
+ | delay( msBetweenBeats / 4 * 3 ); | ||
+ | |||
+ | digitalWrite( ledPin1, LOW ); | ||
+ | digitalWrite( ledPin2, LOW ); | ||
+ | |||
+ | delay( msBetweenBeats / 4 ); | ||
+ | |||
+ | currentBeat = currentBeat + 1; | ||
+ | |||
+ | if( currentBeat == numberOfBeats ) { | ||
+ | |||
+ | currentBeat = 0; | ||
+ | currentCycleRepetition = currentCycleRepetition + 1; | ||
+ | |||
+ | if( currentCycleRepetition == numberOfCycleRepetitions ) { | ||
+ | currentCycleRepetition = 0; | ||
+ | currentCycle = currentCycle + 1; | ||
+ | |||
+ | if( currentCycle == numberOfBeats ) { | ||
+ | currentCycle = 0; | ||
+ | }; | ||
+ | }; | ||
+ | }; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | =====Physiologie ?===== | ||
+ | Pour aller encore plus loin, il faut noter que **le duplicata de l'// | ||
+ | |||
+ | Avec cet algorithme, **il n'est même plus possible de représenter adéquatement la " | ||
+ | |||
+ | < | ||
+ | noteAcutelleDeLaDeuxièmeVoix = score[ ( currentBeat + currentCycle ) % numberOfBeats ]; | ||
+ | </ | ||
+ | |||
+ | Encore une fois pourtant, l' | ||
+ | |||
+ | Cela nous questionne sur **la définition de la partition**. | ||
+ | |||
+ | **Doit-elle être considérée comme un système de symbole purement informatifs, | ||
+ | |||
+ | **La version " | ||
+ | |||
+ | À l' | ||
+ | |||
+ | < | ||
+ | int ledPin1 = 2; | ||
+ | int ledPin2 = 3; | ||
+ | |||
+ | int msBetweenBeats = 200; | ||
+ | |||
+ | int score[] = { 1, 0, 0, 1, 0, 0, 1, 0 }; | ||
+ | |||
+ | int currentBeat = 0; | ||
+ | |||
+ | int numberOfBeats; | ||
+ | |||
+ | int currentCycleRepetition = 0; | ||
+ | int numberOfCycleRepetitions = 4; | ||
+ | int currentCycle = 0; | ||
+ | |||
+ | void setup() { | ||
+ | Serial.begin(9600); | ||
+ | |||
+ | pinMode( ledPin1, OUTPUT ); | ||
+ | pinMode( ledPin2, OUTPUT ); | ||
+ | |||
+ | numberOfBeats = sizeof( score ) / sizeof( score[0] ); | ||
+ | |||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | |||
+ | Serial.println( score[ currentBeat + currentCycle ] ); | ||
+ | |||
+ | if( score[ currentBeat ] == 1 ) { | ||
+ | digitalWrite( ledPin1, HIGH ); | ||
+ | }; | ||
+ | |||
+ | if( score[ ( currentBeat + currentCycle ) % numberOfBeats ] == 1 ) { | ||
+ | digitalWrite( ledPin2, HIGH ); | ||
+ | }; | ||
+ | |||
+ | delay( msBetweenBeats / 4 * 3 ); | ||
+ | |||
+ | digitalWrite( ledPin1, LOW ); | ||
+ | digitalWrite( ledPin2, LOW ); | ||
+ | |||
+ | delay( msBetweenBeats / 4 ); | ||
+ | |||
+ | currentBeat = currentBeat + 1; | ||
+ | |||
+ | if( currentBeat == numberOfBeats ) { | ||
+ | |||
+ | currentBeat = 0; | ||
+ | currentCycleRepetition = currentCycleRepetition + 1; | ||
+ | |||
+ | if( currentCycleRepetition == numberOfCycleRepetitions ) { | ||
+ | currentCycleRepetition = 0; | ||
+ | currentCycle = currentCycle + 1; | ||
+ | |||
+ | if( currentCycle == numberOfBeats ) { | ||
+ | currentCycle = 0; | ||
+ | }; | ||
+ | }; | ||
+ | }; | ||
+ | } | ||
+ | </ |
clapping_music_for_robots.1647250176.txt.gz · Dernière modification : 2022/03/14 09:29 de Simon Deplat