From df68e7e510499af212aff0245f03fa1ca6f89f80 Mon Sep 17 00:00:00 2001 From: Jean-Marie Favreau <jm.trivial@gmail.com> Date: Wed, 6 Feb 2019 12:53:31 +0100 Subject: [PATCH] =?UTF-8?q?ajout=20de=20nouvelles=20m=C3=A9lodies,=20et=20?= =?UTF-8?q?am=C3=A9lioration=20des=20rendus?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 12 +++- brahms.py | 9 ++- joie.py | 8 ++- lune.py | 58 +++++++++++++++ musique/exercice.py | 169 ++++++++++++++++++++++++++++++++++++-------- tabac2.py | 50 +++++++------ 6 files changed, 247 insertions(+), 59 deletions(-) create mode 100644 lune.py diff --git a/Makefile b/Makefile index 0065516..7c9ae6b 100644 --- a/Makefile +++ b/Makefile @@ -4,24 +4,30 @@ SONS=sons/ SCRIPTS=$(wildcard *.py) EXESPECTEX=$(addprefix $(EXERCICESDIR)/ex-spec-,$(SCRIPTS:.py=.tex)) EXESPECPDF=$(EXESPECTEX:.tex=.pdf) + +EXEPROJTEX=$(EXERCICESDIR)/ex-proj-joie.tex $(EXERCICESDIR)/ex-proj-brahms.tex $(EXERCICESDIR)/ex-proj-lune.tex $(EXERCICESDIR)/ex-proj-tabac2.tex +EXEPROJPDF=$(EXEPROJTEX:.tex=.pdf) WAVES=$(addprefix $(SONS)/,$(SCRIPTS:.py=.wav)) BOOMWHACKERS=boomwhackers-8.json -.PRECIOUS: $(EXESPECTEX) +.PRECIOUS: $(EXESPECTEX) $(EXEPROJTEX) all: waves pdf waves: $(WAVES) -pdf: $(EXESPECPDF) +pdf: $(EXESPECPDF) $(EXEPROJPDF) -tex: $(EXESPECTEX) +tex: $(EXESPECTEX) $(EXEPROJTEX) $(EXERCICESDIR)/%.pdf: $(EXERCICESDIR)/%.tex cd $(EXERCICESDIR); pdflatex $(<:$(EXERCICESDIR)/%=%); cd .. $(EXERCICESDIR)/ex-spec-%.tex: %.py python $< --exercice-spectrogramme --boomwhackers=$(BOOMWHACKERS) + +$(EXERCICESDIR)/ex-proj-%.tex: %.py + python $< --exercice-spectrogramme-transparent --boomwhackers=$(BOOMWHACKERS) $(SONS)/%.wav: %.py python $< diff --git a/brahms.py b/brahms.py index 1e68521..6a0de06 100644 --- a/brahms.py +++ b/brahms.py @@ -9,6 +9,7 @@ from musique.gamme import GammeTemperee parser = argparse.ArgumentParser(description='Génère des documents à partir de la partition du thème Lullaby, berceuse de Brahms.') parser.add_argument('--exercice-spectrogramme', help="Génère un exercice plutôt que le fichier son", dest='exerciceSpectrogramme', action='store_true',default=False) +parser.add_argument('--exercice-spectrogramme-transparent', help="Génère un exercice à projeter", dest='transparent', action='store_true',default=False) parser.add_argument('--boomwhackers', help="Génère un exercice plutôt que le fichier son", dest='boomwhackers', nargs=1) args = parser.parse_args() @@ -55,11 +56,15 @@ brahms = [ [ [gamme.mi(3), gamme.croche], ] ] -if args.exerciceSpectrogramme: +if args.exerciceSpectrogramme or args.transparent: g = GenerateurExercice(gamme.bpm) g.setBoomwhackers(boomwhackers) g.setLongueurPartitionColoree(6) - g.genererExerciceSpectrogramme(brahms, "exercices/ex-spec-brahms.tex", "thème 2") + if args.exerciceSpectrogramme: + g.genererExerciceSpectrogramme(brahms, "exercices/ex-spec-brahms.tex", "thème 4", "Lullaby, berceuse de Brahms") + if args.transparent: + g.genererTransparentSpectrogramme(brahms, "exercices/ex-proj-brahms.tex", "thème 4", "Lullaby, berceuse de Brahms") + else: print "Génération du son" s = BasicSequenceur(1, gamme.bpm, 0) diff --git a/joie.py b/joie.py index 4c1765c..6119346 100644 --- a/joie.py +++ b/joie.py @@ -9,6 +9,7 @@ from musique.gamme import GammeTemperee parser = argparse.ArgumentParser(description='Génère des documents à partir de la partition du thème ode à la joie.') parser.add_argument('--exercice-spectrogramme', help="Génère un exercice plutôt que le fichier son", dest='exerciceSpectrogramme', action='store_true',default=False) +parser.add_argument('--exercice-spectrogramme-transparent', help="Génère un exercice à projeter", dest='transparent', action='store_true',default=False) parser.add_argument('--boomwhackers', help="Génère un exercice plutôt que le fichier son", dest='boomwhackers', nargs=1) args = parser.parse_args() @@ -67,11 +68,14 @@ joie = [ [ [E, gamme.noire], ] ] -if args.exerciceSpectrogramme: +if args.exerciceSpectrogramme or args.transparent: g = GenerateurExercice(gamme.bpm) g.setBoomwhackers(boomwhackers) g.setLongueurPartitionColoree(8) - g.genererExerciceSpectrogramme(joie, "exercices/ex-spec-joie.tex", "thème 1") + if args.exerciceSpectrogramme: + g.genererExerciceSpectrogramme(joie, "exercices/ex-spec-joie.tex", "thème 1", "Hymne à la joie") + if args.transparent: + g.genererTransparentSpectrogramme(joie, "exercices/ex-proj-joie.tex", "thème 1", "Hymne à la joie") else: print "Génération du son" s = BasicSequenceur(1, gamme.bpm, 0) diff --git a/lune.py b/lune.py new file mode 100644 index 0000000..efd0dd3 --- /dev/null +++ b/lune.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python +# coding: utf8 +# -*- coding: utf-8 -*- + +import argparse +from musique.basicsynth import BasicSequenceur +from musique.exercice import GenerateurExercice +from musique.gamme import GammeTemperee + +parser = argparse.ArgumentParser(description='Génère des documents à partir de la partition du thème au clair de la lune.') +parser.add_argument('--exercice-spectrogramme', help="Génère un exercice plutôt que le fichier son", dest='exerciceSpectrogramme', action='store_true',default=False) +parser.add_argument('--exercice-spectrogramme-transparent', help="Génère un exercice à projeter", dest='transparent', action='store_true',default=False) +parser.add_argument('--boomwhackers', help="Génère un exercice plutôt que le fichier son", dest='boomwhackers', nargs=1) + +args = parser.parse_args() + +gamme = GammeTemperee(80) + + +boomwhackers = "" +if not args.boomwhackers is None: + boomwhackers = args.boomwhackers[0] + + +lune = [ [ [gamme.do(4), gamme.croche], + [gamme.do(4), gamme.croche], + [gamme.do(4), gamme.croche], + [gamme.re(4), gamme.croche], + + [gamme.mi(4), gamme.noire], + [gamme.re(4), gamme.noire], + + [gamme.do(4), gamme.croche], + [gamme.mi(4), gamme.croche], + [gamme.re(4), gamme.croche], + [gamme.re(4), gamme.croche], + + [gamme.do(4), gamme.blanche], + + + + ] ] + + +if args.exerciceSpectrogramme or args.transparent: + g = GenerateurExercice(gamme.bpm) + g.setBoomwhackers(boomwhackers) + g.setLongueurPartitionColoree(4) + if args.exerciceSpectrogramme: + g.genererExerciceSpectrogramme(lune, "exercices/ex-spec-lune.tex", "thème 2", "Au clair de la lune") + if args.transparent: + g.genererTransparentSpectrogramme(lune, "exercices/ex-proj-lune.tex", "thème 2", "Au clair de la lune") + +else: + print "Génération du son" + s = BasicSequenceur(1, gamme.bpm, 0) + s.genererMelodie(lune, "sons/lune.wav") + diff --git a/musique/exercice.py b/musique/exercice.py index 41904ed..4fe2bb5 100644 --- a/musique/exercice.py +++ b/musique/exercice.py @@ -106,11 +106,41 @@ class GenerateurExercice(GammeTemperee): result += "\\maketitle\n" result += "\\thispagestyle{empty}\n" return result - + + def enteteBeamer(self, titre): + result = "\\documentclass{beamer}\n" + result += "\\usepackage[utf8]{inputenc}\n" + result += "\\usepackage[french]{babel}\n" + result += "\\usepackage{tikz,pgfplots}\n" + result += "\\usepackage{float}\n" + result += "\\usetikzlibrary{positioning}\n" + result += "\\usetikzlibrary{shapes.geometric}\n" + result += "\\usetikzlibrary{shapes.symbols}\n" + result += "\\usetikzlibrary{shadows}\n" + result += "\\usetikzlibrary{decorations.pathmorphing, patterns,shapes}\n" + result += "\\usetikzlibrary{positioning, decorations.markings}\n" + result += "\\usepgflibrary{arrows}\n" + result += "\\usetikzlibrary{arrows}\n" + result += "\\pagestyle{empty}\n" + result += "\\usepackage{helvet}" + result += "\\usepackage{musixtex}" + result += "\\usepackage{harmony}" + result += "\\renewcommand{\\familydefault}{\\sfdefault}" + + + result += "\\title{" + titre + "}\n" + result += "\\date{}\n" + result += "\\begin{document}\n" + result += "\\frame{\\titlepage}" + return result + # cette fonction retourne le pied d'un document LaTeX def piedLaTeX(self): return "\\end{document}\n" + # cette fonction retourne le pied d'un document Beamer + def piedBeamer(self): + return "\\end{document}\n" # cette fonction écrit le début de l'exercice spectrogramme def debutExerciceSpectrogramme(self): result = "\n" @@ -185,7 +215,7 @@ class GenerateurExercice(GammeTemperee): # on ne va utiliser que la première partition partition = partitions[0] - result = "\\renewcommand{\\arraystretch}{1.5}" + result = "\\renewcommand{\\arraystretch}{1.3}" result += "\\begin{table}[H]\n\centering\n" if solution: result += "\\begin{tabular}{|c||c|c||c|c|}\n" @@ -217,7 +247,7 @@ class GenerateurExercice(GammeTemperee): else: result += " & \\\\\n" result += "\\hline\n" - if not solution: + if solution: result += "\\hline\n" result += "\\end{tabular}\n" if solution: @@ -305,19 +335,27 @@ class GenerateurExercice(GammeTemperee): return result - def ensembleDesNotesGraphiques(self, frequences, radius): + def ensembleDesNotesGraphiques(self, frequences, radius, beamer): result = "" notes = sorted(list(set(frequences))) result += "\\begin{table}[H]\n\centering\n" - result += "\\begin{tabular}{|r|" + "".join(["c|"] * len(notes)) + "}\n" - result += "\\hline\n" + if not beamer: + result += "\\begin{tabular}{|r|" + "".join(["c|"] * len(notes)) + "}\n" + else: + result += "\\begin{tabular}{r|" + "".join(["c"] * len(notes)) + "}\n" + if not beamer: + result += "\\hline\n" result += "Notes" for n in notes: result += "&" + if beamer: + result += "\\hspace*{.2cm}" result += self.frequenceToLaTeX(n) + if beamer: + result += "\\hspace*{.2cm}" result += "\\\\ \n" result += "Forme" for n in notes: @@ -328,27 +366,40 @@ class GenerateurExercice(GammeTemperee): result += self.pointColore(mw, 0, 0, radius) result += "\\end{tikzpicture}" result += "\\\\ \n" - result += "Prénom" - for n in notes: - result += "&" - result += "\\hspace*{2cm}" - result += "\\\\ \n" - result += "\\hline\n" + if not beamer: + result += "Prénom" + for n in notes: + result += "&" + result += "\\hspace*{2cm}" + result += "\\\\ \n" + if not beamer: + result += "\\hline\n" result += "\\end{tabular}\n" result += "\\caption{Représentation colorée des notes}\n" result += "\\end{table}\n" return result - def partitionGraphique(self, partitions): + def partitionGraphique(self, partitions, beamer = False): + + result = "" + if beamer: + result += "\\frame{" + result += "\\frametitle{Partition graphique}" + frequences = self.notesDansPartition(partitions) x = 0. y = 0. - stepx = 2 - stepy = 2.5 + if beamer: + stepx = 1 + stepy = 1.2 + else: + stepx = 2 + stepy = 2.5 + radius = stepx * 0.22 finDeLigne = self.longueurPartitionColoree * stepx @@ -358,9 +409,10 @@ class GenerateurExercice(GammeTemperee): p = partitions[0] - result += self.ensembleDesNotesGraphiques(frequences, radius) + result += self.ensembleDesNotesGraphiques(frequences, radius, beamer) - result += "La partition graphique suivante se lit ligne par ligne. Les durées sont représentées par les espaces entre les cercles colorés. \n \n" + if not beamer: + result += "La partition graphique suivante se lit ligne par ligne. Les durées sont représentées par les espaces entre les cercles colorés. \n \n" result += "\\begin{figure}[H]" result += "\\begin{tikzpicture}[]" @@ -384,15 +436,23 @@ class GenerateurExercice(GammeTemperee): result += "\\end{tikzpicture}" - result += "\\caption{Partition graphique retranscrite depuis le tableau des notes de la partition}" + if not beamer: + result += "\\caption{Partition graphique retranscrite depuis le tableau des notes de la partition}" result += "\\end{figure}" else: result += "Cette partition n'est pas représentable sous forme de partition pour boomwhackers diatoniques." - + + if beamer: + result += "}" return result - def partitionMusicale(self, partitions): + def partitionMusicale(self, partitions, beamer = False): result = "" + + if beamer: + result += "\\frame{" + result += "\\frametitle{Partition musicale}" + if len(partitions) == 1: partition = partitions[0] @@ -407,7 +467,10 @@ class GenerateurExercice(GammeTemperee): maxNote = max([ n for n in notes if n[1] > 0]) (maxoctave, maxidnote) = maxNote midOctave = int((maxoctave + minoctave) / 2) - result += "\\normalmusicsize" + if beamer: + result += "\\normalmusicsize" + else: + result += "\\Largemusicsize" result += "\\begin{figure}[H]" result += "\\begin{music}" #result += "\\parindent10mm" @@ -427,15 +490,16 @@ class GenerateurExercice(GammeTemperee): result += "\\end{music}" result += "\\caption{Partition simplifiée}" result += "\\end{figure}" - else: result += "Le générateur d'exercice ne prend pas en charge cette partition." - + + if beamer: + result += "}" return result # cette fonction écrit la fin de l'exercice spectrogramme - def finExerciceSpectrogramme(self, partitions): + def finExerciceSpectrogramme(self, partitions, nomSolution): result = "\n" result += "~\\clearpage\n" @@ -457,16 +521,23 @@ class GenerateurExercice(GammeTemperee): result += self.tableauNotesBrutes(partitions, False) + result += "~\\clearpage\n" result += "\\section{Solution}\n" # on écrit le tableau solution de l'exercice result += self.tableauNotesBrutes(partitions, True) + result += "~\\clearpage\n" + result += "\\section{Partition graphique}\n" result += self.partitionGraphique(partitions) result += "\\section{Partition musicale}\n" result += self.partitionMusicale(partitions) + if nomSolution != "": + result += "\\section{Solution}\n" + result += "Cette mélodie s'appelle " + nomSolution + return result @@ -598,11 +669,19 @@ class GenerateurExercice(GammeTemperee): # cette fonction écrit le spectrogramme simplifié correspondant à la # partition donnée en paramètre - def spectrogramme(self, partitions): - # on commence par initialiser l'échelle - self.initialisationEchelleSpectrogramme(partitions, 21 - 2 * self.margeDocument - self.margeLegende, 12) + def spectrogramme(self, partitions, beamer = False): result = "" + # on commence par initialiser l'échelle + if beamer: + result += "\\frame{" + result += "\\frametitle{Spectrogramme}" + self.initialisationEchelleSpectrogramme(partitions, 12 - 2 * self.margeDocument - self.margeLegende, 7) + else: + self.initialisationEchelleSpectrogramme(partitions, 21 - 2 * self.margeDocument - self.margeLegende, 12) + + + result += "\\begin{tikzpicture}[]" # lignes verticales @@ -631,6 +710,9 @@ class GenerateurExercice(GammeTemperee): result += self.notesSpectrogrammePartition(p, couleur.get(i, "lightgray")) result += "\\end{tikzpicture}" + + if beamer: + result += "}" return result @@ -642,7 +724,7 @@ class GenerateurExercice(GammeTemperee): # où chaque liste décrit la partition d'une "main". Une partition est décrite comme # une liste d'éléments composés d'une ou plusieurs notes (quantifiée par une frequence) et d'une duree exprimee en seconde. # * nomFichier: le nom d'un fichier où sera sauvée la feuille d'exercice - def genererExerciceSpectrogramme(self, partitions, nomFichier, nomMelodie): + def genererExerciceSpectrogramme(self, partitions, nomFichier, nomMelodie, nomSolution=""): # on ouvre le fichier l_fichier = open(nomFichier, "w") @@ -657,10 +739,39 @@ class GenerateurExercice(GammeTemperee): l_fichier.write(self.spectrogramme(partitions)) # on écrit la suite de l'exercice - l_fichier.write(self.finExerciceSpectrogramme(partitions)) + l_fichier.write(self.finExerciceSpectrogramme(partitions, nomSolution)) # on écrit la fin du document LaTeX l_fichier.write(self.piedLaTeX()) # on ferme le fichier l_fichier.close() + + def genererTransparentSpectrogramme(self, partitions, nomFichier, nomMelodie, nomSolution=""): + + # on ouvre le fichier + l_fichier = open(nomFichier, "w") + + # on écrit les entêtes du document LaTeX + l_fichier.write(self.enteteBeamer(nomMelodie)) + + l_fichier.write(self.spectrogramme(partitions, True)) + + l_fichier.write(self.partitionGraphique(partitions, True)) + + l_fichier.write(self.partitionMusicale(partitions, True)) + + if nomSolution != "": + result = "\\frame{" + result += "\\frametitle{Solution}\n" + result += "\\begin{center}\Large Cette mélodie s'appelle " + nomSolution + "\\end{center}" + result += "}" + l_fichier.write(result) + + + + # on écrit la fin du document LaTeX + l_fichier.write(self.piedBeamer()) + + # on ferme le fichier + l_fichier.close() diff --git a/tabac2.py b/tabac2.py index fbdd7aa..011d874 100644 --- a/tabac2.py +++ b/tabac2.py @@ -9,6 +9,7 @@ from musique.gamme import GammeTemperee parser = argparse.ArgumentParser(description='Génère des documents à partir de la partition du thème j\'ai du bon tabac.') parser.add_argument('--exercice-spectrogramme', help="Génère un exercice plutôt que le fichier son", dest='exerciceSpectrogramme', action='store_true',default=False) +parser.add_argument('--exercice-spectrogramme-transparent', help="Génère un exercice à projeter", dest='transparent', action='store_true',default=False) parser.add_argument('--boomwhackers', help="Génère un exercice plutôt que le fichier son", dest='boomwhackers', nargs=1) args = parser.parse_args() @@ -21,42 +22,45 @@ if not args.boomwhackers is None: boomwhackers = args.boomwhackers[0] -tabac = [ [ [gamme.fa(3), gamme.croche], - [gamme.sol(3), gamme.croche], - [gamme.la(3), gamme.croche], - [gamme.fa(3), gamme.croche], +tabac = [ [ [gamme.do(3), gamme.croche], + [gamme.re(3), gamme.croche], + [gamme.mi(3), gamme.croche], + [gamme.do(3), gamme.croche], - [gamme.sol(3), gamme.noire], - [gamme.sol(3), gamme.croche], - [gamme.la(3), gamme.croche], + [gamme.re(3), gamme.noire], + [gamme.re(3), gamme.croche], + [gamme.mi(3), gamme.croche], - [gamme.sib(3), gamme.noire], - [gamme.sib(3), gamme.noire], + [gamme.fa(3), gamme.noire], + [gamme.fa(3), gamme.noire], - [gamme.la(3), gamme.noire], - [gamme.la(3), gamme.noire], + [gamme.mi(3), gamme.noire], + [gamme.mi(3), gamme.noire], - [gamme.fa(3), gamme.croche], - [gamme.sol(3), gamme.croche], - [gamme.la(3), gamme.croche], - [gamme.fa(3), gamme.croche], + [gamme.do(3), gamme.croche], + [gamme.re(3), gamme.croche], + [gamme.mi(3), gamme.croche], + [gamme.do(3), gamme.croche], - [gamme.sol(3), gamme.noire], - [gamme.sol(3), gamme.croche], - [gamme.la(3), gamme.croche], + [gamme.re(3), gamme.noire], + [gamme.re(3), gamme.croche], + [gamme.mi(3), gamme.croche], - [gamme.sib(3), gamme.noire], - [gamme.do(4), gamme.noire], + [gamme.fa(3), gamme.noire], + [gamme.sol(3), gamme.noire], - [gamme.fa(3), gamme.blanche] + [gamme.do(3), gamme.blanche] ] ] -if args.exerciceSpectrogramme: +if args.exerciceSpectrogramme or args.transparent: g = GenerateurExercice(gamme.bpm) g.setBoomwhackers(boomwhackers) g.setLongueurPartitionColoree(6) - g.genererExerciceSpectrogramme(tabac, "exercices/ex-spec-tabac2.tex", "thème 2") + if args.exerciceSpectrogramme: + g.genererExerciceSpectrogramme(tabac, "exercices/ex-spec-tabac2.tex", "thème 3", "j'ai du bon tabac") + if args.transparent: + g.genererTransparentSpectrogramme(tabac, "exercices/ex-proj-tabac2.tex", "thème 3", "j'ai du bon tabac") else: print "Génération du son" s = BasicSequenceur(1, gamme.bpm, 0) -- GitLab