Partage
  • Partager sur Facebook
  • Partager sur Twitter

[Clavier] Différencier un ou plusieurs appuis

Sujet résolu
    22 octobre 2018 à 12:36:04

    Bonjour à tous, 
    Actuellement j'essai de créer un logiciel de musique qui ressemble à un piano amélioré sur ordinateur en java avec une interface graphique.
    On considérera qu'un son corresponds à un son classique comme FA, DO etc 
    FONCTIONNALITÉS:

    - J'appuie sur une touche du clavier, un son est lu. (Fait)
    - Les touches du clavier (26 touches) peuvent être modifiées pour réaliser une autre action. (Par exemple A qui exécute l'action 1 peut être modifier en B qui exécute l'action 1) (Fait)
    - Les touches sont enregistrées dans un fichier JSON (Fait)
    - Les sons joués peuvent être modifié en fonction de la touche appuyée. (Par exemple Action 1 joue le son 1 peut être modifier en Action 2 joue le son 1) (Pas fait)
    - Les sons peuvent être stoppés lorsqu'on relâche la touche et continue en boucle si on ne la relâche pas. (Par exemple, j'appuie sur A, sa joue le son 1 ET en même temps j'appuie sur B sa joue le son 2, je relâche A le son s’arrête mais pas B qui continue en boucle) <- C'est ICI que je bloque


    INFORMATIONS UTILES
    - On utilisera Applet pour lire un son ainsi que la classes contenant ces fonctions (cela marche parfaitement)
    Code: 
    import java.applet.Applet;
    import java.applet.AudioClip;
    import java.io.IOException;
    import java.net.URL;
    
    import javax.sound.sampled.AudioFormat;
    import javax.sound.sampled.AudioInputStream;
    import javax.sound.sampled.AudioSystem;
    import javax.sound.sampled.UnsupportedAudioFileException;
    
    
    class Son {
    		
    	private URL url;
    	private AudioClip ac;
    
        public void jouer(String name) {
        	url = getClass().getResource(name);
        	ac = Applet.newAudioClip(url);
        	ac.play(); // Lis le son puis s'arrete
        }
        public void jouerEnBoucle(String name) {
        	url = getClass().getResource(name);
        	ac = Applet.newAudioClip(url);
        	ac.loop(); // Lis le son en boucle jusqu'a l'appelle de la fonction suivante
    
        }
        public void arreter() {
        	ac.stop(); // Stop le son immédiatement
        }
        
        public double duree(String name) throws UnsupportedAudioFileException, IOException { // Fonction créer à part qui renvoie la durée du son EN SECONDE
        	url = getClass().getResource(name);
        	
        	AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(url);
        	AudioFormat format = audioInputStream.getFormat();
        	long frames = audioInputStream.getFrameLength();
        	double duration = (frames+0.0) / format.getFrameRate();
        	
        	return duration;
        }
    
    }
    - La fonction getWhen() (Utiliser dans le KeyListener via e.getWhen()) renvoie le temps lorsqu'on appuie sur la touche depuis 1970 en Millisecondes
    PROBLEME:
    Essaie n°1:
    Utilisation du KeyListener. 
    Je créer un bouton qui permet de dire au logiciel que maintenant lorsque j'appuie sur une touche cela récupére l'action et joue le son correspondant. Si le son est déjà en cours, le processus se met en pause. Code:
     
    				long time = 0;
    				boolean enCours = false;
    				if (!enCours) {
    					System.out.println("here");
    					enCours = true;
    					time = e.getWhen();
    					son.jouer("/son2.wav");
    					try {
    						Thread.sleep((long) (son.duree("/son2.wav")*1000));
    					} catch (InterruptedException | UnsupportedAudioFileException | IOException e1) {
    						// TODO Bloc catch généré automatiquement
    						e1.printStackTrace();
    					}
    					enCours = false;
    				}
    Problème que soulève cette technique:
    - Le KeyListener stocke les événement créer au clavier (même quand le processus s'arrete) puis les renvois (Une sorte de mémoire tampon)
    Comment le résoudre ?
    Essaie n°2:
    Utilisation du KeyListener.
    Même principe que l'autre mais je créer une boucle qui ajoute le temps pour un meilleur timing. Code:
    				try {
    					for (int i = 0; i < son.duree("/capture.wav"); i++ ) {
    						TimeUnit.SECONDS.sleep(1);
    						do {
    							x++;
    							timeBeforeGetTouche = e.getWhen();
    							son.jouer("/capture.wav");
    							System.out.println(x);
    							
    						} while(timeBeforeGetTouche + i > time); 
    					}
    				} catch (UnsupportedAudioFileException | IOException | InterruptedException e1) {
    					// TODO Bloc catch généré automatiquement
    					e1.printStackTrace();
    				}
    Problème: Cela ne marche pas je comprends pas trop pourquoi
    Essaie n°3: 
    Utilisation de l'ActionListener du bouton (On fait correspondre une touche du clavier avec un bouton et quand on appuie sur la touche, le bouton est enclenché) Ne fonctionne pas car l'ActionListener contient qu'une unique fonction pour récupérer les événements (ActionPerformed). Du coup, autant utiliser le MouseListener qui lui contient lui plus de fonction pratique. Cela fonctionne très bien, mais on ne peut pas cliquer sur le bouton avec le clavier vu que c'est une action sourie et non une action souris sur un bouton. Cependant, autant déplacer la souris pour cliquer dessus.
    Code du MouseListener: 
    		b.addMouseListener(new MouseListener() {
    
    			@Override
    			public void mouseClicked(MouseEvent arg0) {
    				// TODO Stub de la méthode généré automatiquement
    				//son.jouer("/son2.wav");
    				son.jouer("/argent.wav");
    			}
    
    			@Override
    			public void mouseEntered(MouseEvent arg0) {
    				// TODO Stub de la méthode généré automatiquement
    				
    			}
    
    			@Override
    			public void mouseExited(MouseEvent arg0) {
    				// TODO Stub de la méthode généré automatiquement
    				
    			}
    
    			@Override
    			public void mousePressed(MouseEvent arg0) {
    				// TODO Stub de la méthode généré automatiquement
    				//son.jouerEnBoucle("/argent.wav");
    			}
    
    			@Override
    			public void mouseReleased(MouseEvent arg0) {
    				// TODO Stub de la méthode généré automatiquement
    				son.arreter();
    				
    			}
    			
    		});
    Code pour déplacer la souris: 
    		b.addKeyListener(new KeyAdapter() {
    			public void keyPressed(KeyEvent e)
                {
    				
                    System.out.println("oui");
                   ro.mouseMove(10, 160);
                   ro.mousePress(InputEvent.BUTTON1_MASK);
                   
                }
    			public void keyReleased(KeyEvent e)
    	            {
    				System.out.println("non"); 
    				ro.mouseRelease(InputEvent.BUTTON1_MASK);
    	            }
    			
    			
    		});
    Cela fonction, c'est vrai, mais bon, c'est vraiment pas optimal, on ne peut lire qu'un son, bref, c'est nul. Et encore, cela peut planter si on surcharge le bouton (comme avec une macro)
    Voila, j'ai essayé aussi d'autres trucs, mais rien de convainquant c'est pourquoi je viens vers vous aujourd’hui. J’espère avoir était assez clair dans mes explications. Si il faut changé de bibliothèque de son, pas de problème si l'on m'explique vite fait comment faire marché le truc. Je ne vous joins pas tout le code car il y a au total pas loin de 600 lignes répartie dans différentes classes et je pense pas que c'est bien utile.
    Dans l'attente d'une réponse, merci d'avance à vous. 
    Ps: Désolé pour les fautes d'orthographe. 

    -
    Edité par Gunteam_ 22 octobre 2018 à 15:03:56

    • Partager sur Facebook
    • Partager sur Twitter

    [Clavier] Différencier un ou plusieurs appuis

    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
    × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
    • Editeur
    • Markdown