Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 9 sur 9
  1. #1
    Membre habitué Avatar de anadoncamille
    Inscrit en
    juillet 2007
    Messages
    222
    Détails du profil
    Informations forums :
    Inscription : juillet 2007
    Messages : 222
    Points : 118
    Points
    118

    Par défaut Java Sound Audio Engine

    Bonjour,

    j'ai développé un moteur stéréo de son basé sur un Mixer capable de produire des Line que l'on peut contrôler en temps réel pour faire de la stéréo dynamique.

    Jusqu'à la version jvm1.6.0_31, je détecte systématiquement un mixer logiciel nommé : Java Sound Audio Engine

    Je le détecte en forçant les mixers détectés à produire des Line et en vérifiant avec isControlSupported qu'elles supportent MUTE, PAN et GAIN.

    Mais à partir de la jvm1.6.0_32, je ne détecte plus de Mixer valable.

    Y a-t-il une autre méthode permettant de faire de la stéréo temps réel ou un autre Mixer ou système de son nouveau qui remplace l'ancien qui fonctionne parfaitement jusqu'à la jvm1.6.0_31 ?

    Que faire ?
    __________________________________
    | +
    | Sylvain Tournois - Création logicielle.
    |
    | http://www.anadoncamille.com/
    |

  2. #2
    Modérateur
    Avatar de wax78
    Homme Profil pro Renaud Warnotte
    Développeur informatique
    Inscrit en
    août 2006
    Messages
    2 579
    Détails du profil
    Informations personnelles :
    Nom : Homme Renaud Warnotte
    Âge : 33
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : août 2006
    Messages : 2 579
    Points : 4 380
    Points
    4 380

    Par défaut

    Tu as un petit bout de code qui montre la liste des "mixer" à testé ?

    (par contre produire des Line j'avoue ne pas comprendre le sens)

  3. #3
    Membre habitué Avatar de anadoncamille
    Inscrit en
    juillet 2007
    Messages
    222
    Détails du profil
    Informations forums :
    Inscription : juillet 2007
    Messages : 222
    Points : 118
    Points
    118

    Par défaut code détection mixers

    Bonjour,

    voici le code que j'utilise pour faire la détection de mixer :

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
     
      public static boolean STEREO = true;
     
      public static Mixer getOutMixer() {
        try {
          AudioInputStream stream = AudioSystem.getAudioInputStream(new File("ok.wav"));
          AudioFormat format = stream.getFormat();
          DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
          Mixer.Info[] mixers = AudioSystem.getMixerInfo();
          long date = System.currentTimeMillis();
          while ((System.currentTimeMillis() - date < 1000) || (STEREO)) {
            for (int i = 0 ; i < mixers.length ; i++) {
              Mixer mixer = AudioSystem.getMixer(mixers[i]);
              Line.Info[] infos = mixer.getSourceLineInfo();
              if (infos.length > 0)  {
                try {
                  SourceDataLine line = (SourceDataLine)mixer.getLine(info);
                  boolean mc = line.isControlSupported(BooleanControl.Type.MUTE);
                  boolean gc = line.isControlSupported(FloatControl.Type.MASTER_GAIN);
                  boolean pc = line.isControlSupported(FloatControl.Type.PAN);
                  if (STEREO) {
                    if (mc && gc && pc) {
                      System.out.println("Mixer detected (stereo) : " + mixers[i].getName());
                      return mixer;
                    }
                  }
                  else {
                    System.out.println("Mixer detected (mono) : " + mixers[i].getName());
                    return mixer;
                  }
                }
                catch (Exception e) {
                }
              }
            }
            STEREO = false;
          }
        }
        catch (Exception e) {
          System.err.println("ERREUR : Détection de mixer audio");
        }
        System.out.println("No correct mixer available.");
        return null;
      }
     
    }
    La variable statique STEREO me sert à ajuster la machine audio.

    Si la varable STEREO est vraie, les sons produits peuvent être travaillés en stéréo. C'est un travail souvent lié au jeu vidéo. Si un monstre grogne à droite du joueur, on l'entend à droite. S'il sifflote à gauche, on l'entend à gauche dans les hauts parleurs. Le volume (GAIN) permet de produire un effet de distance. J'utilise des Line et précisemment des SourceDataLine pour produire ces effets, en combinaison avec des objets qui font la stéréo automatiquement en fonction de leur position relative au joueur.

    Quand la détection de mixer ne trouve aucun mixer capable de produire la stéréo, elle passe STEREO à false et trouve rapidement un mixer. Mais il est impossible avec mon code de produire de la stéréo à ce moment-là. Je ne sais pas comment faire.

    L'ancienne détection de mixer était une simple boucle de passage sur mixer.getName() et je testais qu'il y avait "java" dans son nom. J'obtenais très simplement le mixer stéréo nommé "Java Sound Audio Engine".

    Depuis la jvm1.6.0_32, je ne détecte plus ce mixer. Qu'est-il devenu ? A-t-il été remplacé et si oui, par quoi ?
    __________________________________
    | +
    | Sylvain Tournois - Création logicielle.
    |
    | http://www.anadoncamille.com/
    |

  4. #4
    Modérateur
    Avatar de wax78
    Homme Profil pro Renaud Warnotte
    Développeur informatique
    Inscrit en
    août 2006
    Messages
    2 579
    Détails du profil
    Informations personnelles :
    Nom : Homme Renaud Warnotte
    Âge : 33
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : août 2006
    Messages : 2 579
    Points : 4 380
    Points
    4 380

    Par défaut

    Je ne sais pas pour le Java Sound engine... il a peut être disparu. Chez moi si je liste tout les mixer j'ai ceci :

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    M=Périphérique audio principal, version Unknown Version
    M=Haut-parleurs (Realtek High Definition Audio), version Unknown Version
    M=Pilote de capture audio principal, version Unknown Version
    M=Microphone (Webcam Pro 9000), version Unknown Version
    M=Entrée ligne (Realtek High Defi, version Unknown Version
    M=Port Haut-parleurs (Realtek High Def, version 6.1
    M=Port Entrée ligne (Realtek High Defi, version 6.1
    M=Port Microphone (Webcam Pro 9000), version 0.9
    Les 2 premiers étant ceux à utiliser pour faire sortir du son.

    Il y a Plusieurs choses que je ne comprends pas dans ton code, que je vais te demander afin de bien comprendre et trouver une solution éventuelle

    1) La variable STEREO semble fixée dés le départ et jamais changée. Je ne comprends pas l'intérêt immédiat (sauf si un autre truc manipule cette variable?).

    2) Tu as une exception catchée qui ne fait rien. Il faut toujours s'en occuper pour bien faire. (mais la n'est pas ton problème primaire).

    3) La boucle while, a quoi sert cette bricole ?

    Code :
    while ((System.currentTimeMillis() - date < 1000) || (STEREO))
    4)
    Code :
    boolean pc = line.isControlSupported(FloatControl.Type.PAN);
    J'imagine que ceci te permets par la suite de savoir si la line permet de faire un PAN et donc peut etre serait stéréo.

    La variable "channels" de AudioFormat ne pourrait pas faire l'affaire ? Si elle vaut 2 alors c'est stéréo, enfin j'imagine...

    Enfin quoiqu'il en soit, ne cherche pas apres "java sound" faut trouver un autre moyen d'obtenir un mixer qui te convienne a mon avis.

  5. #5
    Membre habitué Avatar de anadoncamille
    Inscrit en
    juillet 2007
    Messages
    222
    Détails du profil
    Informations forums :
    Inscription : juillet 2007
    Messages : 222
    Points : 118
    Points
    118

    Par défaut re

    pour répondre dans l'ordre :

    Je détecte sensiblement la même liste de mixers après la jvm1.6.0_31 et quand je ne trouve pas le mixer Java, je détecte habituellement le périphérique audio principal, que j'utilise pour l'instant en mono.

    1) La variable STEREO est disponible pour les autres objets de la machine son que j'ai codée. Elle sert de contrôle sur les sons produits. J'ai une méthode play(String monSon, boolean stéréo) qui construit un gestionnaire de son actif le temps que dure le son. Pendant son activité, on peut paramétrer en temps réel les contrôles MUTE, PAN et GAIN pour produire des effets stéréo. Mais si la variable STEREO globale est fausse, tous les sons sortiront en mono même si le boolean local sereo est vrai.
    Lors de la détection des mixers, la première passe de boucle vérifie la disponibilité des controles stéréo. Si elle ne trouve aucun mixer qui réponde au besoin, elle passe la variable STEREO à false et refait une passe de test en mono, ce qui détecte habituellement le premier mixer disponible.

    2) L'exception non catchée m'évite simplement les surcharges de textes dans le prompt, sachant que la méthode de détection est basée sur une fonctionnalité complète qui ne lève aucune Exception. Si un mixer déclenche une exception à cause des services demandés, il est rejeté et cela peut se faire sans remplir le prompteur de fautes volontaires. La deuxième exception, par contre, se contente de signaler un abus d'exceptions dans la détection, cas où aucun mixer ne serait disponible.

    3) La boucle while est bel et bien une bricole qui date d'il y a longtemps et que je vais certainement enlever. Elle permet de forcer la détection pendant une seconde maximum, même si les passes de détection précédentes n'ont rien donné. Au bout d'une seconde, la détection de mixers est abandonnée si aucun n'a été trouvé. Je pense que je vais me contenter des passes stéréo et mono et stopper la détection immédiatement après.

    4) Oui le boolean pc détecte la possibilité de faire la stéréo et la détection du nombre de chanels sur la ligne permet certainement de faire les calculs pour la stéréo. Je testerai ton idée, mais j'avoue que penser qu'il faudrait recoder à la main un mixer qui fasse la stéréo en temps réel alors qu'elle était déjà fonctionnelle avant la jvm1.6.0_32 est assez frustrant. Pour le moment j'imagine que Sun a déplacé la fonctionnalité ailleurs mais je ne trouve pas où. J'ai retesté la JavaSoundDemo mais la stéréo est inactive.
    __________________________________
    | +
    | Sylvain Tournois - Création logicielle.
    |
    | http://www.anadoncamille.com/
    |

  6. #6
    Membre habitué Avatar de anadoncamille
    Inscrit en
    juillet 2007
    Messages
    222
    Détails du profil
    Informations forums :
    Inscription : juillet 2007
    Messages : 222
    Points : 118
    Points
    118

    Par défaut autres test

    J'ai testé d'autres paramètres et d'autres méthodes, mais je ne trouve plus aucun mixer avec lequel je puisse implémenter de la stéréo dynamique

    Est-il possible d'obtenir des contrôles de Line comme le Java Mixer l'autorisait (PAN et GAIN) ?

    Autrement, comment programmer de la stéréo temps réel ?
    __________________________________
    | +
    | Sylvain Tournois - Création logicielle.
    |
    | http://www.anadoncamille.com/
    |

  7. #7
    Modérateur
    Avatar de wax78
    Homme Profil pro Renaud Warnotte
    Développeur informatique
    Inscrit en
    août 2006
    Messages
    2 579
    Détails du profil
    Informations personnelles :
    Nom : Homme Renaud Warnotte
    Âge : 33
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : août 2006
    Messages : 2 579
    Points : 4 380
    Points
    4 380

    Par défaut

    Citation Envoyé par anadoncamille Voir le message
    Autrement, comment programmer de la stéréo temps réel ?
    Personnelement j'ai dut louper une étape quelques part ou je ne comprends pas ce que veux dire stéréo temps réel (et pourtant des soft de musique j'en ai codé quelques un en java...)

    Mis a part cela, je me suis dit que j'allais essayer de lire un fichier WAV stereo et de contrôler le PAN afin de verifier que je puisse regler le pan et entendre soit la gauche, soit la droite (ou les 2, ou entres les 2).

    J'ai donc écrit ceci en me basant d'un exemple d'internet :

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    import java.io.File;
    import java.io.IOException;
     
     
     
    import javax.sound.sampled.AudioFormat;
    import javax.sound.sampled.AudioInputStream;
    import javax.sound.sampled.AudioSystem;
    import javax.sound.sampled.DataLine;
    import javax.sound.sampled.FloatControl;
    import javax.sound.sampled.LineUnavailableException;
    import javax.sound.sampled.SourceDataLine;
    import javax.sound.sampled.FloatControl.Type;
     
    public class MakeSound {
     
        private final int BUFFER_SIZE = 128000;
        private File soundFile;
        private AudioInputStream audioStream;
        private AudioFormat audioFormat;
        private  SourceDataLine sourceLine;
     
        public static void main(String args[])
        {
        	MakeSound ms = new MakeSound();
        	ms.playSound("");
        }
        /**
         * 
         * @param filename the name of the file that is going to be played
         *
         */
        public void playSound(String filename){
     
            String strFilename = "M1F1-int16-AFsp.wav";
     
            try {
            	soundFile = new File(strFilename);
     
            } catch (Exception e) {
                e.printStackTrace();
                System.exit(1);
            }
     
            try {
            	audioStream = AudioSystem.getAudioInputStream(soundFile);
            } catch (Exception e){
                e.printStackTrace();
               System.exit(1);
            }
     
     
     
            audioFormat = audioStream.getFormat();
     
            DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
            try {
            	sourceLine = (SourceDataLine) AudioSystem.getLine(info);
            	sourceLine.open(audioFormat);
     
            } catch (LineUnavailableException e) {
                e.printStackTrace();
                System.exit(1);
            } catch (Exception e) {
                e.printStackTrace();
                System.exit(1);
            }
     
            FloatControl pan = (FloatControl) sourceLine.getControl(FloatControl.Type.PAN);
            pan.setValue(-1.f);
     
            sourceLine.start();
     
            boolean isPan = sourceLine.isControlSupported(Type.PAN);
            System.err.println("Pan : "+isPan);       
     
            int nBytesRead = 0;
            byte[] abData = new byte[BUFFER_SIZE];
            while (nBytesRead != -1) {
                try {
                    nBytesRead = audioStream.read(abData, 0, abData.length);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (nBytesRead >= 0) {
                    @SuppressWarnings("unused")
                    int nBytesWritten = sourceLine.write(abData, 0, nBytesRead);
                }
            }
     
            sourceLine.drain();
            sourceLine.close();
     
        }
    }
    Cela lis un fichier en prenant le mixer par défaut (celui qui est censé bien allé sous windows).

    Dans un premier temps j'ai controler avec un ficheir WAV stéréo afin de contrôler que sa sortait bien en stereo. (franchement des mixer mono ca doit plus exister depuis des lustres).

    Ensuite j'ai rajouter de quoi modifier le PAN et constater que celui ci fonctionnait.

    Je ne sais pas si ca va t'aider mais essayons toujours

  8. #8
    Membre habitué Avatar de anadoncamille
    Inscrit en
    juillet 2007
    Messages
    222
    Détails du profil
    Informations forums :
    Inscription : juillet 2007
    Messages : 222
    Points : 118
    Points
    118

    Par défaut merci

    Merci pour ton aide, je vais de ce pas à la maison pour tester tout ça.

    Ce que je veux dire par stéréo temps réel, c'est un effet stéréo indépendant du son joué et de ses propres pistes audio. C'est surtout utile dans le jeu vidéo pour ajouter des effets de profondeur sonore et des effets de mouvement.

    Il me tarde de tester ton code, là je suis au cyber et les souvenirs que j'ai de mes essais proches de ton code, c'est que je n'ai pas de controle dispo, quand je fais getControl, ça me renvoie null. Mais je pense que j'ai fait une erreur que l'ancien mixer supportait. Il me tarde d'essayer.
    __________________________________
    | +
    | Sylvain Tournois - Création logicielle.
    |
    | http://www.anadoncamille.com/
    |

  9. #9
    Membre habitué Avatar de anadoncamille
    Inscrit en
    juillet 2007
    Messages
    222
    Détails du profil
    Informations forums :
    Inscription : juillet 2007
    Messages : 222
    Points : 118
    Points
    118

    Par défaut nouvel essai

    j'ai essayé ton code sur mon ordi mais j'ai obtenu une exception :
    Code :
    1
    2
    3
    4
    Exception in thread "main" java.lang.IllegalArgumentException: Unsupported control type: Pan
            at com.sun.media.sound.AbstractLine.getControl(Unknown Source)
            at MakeSound.playSound(MakeSound.java:68)
            at MakeSound.main(MakeSound.java:28)
    déclenchée par :
    Code :
    FloatControl pan = (FloatControl) sourceLine.getControl(FloatControl.Type.PAN);
    J'ai corrigé mon code de détection de mixer, mais je n'obtiens un mixer stéréo qu'avec l'ancienne jvm. J'ai essayé avec des sons mono pour voir si je pouvais obtenir un mixer me permettant au moins de déplacer un son mono du haut parleur de droite à celui de gauche mais aucun résultat non plus.

    Voici le nouveau code de détection :
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
     
     
      public static Mixer getOutMixer() {
        System.out.println("jvm " + System.getProperty("java.version"));
        boolean STEREO = true;
        try {
    //      AudioInputStream stream = AudioSystem.getAudioInputStream(new File("ok.wav"));
    //      AudioFormat format = stream.getFormat();
          AudioFormat format = new AudioFormat(44000, 16, 1, true, true);
          DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
          Mixer.Info[] mixers = AudioSystem.getMixerInfo();
          long date = System.currentTimeMillis();
          boolean done = false;
          while (!done) {
            for (int i = 0 ; i < mixers.length ; i++) {
              Mixer mixer = AudioSystem.getMixer(mixers[i]);
              Line.Info[] infos = mixer.getSourceLineInfo();
              if (infos.length > 0)  {
                try {
                  SourceDataLine line = (SourceDataLine)mixer.getLine(info);
                  line.open();
                  boolean mc = line.isControlSupported(BooleanControl.Type.MUTE);
                  boolean gc = line.isControlSupported(FloatControl.Type.MASTER_GAIN);
                  boolean pc = line.isControlSupported(FloatControl.Type.PAN);
                  if (STEREO) {
                    if (mc && gc && pc) {
                      line.close();
                      System.out.println("Mixer detected (stereo) : " + mixers[i].getName());
                      return mixer;
                    }
                  }
                  else {
                    line.close();
                    System.out.println("Mixer detected (mono) : " + mixers[i].getName());
                    return mixer;
                  }
                  line.close();
                }
                catch (Exception e) {
                }
              }
            }
            if (!STEREO)
              done = true;
            STEREO = false;
          }
        }
        catch (Exception e) {
          System.err.println("ERREUR : Détection de mixer audio");
        }
        System.out.println("No correct mixer available.");
        return null;
      }
    Voici un lien pour télécharger la jvm 1.6.0_31 :
    http://sylv.tournois.free.fr/data/jr...ows-i586-s.exe

    Je reste surpris par ce qui ressemble à la disparition d'une facilité de programmation qui ne ressemble pas à Sun. Je pars à la quête aux infos.
    __________________________________
    | +
    | Sylvain Tournois - Création logicielle.
    |
    | http://www.anadoncamille.com/
    |

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •