issue190:python
Différences
Ci-dessous, les différences entre deux révisions de la page.
Prochaine révision | Révision précédente | ||
issue190:python [2023/02/26 12:06] – créée auntiee | issue190:python [2023/03/01 12:56] (Version actuelle) – andre_domenech | ||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
- | I have an embarrassing confession to make. Between issues with the weather here in central Texas, deadlines on book chapters, support and testing issues, I didn’t start thinking about this issue of FCM until February the first. I didn’t even get around to starting researching or writing the demo programs until the second. However, once I get this all written down, I truly believe I can hold my head up high and be proud of this issue’s article. | + | **I have an embarrassing confession to make. Between issues with the weather here in central Texas, deadlines on book chapters, support and testing issues, I didn’t start thinking about this issue of FCM until February the first. I didn’t even get around to starting researching or writing the demo programs until the second. However, once I get this all written down, I truly believe I can hold my head up high and be proud of this issue’s article. |
- | Speaking of which, let’s get started. You might notice the title of this article. Yes, it DOES have to do with Python and missing beeps. For years, my computer has not had a built-in speaker, so the beep that I would normally rely on to get the user’s attention didn’t function the way I was used to. For a while, I tried in vain to get the blasted BEEP to respond, then something would come up and I’d have to abandon it for a while. Each time, the “a while” became longer and longer, and it eventually got lost in the shuffle. Until today. | + | Speaking of which, let’s get started. You might notice the title of this article. Yes, it DOES have to do with Python and missing beeps. For years, my computer has not had a built-in speaker, so the beep that I would normally rely on to get the user’s attention didn’t function the way I was used to. For a while, I tried in vain to get the blasted BEEP to respond, then something would come up and I’d have to abandon it for a while. Each time, the “a while” became longer and longer, and it eventually got lost in the shuffle. Until today.** |
- | I tried to go back – to find a way to get the bleep working – and still no luck. So I decided to give up on attempting to force a bleep tone out of my speakers, and started looking for an alternative method, one that would not force any of my users to have to install a ton of libraries before they could use a program of mine. I found a library named (of all things) Beepy. It is a pretty simple, lightweight library, and it has only one dependency. So I gave it a try. The instructions said to install it via pip; I’m lucky that my Python installs don’t require using a “3” at the end of my Python and Pip commands, so I forget that many of you aren’t quite that lucky. So if you can use just a “pip”, convert it mentally when you see “pip3”. | + | J'ai une confession embarrassante à faire. Entre les problèmes de météo dans le centre du Texas, les échéances des chapitres du livre, les problèmes de support et de tests, je n'ai pas commencé à penser à ce numéro du FCM avant le 1er février. Je n'ai même pas commencé à faire des recherches ou à écrire les programmes de démonstration avant le 2 février. Cependant, une fois que j' |
+ | |||
+ | Sur ce, commençons. Vous avez peut-être remarqué le titre de cet article. Oui, il a bien un rapport avec Python et les « bips » manquants. Pendant des années, mon ordinateur n'a pas eu de haut-parleur intégré, donc le bip sur lequel je comptais normalement pour attirer l' | ||
+ | |||
+ | |||
+ | **I tried to go back – to find a way to get the bleep working – and still no luck. So I decided to give up on attempting to force a bleep tone out of my speakers, and started looking for an alternative method, one that would not force any of my users to have to install a ton of libraries before they could use a program of mine. I found a library named (of all things) Beepy. It is a pretty simple, lightweight library, and it has only one dependency. So I gave it a try. The instructions said to install it via pip; I’m lucky that my Python installs don’t require using a “3” at the end of my Python and Pip commands, so I forget that many of you aren’t quite that lucky. So if you can use just a “pip”, convert it mentally when you see “pip3”. | ||
pip3 install beepy | pip3 install beepy | ||
Ligne 15: | Ligne 20: | ||
Traceback (most recent call last): | Traceback (most recent call last): | ||
+ | |||
+ | File "< | ||
+ | NameError: name ' | ||
+ | |||
+ | name ' | ||
+ | >>> | ||
+ | |||
+ | J'ai essayé de revenir en arrière - pour trouver un moyen de faire fonctionner le bip - et toujours pas de chance. J'ai donc décidé d' | ||
+ | |||
+ | pip3 install beepy | ||
+ | |||
+ | J'ai lancé mon REPL ptpython... Les instructions disent : | ||
+ | |||
+ | import beepy | ||
+ | beep(sound=1) | ||
+ | |||
+ | C'est assez facile à suivre, même pour moi. Malheureusement, | ||
+ | |||
+ | Traceback (appel le plus récent en dernier) : | ||
File "< | File "< | ||
Ligne 22: | Ligne 46: | ||
>>> | >>> | ||
- | I double checked the documentation (what little there is), and the instructions still read the same. So I thought maybe there was a change in the program and the documentation didn’t get updated, so I scratched multiple body parts and decided I’d take a look at the output of the dir() function. | + | |
+ | **I double checked the documentation (what little there is), and the instructions still read the same. So I thought maybe there was a change in the program and the documentation didn’t get updated, so I scratched multiple body parts and decided I’d take a look at the output of the dir() function. | ||
>>> | >>> | ||
Ligne 43: | Ligne 68: | ||
Following are the mappings for the numbers: 1 : ' | Following are the mappings for the numbers: 1 : ' | ||
- | Hmmm. Only 7 options. I tried all 7 sounds and, while they worked, I wasn’t really impressed. Given the fact that the last release was in 2019, I thought there might be a better solution. | + | Hmmm. Only 7 options. I tried all 7 sounds and, while they worked, I wasn’t really impressed. Given the fact that the last release was in 2019, I thought there might be a better solution.** |
- | Since beepy had only one dependency, I thought I’d try looking at that for something easier and with a bit more options. That dependency is a library called simpleaudio. I ran a search on the Internet and got their github address. https:// | + | J'ai revérifié la documentation (le peu qu'il y a), et les instructions sont toujours les mêmes. J'ai donc pensé qu'il y avait peut-être eu un changement dans le programme et que la documentation n' |
+ | |||
+ | >>> | ||
+ | [' | ||
+ | |||
+ | Il y avait la commande beep, donc je savais qu'il y avait simplement deux façons de la faire fonctionner. Je pouvais essayer : | ||
+ | |||
+ | from beepy import beep | ||
+ | beep(sound=1) | ||
+ | |||
+ | Et voilà ! On a tous pu apprendre quelque chose ! C'est assez simple à inclure et à coder pour moi, si je voulais attirer l' | ||
+ | |||
+ | import beepy | ||
+ | beepy.beep(sound=1) | ||
+ | |||
+ | Et voilà, c' | ||
+ | |||
+ | L' | ||
+ | |||
+ | Voici les correspondances pour les nombres : 1 : ' | ||
+ | |||
+ | Hmmm. Seulement 7 options. J'ai essayé les 7 sons et, bien qu'ils aient fonctionné, | ||
+ | |||
+ | |||
+ | **Since beepy had only one dependency, I thought I’d try looking at that for something easier and with a bit more options. That dependency is a library called simpleaudio. I ran a search on the Internet and got their github address. https:// | ||
import simpleaudio.functionchecks as fc | import simpleaudio.functionchecks as fc | ||
Ligne 53: | Ligne 102: | ||
I thought I’d hear something like “Right speaker” coming out of the speakers, but I was happy to hear a piano note coming out of one of the speakers and, a moment later, the same note but an octave higher out of the other. I started to see some possibilities. I kept reading on. | I thought I’d hear something like “Right speaker” coming out of the speakers, but I was happy to hear a piano note coming out of one of the speakers and, a moment later, the same note but an octave higher out of the other. I started to see some possibilities. I kept reading on. | ||
- | I moved through the documentation, | + | I moved through the documentation, |
+ | |||
+ | Puisque beepy n' | ||
+ | |||
+ | import simpleaudio.functionchecks as fc | ||
+ | |||
+ | fc.LeftRightCheck.run() | ||
+ | |||
+ | Je pensais entendre quelque chose comme « Right speaker » (haut-parleur droit) sortant des haut-parleurs, | ||
+ | |||
+ | J'ai parcouru la documentation, | ||
- | I had just found one of those “meant to be embedded” files and downloaded it to my desktop. I copied the code block into the REPL and changed the example path to my real path and, low and behold, it worked as advertised. The first time! | + | **I had just found one of those “meant to be embedded” files and downloaded it to my desktop. I copied the code block into the REPL and changed the example path to my real path and, low and behold, it worked as advertised. The first time! |
I dug in a bit deeper and found the other thing I wanted. The ability to create a simple tone or two on demand. However, the sample and this part of documentation was all about using numpy to generate the wave forms. This seemed to be a little bit more than I was willing to commit to, but I gave it a try anyway, since the REPL was still up (middle right). | I dug in a bit deeper and found the other thing I wanted. The ability to create a simple tone or two on demand. However, the sample and this part of documentation was all about using numpy to generate the wave forms. This seemed to be a little bit more than I was willing to commit to, but I gave it a try anyway, since the REPL was still up (middle right). | ||
Ligne 61: | Ligne 121: | ||
Well, that is very familiar to a guy who spent 6 years in the school band. If there were only two things I learned in High School, it was music and computers. So the three lines simply give the frequencies of a concert A4, a C# and an E. The next part sort-of made sense and I’m not a big numpy user. Basically, after setting the sample rate, and the duration of any note, numpy generates an array of values (bottom right). | Well, that is very familiar to a guy who spent 6 years in the school band. If there were only two things I learned in High School, it was music and computers. So the three lines simply give the frequencies of a concert A4, a C# and an E. The next part sort-of made sense and I’m not a big numpy user. Basically, after setting the sample rate, and the duration of any note, numpy generates an array of values (bottom right). | ||
- | The next bit of code (below) creates numpy arrays containing the values for the sine waves of the three notes. | + | The next bit of code (below) creates numpy arrays containing the values for the sine waves of the three notes.** |
- | Then, this code (next page, top left) will “bundle up” all the notes and normalize them into a single numpy array. | + | Je venais de trouver un de ces fichiers « destinés à être intégrés » et je l'ai téléchargé sur mon bureau. J'ai copié le bloc de code dans le REPL et j'ai remplacé le chemin d' |
+ | |||
+ | Je venais de trouver l'un de ces fichiers « à intégrer » et l'ai téléchargé sur mon bureau. J'ai copié le bloc de code dans le REPL et j'ai changé le chemin de l' | ||
+ | |||
+ | J'ai creusé un peu plus profondément et j'ai trouvé l' | ||
+ | |||
+ | Eh bien, c'est très familier pour un gars qui a passé 6 ans dans la fanfare de l' | ||
+ | |||
+ | Le bout de code suivant (ci-dessous) crée des tableaux numpy contenant les valeurs des ondes sinusoïdales des trois notes. | ||
+ | |||
+ | |||
+ | **Then, this code (next page, top left) will “bundle up” all the notes and normalize them into a single numpy array. | ||
Then we feed the audio data into the playbuffer and wait for it to be done (top right). | Then we feed the audio data into the playbuffer and wait for it to be done (top right). | ||
Ligne 75: | Ligne 146: | ||
Ah. The T * sample_rate portion is going to return a floating point value so I tried casting it to an integer. | Ah. The T * sample_rate portion is going to return a floating point value so I tried casting it to an integer. | ||
+ | |||
+ | t = np.linspace(0, | ||
+ | |||
+ | Puis, ce code (page suivante, en haut à gauche) va « regrouper » toutes les notes et les normaliser en un seul tableau numpy. | ||
+ | |||
+ | Ensuite, nous introduisons les données audio dans le tampon d' | ||
+ | |||
+ | Sachant que je ne pouvais pas faire de fautes de frappe, puisque j'ai copié le code directement à partir de la documentation, | ||
+ | |||
+ | C' | ||
+ | |||
+ | T = 0.25 | ||
+ | t = np.linspace(0, | ||
+ | |||
+ | Ah ! La partie T * taux d' | ||
t = np.linspace(0, | t = np.linspace(0, | ||
- | When I ran the program again, I was presented with the three tones that I was expecting all along. | ||
- | There were other examples from the website that I tried; one of which creates a higher resolution object; and then I tried to add more notes to the whole process. The idea was to create all the notes from A4 to A5. I modified the base file to calculate | + | **When I ran the program again, |
+ | There were other examples from the website that I tried; one of which creates a higher resolution object; and then I tried to add more notes to the whole process. The idea was to create all the notes from A4 to A5. I modified the base file to calculate all thirteen notes. | ||
+ | < | ||
# calculate the frequencies | # calculate the frequencies | ||
A_freq = 440 | A_freq = 440 | ||
Ligne 96: | Ligne 183: | ||
Gsh_freq = A_freq * 2 ** (11 / 12) | Gsh_freq = A_freq * 2 ** (11 / 12) | ||
A5_freq = 880 | A5_freq = 880 | ||
+ | </ | ||
If you aren’t a musician, this might not mean much to you; however, I’ll try to give you a point of reference. I grabbed a screenshot of the virtual piano keyboard from an app on my computer, and added some hints. | If you aren’t a musician, this might not mean much to you; however, I’ll try to give you a point of reference. I grabbed a screenshot of the virtual piano keyboard from an app on my computer, and added some hints. | ||
- | Each of the white keys are called natural keys. In the image, it starts with middle C (which is C4) and goes up an octave (13 notes) to C5. It’s called middle C because it’s the C key in the middle of the keyboard. | + | Each of the white keys are called natural keys. In the image, it starts with middle C (which is C4) and goes up an octave (13 notes) to C5. It’s called middle C because it’s the C key in the middle of the keyboard.** |
+ | |||
+ | Lorsque j'ai relancé le programme, j'ai obtenu les trois tons que j' | ||
+ | |||
+ | J'ai essayé d' | ||
+ | < | ||
+ | # calculate the frequencies | ||
+ | A_freq = 440 | ||
+ | Ash_freq = A_freq * 2 ** (1 / 12) | ||
+ | B_freq = A_freq * 2 ** (2 / 12) | ||
+ | C_freq = A_freq * 2 ** (3 / 12) | ||
+ | Csh_freq = A_freq * 2 ** (4 / 12) | ||
+ | D_freq = A_freq * 2 ** (5 / 12) | ||
+ | Dsh_freq = A_freq * 2 ** (6 / 12) | ||
+ | E_freq = A_freq * 2 ** (7 / 12) | ||
+ | F_freq = A_freq * 2 ** (8 / 12) | ||
+ | Fsh_freq = A_freq * 2 ** (9 / 12) | ||
+ | G_freq = A_freq * 2 ** (10 / 12) | ||
+ | Gsh_freq = A_freq * 2 ** (11 / 12) | ||
+ | A5_freq = 880 | ||
+ | </ | ||
+ | Si vous n' | ||
+ | |||
+ | Chacune des touches blanches est appelée touche naturelle. Dans l' | ||
- | The black keys are sharps or flats depending on if you are going up the scale or down. So the keys are | + | **The black keys are sharps or flats depending on if you are going up the scale or down. So the keys are |
C, C#, D, D#, E, F, F#, G, G#, A, A#, B and back to C | C, C#, D, D#, E, F, F#, G, G#, A, A#, B and back to C | ||
Ligne 118: | Ligne 228: | ||
with open(" | with open(" | ||
+ | |||
+ | np.save(f, audio)** | ||
+ | | ||
+ | Les touches noires sont des dièses ou des bémols, selon que vous montez ou descendez la gamme. Les clés sont donc : | ||
+ | |||
+ | Do, Do#, Ré, Ré#, Mi, Fa, Fa#, Sol, Sol#, La, La#, Si et retour au Do. | ||
+ | |||
+ | ...pour un total de treize tonalités. Dans la musique « moderne », on appelle cela la gamme tempérée. Il n'en a pas toujours été ainsi, mais c'est une autre paire de manches, alors je ne m'y attarderai pas. | ||
+ | |||
+ | Sachez simplement que les formules ci-dessus pour générer les treize tons fonctionnent bien. | ||
+ | |||
+ | Vous pouvez trouver le programme pour le faire sous le nom de tones4.py dans le dépôt. | ||
+ | |||
+ | J' | ||
+ | |||
+ | La solution pour sauvegarder l' | ||
+ | |||
+ | # enregistrer l' | ||
+ | |||
+ | with open(" | ||
np.save(f, audio) | np.save(f, audio) | ||
+ | | ||
- | That’s it. I’ve saved the program as tones4a.py . The file that was generated can be used again in a different program (top right). | + | **That’s it. I’ve saved the program as tones4a.py . The file that was generated can be used again in a different program (top right). |
This solution, however, still requires having numpy as a dependency in the program. For me, the better solution is not only to have the numpy file (for future use) but to save the audio object to a .wav file. This requires the additional import of the wave package. Add that to the top of the test4 program, and then add the following code at the bottom. | This solution, however, still requires having numpy as a dependency in the program. For me, the better solution is not only to have the numpy file (for future use) but to save the audio object to a .wav file. This requires the additional import of the wave package. Add that to the top of the test4 program, and then add the following code at the bottom. | ||
Ligne 133: | Ligne 264: | ||
This will create a .wav file (without the need to save the numpy data if you don’t want to). Then to play it back, all you need is this short bit of code. | This will create a .wav file (without the need to save the numpy data if you don’t want to). Then to play it back, all you need is this short bit of code. | ||
+ | |||
+ | import simpleaudio as sa | ||
+ | wave_obj = sa.WaveObject.from_wave_file(" | ||
+ | play_obj = wave_obj.play() | ||
+ | play_obj.wait_done()** | ||
+ | |||
+ | C'est tout. J'ai enregistré le programme sous le nom de tones4a.py . Le fichier qui a été généré peut être réutilisé dans un autre programme (en haut à droite). | ||
+ | |||
+ | Cette solution, cependant, nécessite toujours d' | ||
+ | obj = wave.open(" | ||
+ | obj.setnchannels(1) | ||
+ | obj.setampwidth(2) | ||
+ | obj.setframerate(sample_rate) | ||
+ | obj.writeframesraw(audio) | ||
+ | obj.close() | ||
+ | |||
+ | Cela créera un fichier .wav (sans qu'il soit nécessaire de sauvegarder les données numpy si vous ne le souhaitez pas). Ensuite, pour le lire, tout ce dont vous avez besoin est ce petit bout de code : | ||
import simpleaudio as sa | import simpleaudio as sa | ||
Ligne 139: | Ligne 287: | ||
play_obj.wait_done() | play_obj.wait_done() | ||
- | So I modified tones4a.py to include not only the write to a numpy file, but the code to create the .wav file and play it back. | + | |
+ | **So I modified tones4a.py to include not only the write to a numpy file, but the code to create the .wav file and play it back. | ||
I’ve also included the playback routine as a simple python file named play_my_wav.py which will play back the “scale1.wav” file. Of course, the numpy files and some sample .wav files are also in the repository. | I’ve also included the playback routine as a simple python file named play_my_wav.py which will play back the “scale1.wav” file. Of course, the numpy files and some sample .wav files are also in the repository. | ||
Ligne 147: | Ligne 296: | ||
I’ve put the .wav file for Beepy as well as the test file for simpleaudio in my github repository. I’ve also included a few other test files I created for simpleaudio testing. You can find the repository at https:// | I’ve put the .wav file for Beepy as well as the test file for simpleaudio in my github repository. I’ve also included a few other test files I created for simpleaudio testing. You can find the repository at https:// | ||
- | Until next time, as always; stay safe, healthy, positive and creative! | + | Until next time, as always; stay safe, healthy, positive and creative!** |
+ | |||
+ | J'ai donc modifié tones4a.py pour inclure non seulement l' | ||
+ | |||
+ | J'ai également inclus la routine de lecture dans un simple fichier python nommé play_my_wav.py qui lira le fichier « scale1.wav ». Bien sûr, les fichiers numpy et quelques exemples de fichiers .wav sont également dans le dépôt. | ||
+ | |||
+ | Bon, il est temps de conclure pour ce mois-ci. Sachez que la recherche d'une chose aussi simple que de faire sonner votre ordinateur sur commande peut facilement vous conduire sur un chemin où vous pourriez être comme Alice, et « descendre dans le terrier du lapin ». | ||
+ | |||
+ | J'ai mis le fichier .wav pour Beepy ,ainsi que le fichier de test pour simpleaudio, | ||
+ | |||
+ | Jusqu' |
issue190/python.1677409607.txt.gz · Dernière modification : 2023/02/26 12:06 de auntiee