Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pilotage MIDI #5

Closed
jpcima opened this issue Sep 30, 2018 · 30 comments
Closed

Pilotage MIDI #5

jpcima opened this issue Sep 30, 2018 · 30 comments
Labels
demande de fonctionnalité Nouvelle fonctionnalité demandée

Comments

@jpcima
Copy link
Member

jpcima commented Sep 30, 2018

@trebmuh À détailler.

développer une entrée MIDI et une contrôlabilité MIDI pour pouvoir automatiser tout ça, voire jouer avec les potards d'une BCF 2000 ce qui améliorerait probablement l'ergonomie du logiciel. Ne pas oublier d'y adjoindre une fonctionnalité de MIDI-learn.

@trebmuh
Copy link
Member

trebmuh commented Sep 30, 2018

L'idée ici est de pouvoir assigner les contrôles du logiciel à des potentiomètres et des chariots sur des surfaces de contrôle MIDI, histoire de faciliter son utilisation car il est plus facile/marrant de tourner un potard que d'appuyer sur les touches du clavier alpha-numérique.

@trebmuh trebmuh added the demande de fonctionnalité Nouvelle fonctionnalité demandée label Oct 1, 2018
@jpcima
Copy link
Member Author

jpcima commented Oct 5, 2018

Ici je pense que l'apprentissage MIDI sera important, puisque selon moi il va falloir être en mesure de pouvoir créer une association entre un contrôle MIDI avec un nuage particulier.

Les associations doivent pouvoir être exprimées en Control-Change, voire en NRPN.
Quant aux notes et aux pitchbend je ne sais pas si on peut en faire quelque chose, alors si vous avez des idées..

@trebmuh
Copy link
Member

trebmuh commented Oct 5, 2018

il va falloir être en mesure de pouvoir créer une association entre un contrôle MIDI avec un nuage particulier.

"un nuage particulier" et/ou un "un échantillon" (un rectangle)

@olof29
Copy link
Collaborator

olof29 commented Oct 11, 2018

si on veut associer un controleur midi à chaque grain, on va tres vite saturer en terme de possibilités.
ce serait deja un bon debut de pouvoir piloter les parametres des clouds en midi.
j'ai vérifié, la fonction midi présente dans Frontieres.cpp fonctionne. il est donc possible d'implementer des actions dedans. il nous faudrait definir exactement ce qu'on veut faire :
on a acces à des messages note-on et note-off, avec en prime bien sur le numero de note et le numero de canal, mais aussi à des control change avec numero de controle, numero de canal, et valeur.
on peut donc facilement dupliquer le code qui est appelé à l'appui d'une touche clavier, ou mieux, creer une methode appelée dans les deux cas, ce qui permetytrait aussi de les appeler depuis une fenetre graphique de Qt, par exemple, affichable pour le cloud selectionné

@trebmuh
Copy link
Member

trebmuh commented Oct 11, 2018

si on veut associer un controleur midi à chaque grain, on va tres vite saturer en terme de possibilités.
ce serait deja un bon debut de pouvoir piloter les parametres des clouds en midi.

Je ne crois pas, ça dépend de l'utilisation d'un utilisateur. J'imagine qu'il suffirait probablement d'implémenter l'apprentissage MIDI et de ne pas coder en dur "qui fait quoi" dans le logiciel pour laisser chaque utilisateur définir ce qu'il veut contrôler et avec quel contrôle.

Si toi tu as envie de bosser sur un sujet qui t'intéresse particulièrement comme de contrôler les nuages en MIDI, vasy, c'est super. Mon conseil est d'essayer pour toi de penser à coder en pensant un peu plus loin (comme ce que j'ai abordé dans les messages précédents).

@olof29
Copy link
Collaborator

olof29 commented Oct 11, 2018

du coup ça demanderait de gerer un parametrage des affectations des signaux midi, qui serait peut etre à integrer dans un fichier, peut etre un fichier de sauvegarde d'un projet (voir l'issue au sujet de la sauvegarde des projets).
je vais garder ça à l'esprit dans mes essais.
ça ressemble assez à une base de donnees, ça, non ?

