Accéder aux dictionnaires de musique de la classe Sound

Comme vu dans l'article intitulé « Un robot MindStorm EV3 musicien », la méthode play_song() de la classe Sound utilise deux dictionnaires Python, _NOTE_FREQUENCIES et _NOTE_VALUES, respectivement utilisés pour ranger les données relatives aux fréquences et aux durées des notes de musique.
Malheureusement, ces deux dictionnaires ne sont pas accessibles à partir des instances de la classe Sound. En effet, le caractère de soulignement, en langage Python, indique que la variable est déclarée Protected. Cette syntaxe supprime l’accès aux variables d'une classe à partir des instances pour empêcher un usage non approprié de celles-ci et obliger le programmeur utilisant la classe de ne passer que l'interface Public prévue par celle-ci. En revanche, les variables Protected restent accessibles à partir des classes dérivées. L'astuce, pour permettre un accès à ces dictionnaires, consiste donc à créer une nouvelle classe MySound en dérivant la classe Sound, pour exposer ces dictionnaires selon les besoins.
A titre indicatif, la syntaxe Python prévoit aussi le double soulignement en préfixe pour déclarer les variables Private. Lorsqu'une variable est déclarée Private, contrairement à Protected, elle n'est pas non plus accessible à partir des classes dérivées dans lesquelles on ne peut qu'accéder à l'interface Public (ou Protected) de la classe de base.
Cet article présente un exemple de dérivation de la classe Sound pour exposer les deux dictionnaires

Principe de dérivation de la classe Sound

Programmation

#!/usr/bin/env python3

import sys
from ev3dev2.sound import Sound

#1#
class MySound(Sound):

    #2#
    @property
    def note_frequencies(self):
        return self._NOTE_FREQUENCIES
 
    #3#
    @property
    def note_values(self):
        return self._NOTE_VALUES


if __name__ == '__main__':
    #4#
    hp = MySound()
    #5#
    print("Frequences : ", hp.note_frequencies, file=sys.stderr)
    #6#
    print("\nDurees : ", hp.note_values, file=sys.stderr)

Explications

  1. La classe MySound est déclarée en passant en paramètre la classe Sound pour indiquer que MySound est dérivée de Sound.  La classe MySound hérite des propriétés de la classe Sound
  2. La propriété note_frequencies permet d'exposer le dictionnaire Protected  _NOTE_FREQUENCIES dans l'interface publique de la classe. Le décorateur @property permet d'utiliser cette propriété à partir des instances comme une variable et non comme une fonction.
  3. La propriété note_values permet d'exposer le dictionnaire Protected  _NOTE_VALUES dans l'interface publique de la classe. Le décorateur @property permet d'utiliser cette propriété à partir des instances comme une variable et non comme une fonction.
  4. C'est la classe MySound qui doit être instanciée et non plus la classe Sound. L'instance de la classe MySound est affecté à la variable hp.  Ceci n'est q'un exemple. Pour l'utilisation dans un robot, il conviendrait d'affecter cette instance à une variable globale HP en lieu et place de l'instance de la classe Sound utilisée habituellement.
  5. La propriété note_frequencies peut être utilisée dans l'instance hp. L'instruction Python print affiche par défaut sur l'écran LCD de la brique EV3 (de façon illisible en tout petits caractères). Le paramètre file=sys.stderr permet de détourner l'affichage vers la console de VSCode. 
  6. La propriété note_values peut être utilisée dans l'instance hp. Ci-dessous ce que ce programme affiche sur la console de VSCode.

Résultat affiché dans la console

Starting: brickrun --directory="/home/robot/Exploration" "/home/robot/Exploration/mysound.py"
Started.
----------
Frequences :  {'Db2': 69, 'C#7': 2217, 'Gb7': 2960, 'Db3': 139, 'G3': 196, 'G7': 3136, 'G8': 6272, 'A6': 1760, 'Eb8': 4978, 'G1': 49, 'C#3': 139, 'A7': 3520, 'F1': 44, 'G#6': 1661, 'D#2': 78, 'Bb7': 3729, 'Db0': 17, 'A#2': 117, 'D4': 294, 'Bb8': 7459, 'C#8': 4435, 'A3': 220, 'C#5': 554, 'G5': 784, 'Bb5': 932, 'A4': 440, 'Db1': 35, 'G2': 98, 'D5': 587, 'Eb3': 156, 'B0': 31, 'F#1': 46, 'Gb4': 370, 'E8': 5274, 'E6': 1319, 'E2': 82, 'D#6': 1245, 'G#0': 26, 'Db8': 4435, 'D3': 147, 'Ab0': 26, 'Eb2': 78, 'Bb3': 233, 'D6': 1175, 'D8': 4699, 'Eb0': 19, 'F#3': 185, 'G6': 1568, 'Bb4': 466, 'B2': 123, 'D1': 37, 'Gb6': 1480, 'B5': 988, 'F#8': 5920, 'D7': 2349, 'A#7': 3729, 'D#4': 311, 'G#5': 831, 'A#5': 932, 'Eb5': 622, 'C2': 65, 'Bb6': 1865, 'E4': 330, 'D2': 73, 'C8': 4186, 'Db6': 1109, 'A#3': 233, 'C5': 523, 'C4': 262, 'C#2': 69, 'E5': 659, 'G#1': 52, 'Bb1': 58, 'G#7': 3322, 'B7': 3951, 'C1': 33, 'Ab7': 3322, 'Db5': 554, 'D#8': 4978, 'C0': 16, 'G#8': 6645, 'C#1': 35, 'F3': 175, 'Gb0': 23, 'C#4': 277, 'A0': 28, 'F7': 2794, 'C#6': 1109, 'F#7': 2960, 'Ab1': 52, 'B3': 247, 'F#5': 740, 'C6': 1046, 'A#4': 466, 'G#3': 208, 'A#1': 58, 'D#5': 622, 'Eb6': 1245, 'Bb0': 29, 'D#0': 19, 'F4': 349, 'Eb4': 311, 'Gb5': 740, 'F8': 5588, 'D#3': 156, 'A8': 7040, 'A5': 880, 'C#0': 17, 'E3': 165, 'C7': 2093, 'C3': 131, 'F0': 22, 'Ab6': 1661, 'Eb7': 2489, 'Ab8': 6645, 'A#0': 29, 'A#6': 1865, 'A1': 55, 'Ab2': 104, 'Db7': 2217, 'E0': 21, 'G0': 24, 'F#0': 23, 'A#8': 7459, 'Bb2': 117, 'F5': 698, 'F2': 87, 'B6': 1976, 'D#7': 2489, 'D#1': 39, 'F6': 1397, 'Ab4': 415, 'D0': 18, 'Ab3': 208, 'B8': 7902, 'Gb8': 5920, 'F#6': 1480, 'Ab5': 831, 'G#2': 104, 'G4': 392, 'Db4': 277, 'Gb1': 46, 'G#4': 415, 'A2': 110, 'Gb2': 92, 'E7': 2637, 'E1': 41, 'Gb3': 185, 'B1': 62, 'F#2': 92, 'B4': 494, 'F#4': 370, 'Eb1': 39}

Durees :  {'q': 0.25, 'w': 1.0, 'h': 0.5, 'e': 0.125, 's': 0.0625}
----------
Completed successfully.

Commentaires

Posts les plus consultés de ce blog

Connecter ev3dev2 à Internet en WiFi

Connecter Visual Studio Code à un robot MindStorm EV3 avec ev3dev-browser

Installer les modules EV3DEV2 sur Python