@olof29
Copy link
Collaborator

olof29 commented Oct 21, 2018

bon, il s'agit ici de bien définir toutes les idées qui nous viennent à l'esprit de type de pilotages midi pour voir si la maniere dont on developpera celui ci permettra de repondre à toutes ces envies.
je vais donc enumerer celles qui me sont dejà venues à l'esprit.

  • creer un expandeur midi granulaire.
    pour cela, chaque note midi doit etre affectee à un cloud. un signall midi all note off arrete tous les clouds. un note on fait passer actif un cloud, la velocite regle le niveau sonore, un note off fait passer inactif le cloud. les canaux midi peuveut aussi donner des series de clouds differents. exemple : 16 sons differents sur 88 touches d'un clavier affectees aux clouds 1 à 88, 89 à 176 ... le parametrage midi decidant de quelles etendues de notes affeter à quelles etendues de clouds, permettant d'affecter la velocité à un parametre de cloud, et de la façon dont celle ci influe sur le parametre (dans cet exemple, echeloner les valeurs de velocités sur l'echelle des volumes.
  • pouvoir piloter, quelque soit le nombre de clouds, chacun d'entre eux en deplacements, et pour tous ses parametres. cela veut donc dire aussi emettre les signaux midi parametres de maniere à pouvoir "rejouer" une oeuvre.
  • pouvoir affecter un controleur globalement au meme paramatre de tous les clouds (exemple, deplacer tous les clouds de haut en bas. l'ampleur du deplacement doit etre alors parametrable).
  • pouvoir affecter un controleur globalement au meme paramatre d'une serie de clouds (exemple deplacer verticalement les clouds de 1 à 88 de mon expandeur cité plus haut à l'utilisation d'un controleur)
  • pouvoir globalement pitcher des series de clouds grace à la molette de pitch de mon clavier midi.
  • pouvoir utiliser ma surface de controle midi pour controler à la main mes clouds. pouvoir donc choisir à quoi affecter le signal de tel ou tel bouton ou fader de mon controleur. mais du coup aussi pouvoir parametrer la façon dont celui ci influe sur le parametre du cloud (exemple affecter un fader au deplacement vertical d'un cloud, pouvoir regler l'echelle de deplacement selon les valeurs reçues)
  • chaque parametrage midi doit pouvoir etre enregistre en tant qu'"instrument midi", voir en tant que programm midi. du coup pouvoir affecter un program change midi au chargement d'un instrument, ou d'une scene, ou des deux.

bon, dejà avec ça y'a de quoi se prendre pas mal la tete. n'hesitez pas à enumerer vos envies possibles aussi.
quoiqu'il en soit, se dessine deja une reflexion à avoir sur la façon dont on peut traduire une valeur envoyée par un element midi quelqu'il soit (souvent entre 0 et 127) et la valeur d'un parametre de cloud ou d'echantillon, qui elle peut avoir des façons de varier totalement differentes selon le parametre

@jpcima
Copy link
Member Author

jpcima commented Oct 21, 2018

quoiqu'il en soit, se dessine deja une reflexion à avoir sur la façon dont on peut traduire une valeur envoyée par un element midi quelqu'il soit (souvent entre 0 et 127) et la valeur d'un parametre de cloud ou d'echantillon, qui elle peut avoir des façons de varier totalement differentes selon le parametre

A mon avis le plus simple est de normaliser toute valeur en domaine 0-1 et appliquer une courbe de contrôle. La courbe se définit en points de contrôle (x,y) et pour le besoin de la synthèse on conserve dans un tableau la version interpolée.

@olof29
Copy link
Collaborator

olof29 commented Oct 21, 2018

ravi de voir ma suggestion comprise, mais malheureusement, moi je ne comprends pas la solution :)

@olof29
Copy link
Collaborator

olof29 commented Oct 22, 2018

dans l'optique d'un expandeur midi, une autre fonctionnalité me plairait enormement.

  • pouvoir appliquer aux clouds déclenchés par des midi note on une enveloppe ADSR

@olof29
Copy link
Collaborator

olof29 commented Oct 31, 2018

pour pouvoir faire de Frontieres un expandeur midi, il serait simple de rajouter 2 parametres aux clouds :

  • canal midi
  • numero de note midi

ainsi, on peut tres simplement :

  • activer un cloud par un signal midi "note on"
  • desactiver un cloud par un signal midi "note off"

@olof29
Copy link
Collaborator

olof29 commented Nov 18, 2018

fonction de base midi proposée avec note on, note off, qui activent / desactivent des clouds.
cela est un progres, mais me semble insuffisant :

  • il serait meilleur de pouvoir considérer chaque cloud comme un son de base, déclinable sur une plage de notes midis (exemple, du C2 au B2, on joue ce cloud sur le canal midi 3.
  • dans ce cas, il faut pouvoir définir pour un cloud une note de base du cloud (son accord), et transposer celui ci selon la note demandée.
  • mais cela me pose un sérieux problème au niveau de la commande du son des clouds., en effet, je cherche un moyen simple au niveau de la scene, par exemple, de pouvoir rendre un cloud polyphonique, c'est à dire déclenchable simultanement plusieurs fois, avec des pitchs differents.(et aussi d'autres parametres, d'ailleurs, de maniere à utiliser l'after touch clavier different sur chaque note par exemple)
  • je songe pour cela à creer une nouvelle classe dans la scene, une classe "note" qui serait une copie momentanée d'un cloud, crée au depart midi d'une note, et effacé à la fin de son release. Mais je me demande si la démarche est viable en terme de performances, si la copie du cloud ne va pas prendre un temps trop important qui induirait une espece de latence ? peut faut il tout bonnement tester...

@olof29
Copy link
Collaborator

olof29 commented Nov 18, 2018

dans l'optique de la creation de cette nouvelle classe, voici verbalisées quelques idées à son propos :

  • nom de la classe : son, ou combinaison, ou performance (j'ai une petite preference pour combinaison, qui ne porterait à aucune confusion)
  • définition : ensemble de clouds bornés par tranches de notes midi (exemple : de c2 à e2, tel cloud, de d2 à d3, tel cloud, etc)
  • utilisation : chaque canal midi a sa combinaison différente, un program change peut faire changer de cominaison sur ce canal (ce qui veut dire qu'on peut avoir un nombre de combinaisons infini par scene)
  • relations avec les clouds :
    dans une combinaison, un cloud peut etre transposé pzar rapport à sa note d'accord
    dans une combinaison, un cloud peut etre joué plus ou moins fort
    dans une combinaison, un cloud peut etre pitch selon le pitch midi
    dans une combinaison, un cloud peut etre modulé selon la modulation midi (définir comment il peut etre modulé, longueur de grain par exemple, ou/et lfo...)

@olof29
Copy link
Collaborator

olof29 commented Nov 18, 2018

voici donc ce que pourrait etre cette classe :

combinaison :

  • numéro
  • nom
  • tableau extensible contenant :
    - id de cloud
    - midi note de debut de tessiture
    - midi note de fin de tessiture
    - volume
    - effet de la modulation

instrument :

tout cela fait partie d'une scene, et peut etre mémorisé avec elle.

il faudrait peut etre aussi creer un parametre de verrouillage d'un cloud, afin que l'utilisateur puisse décider de ne pas permettre de le modifier par inadvertance lorsqu'il est utilisé dans des combinaisons (idem pour la position et la forme des samples)

@olof29
Copy link
Collaborator

olof29 commented Nov 18, 2018

il y a des bugs dans l'implementation midi qui etait fournie à la base dans borderlands :

  • j'ai du echanger les code de note on et note off qui etaient inversés
  • le canal midi est toujours à 0 tel qu'il est detecté

@olof29
Copy link
Collaborator

olof29 commented Nov 18, 2018

bon, le canal midi n'est pas à 0 en fait, il est au numero de canal -1, et comme j'emettais sur le canal 1, il mettait 0, il me faut donc ajouter 1 au numero de canal reçu

@jpcima
Copy link
Member Author

jpcima commented Nov 18, 2018

j'ai du echanger les code de note on et note off qui etaient inversés

Oui je confirme que les indications en commentaire sont erronnées.

bon, le canal midi n'est pas à 0 en fait, il est au numero de canal -1, et comme j'emettais sur le canal 1, il mettait 0, il me faut donc ajouter 1 au numero de canal reçu

Dans les messages midi, le canal est une valeur sur 4 bits, soit valuée de 0 à 15.
Les interfaces graphiques, les documentations adressées aux utilisateurs, etc. désignent ces mêmes canaux dans le domaine 1-16.

Cela explique le décalage de 1, mais le calcul est juste.
En programmation il est sage de conserver l'indiçage à 0, ce qui évite des erreurs de code un peu bêtes. (dès qu'il est question d'indicer un tableau, notamment)

@olof29
Copy link
Collaborator

olof29 commented Nov 18, 2018

oui, c'est ce que j'ai fait pour cette meme raison.

maintenant , je me penche sur la question des combinaisons.
pour cela, je patauge un petit peu :

  • je veux faire une copie provisoire d'un cloud à chaque declenchement d'une note midi le concernant.
  • je veux detruire ce cloud provisoire à la fin de son release.
  • je suis donc en train de chercher comment faire cette copie rapidement, mais ce n'est pas simple. j'ai le sentiment que je devrais utiliser un constructeur de copie, mais c'est une nouveauté complete pour moi...
  • est ce la bonne voie ? ou dois je chercher ailleurs ?

@jpcima
Copy link
Member Author

jpcima commented Nov 18, 2018

J'ai pas du tout réfléchi à la question pour l'instant, mais je me suis noté de faire ça un peu plus tard.
N'est-ce pas possible de faire ça sans dupliquer les nuages ?
Ne peut-on pas avoir des grains accordés sur différent tons ?

@jpcima
Copy link
Member Author

jpcima commented Nov 18, 2018

constructeur de copie

Ce serait une éventualité, mais sous contrainte de temps réel cela rajoute de la complication, car on n'a pas le droits aux malloc/new, toute mémoire se réserve à l'avance.
C'est pas impossible mais on peut accepter une version provisoire qui fait les allocs mémoire, on verrait ensuite.

@olof29
Copy link
Collaborator

olof29 commented Nov 18, 2018

J'ai pas du tout réfléchi à la question pour l'instant, mais je me suis noté de faire ça un peu plus tard.

j'ai noté la strucutre que je pense utiliser quelques messages au dessus

N'est-ce pas possible de faire ça sans dupliquer les nuages ?

difficilement, à mon avis, si on veut un synthetiseur reellement polyphonique sur chaque cloud :
il faut pouvoir simultanement jouer le meme cloud à des pitchs différents

Ne peut-on pas avoir des grains accordés sur différent tons ?

les grains ne sont à mon avis que des constituantes du son qu'on peut comparer à des harmoniques de celui ci, ils peuvent donc tout à fait etre accordés différemment de l'accord principal du cloud.
selon moi, c'est à l'utilisateur de dire quelle est la note principale, quiite à ce que plus tard on lui fournisse des outils de détection de celle ci, mais en tout etat de cause, en raccordant la sortie à un simple accordeur, il devrait pouvoir le savoir.
ensuite, selon la note midi voulue, le cloud copié sera repitché en comparaison avec la note principale

tout ça, je sais faire. seule la question de faire une copie sans creer une latence m'inquiète, mais sinon, je ne vois pas du tout comment rendre un cloud polyphonique avec différents pitchs.

@jpcima
Copy link
Member Author

jpcima commented Nov 18, 2018

Ok j'aime bien l'idée. Tout de même, je pense qu'il serait bien que Cloud reste ce qu'il est.

Je verrais éventuellement un fractionnement de l'entité nuage, avec une relation 1→N avec une multitude de "variantes tonales de nuage". Le N peut être borné par un maximum tel que 32, comme une polyphonie de synthétiseur.

Je pense que l'interface graphique doit continuer à manipuler des instances de Nuage, en ajout/suppression, ce qui occupe le verrou de scène et donc constitue une opération pouvant occasionner une période d'arrêt.

Au contraire, les N "voix" (si on peut maintenant se permettre de réutiliser ce terme) pourraient être réservées en mémoire à l'avance, et seul le fil audio se permettrait de les manipuler. Cette opération serait compatible avec le temps réel.


J'en profite pour glisser un lien vers une structure de donnée que j'ai réalisée très récemment pour un synthé TR : https://github.com/jpcima/libADLMIDI/tree/std-structures/src/structures
Il s'agit d'une liste chaînée qui réserve un espace borné réutilisable de N cellules, utile en ce genre de situation.

@olof29
Copy link
Collaborator

olof29 commented Nov 18, 2018

Ok j'aime bien l'idée. Tout de même, je pense qu'il serait bien que Cloud reste ce qu'il est.

ça, dans mon idée, c'est le cas, et on peut tres bien melanger les deux façons de faire du son en continuant à travailler en temps réel sur les clouds, même si un musicien autre est en train de jouer en pilotage midi.

Je verrais éventuellement un fractionnement de l'entité nuage, avec une relation 1→N avec une multitude de "variantes tonales de nuage". Le N peut être borné par un maximum tel que 32, comme une polyphonie de synthétiseur.

c'est ce que je ne vois comment realiser, c'est pour ça que je me suis tourné vers la logique de copie temporaire du cloud.

Je pense que l'interface graphique doit continuer à manipuler des instances de Nuage, en ajout/suppression, ce qui occupe le verrou de scène et donc constitue une opération pouvant occasionner une période d'arrêt.

c'est quoi, ce verrou de scene dont tu parles ?

Au contraire, les N "voix" (si on peut maintenant se permettre de réutiliser ce terme) pourraient être réservées en mémoire à l'avance, et seul le fil audio se permettrait de les manipuler. Cette opération serait compatible avec le temps réel.

meme commentaire que ci dessus, ça je ne sais pas comment le gerer

J'en profite pour glisser un lien vers une structure de donnée que j'ai réalisée très récemment pour un synthé TR : https://github.com/jpcima/libADLMIDI/tree/std-structures/src/structures
Il s'agit d'une liste chaînée qui réserve un espace borné réutilisable de N cellules, utile en ce genre de situation.

je vais jeter un oeil voir si j'y comprends quelque chose.

@jpcima
Copy link
Member Author

jpcima commented Nov 18, 2018

C'est pas évident et ça demande de s'y pencher plus en détail, raison pour laquelle je ne sais trop te donner une réponse précise pour le moment.

C'est ça le verrou de scène: extern std::mutex currentSceneMutex;
L'interface graphique occupe ce verrou durant l'ajout/suppression sur l'ensemble de nuages, et pendant ce court moment, c'est un signal à zéro qui sera produit sur la sortie sonore.

@olof29
Copy link
Collaborator

olof29 commented Nov 18, 2018

pourtant, la suppression d'un cloud ne me semble pas creer d'interruption du rendu sonore des autres clouds actifs. ou c'est si court que je ne le décele pas, et s'il y a trop de destructions dues à une polyphonie comme je la pense, ça pourrait devenir audible ?

@jpcima
Copy link
Member Author

jpcima commented Nov 18, 2018

J'ai fait que la prise du verrou soit réalisée sur la période la plus courte possible, donc il se peut que la discontinuité ne se produise que très rarement. Il n'empêche qu'elle est possible.

@olof29
Copy link
Collaborator

olof29 commented Nov 18, 2018

bon, si je résume :

  • la logique de combinaisons est correcte, et toute la structure qui va avec
  • c'est la façon de faire passer aux clouds la production polyphonique qui est le noeud du probleme.

donc, je pense que, vu que mes capacités sont loin d'atteindre les tiennes, je peux me pencher sur la partie structure de cominaisons, son implementation et les fenêtres permettant de gérer tout ça, et te laisser pour plus tard voir le lien avec les clouds.
au pire, je peux, une fois fait cela, voir ce que donne la version avec copie pour verifier si ça génère effectivement des arrets en faisant des copies completes de clouds.

@jpcima
Copy link
Member Author

jpcima commented Nov 18, 2018

simple remarque : il s'agira de xrun en ce cas, et non simplement de discontinuité sonore.

jpcima pushed a commit that referenced this issue Nov 22, 2018
maj depuis master officiel
@olof29
Copy link
Collaborator

olof29 commented Nov 23, 2018

je suis en train de réfléchir à la question de la polyphonie de nouveau.
la notion de voix qui serait réservées en mémoire à l'avance commence à se dessiner dans mon esprit.

  • je me demande même si la réservation mémoire à l'avance est nécessaire. ne pourrait on les créer et les détruires à la volée ?
  • les parametres qui appartiennent aux voix seraient la note, qui crée un décalage par rapport au pitch en comparant la note midi du cloud, mais aussi leur propre envelope, puisque 2 notes différentes du meme cloud peuvent etre présentes au meme moment, mais à des avancements differents de l'envelope, puisqu'ayant ete declenchées à des moments différents, et leur vélocité propre.

@olof29
Copy link
Collaborator

olof29 commented Dec 2, 2018

j'ai déposé un nouveau PR sur la gestion de la polyphonie midi

je reprends ici les explications mises dans le PR, et clos "polyphonie midi, probleme de comprehention dans la gestion des envelopes #59 " qui fait double emploi avec ici.

cette branche est assez conséquente :

  • nouvelle classe instrument (MidiInstrum) :
    16 canaux midi avec chacun sa combinaison (ou rien)
  • nouvelle classe cominaison (MidiCombi) :
    128 notes midi avec pour chacune des couches contenant un Id de cloud, une velocité minimum , une velocité maximum
  • nouvelle classe banque (MidiBank) :
    128 combinaisons
  • nouvelle fenetre banque (BankDialog) :
    permet de gérer les combinaisons (copie/paste/delete par menu contextuel, double clic pour éditer la combinaison, ou la sélectionner si on vient de la fenetre instrument)
  • nouvelle fenetre instrument (InstrumDialog) :
    pertmet d'affecter une combinaison à chaque canal midi (double clic pour aller selectionner)
  • nouvelle fenetre combinaison (CombiDialog) :
    permet de creer les couches de Clouds qui seront joués en midi selon les vélocités et les notes dempandées.
    mode opératoire : on sélectionne dans le tableau de droite les Clouds qu'on veut affecter, on décide de la plage de notes midi, et des velocités mini et maxi, et on les ajoute (idem pour les retirer) à la combinaison.
    l'arboresscence des couches est visualisée dans le tableau de gauche
  • nouvelle classe CloudMidi dans Cloud :
    contient sa note midi, son pitch, sa velocité, ses buffers de jeu, son envelope, et son tableau de grains
    le Cloud contient un tableau de 32 pointeurs vers des CloudMidis, qui sont créés dans le constructeur de Cloud, et détruits dans son destructeur.
    les constructeurs et destructeurs de CloudMidi gèrent les creations et destructions de leurs contenus, buffers, tableaux de grains, etc
  • nouvelle fonction setActivateMidiState dans Cloud, qui gère le tableau de MidiClouds selon les appels midi.
  • ajout d'une boucle de jeu des midiClouds dans nextBuffer du Cloud, similaire à ce qui est fait pour le cloud lui meme, mais avec les parametres des midiclouds. (elle existe en parallele de la gestion habituelle du cloud, et les deux peuvent etre joués en simultanés sans souci, un cloud pouvant etre activé et manipulé par l'interface, et en meme temps joué en midi à des pitchs différents.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
demande de fonctionnalité Nouvelle fonctionnalité demandée
Projects
None yet
Development

No branches or pull requests

3 participants