Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Java Discussion :

Un générateur de sons


Sujet :

Java

  1. #1
    Membre actif
    Un générateur de sons
    Bonjour,

    je veux créer un générateur de sons pour mon jeu vidéo. Je veux que ce générateur produisent divers cris d'oiseaux et d'autres sons d'ambiance. Les générer me permettra d'économiser des ressources mémoire.

    J'ai créé une classe qui génère un ensemble de sons de façon aléatoire, la voici :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    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
    96
     
    import java.nio.*;
    import java.util.*;
    import javax.sound.sampled.*;
     
    public class Sounder implements Runnable {
     
      private static final int SAMPLE_SIZE_IN_BITS = 16;
      private static final int CHANNELS = 2;
      private static final boolean SIGNED = true;
      private static final boolean BIG_ENDIAN = true;
     
      private float SAMPLE_RATE;
      private AudioFormat AUDIO_FORMAT;
      private DataLine.Info LINE_INFO;
     
      private byte[] bytes;
      private ByteBuffer buffer;
      private short valueLeft;
      private short dValueLeft;
      private short valueRight;
      private short dValueRight;
     
      private SourceDataLine line;
     
      private Random random;
     
      public Sounder() {
        random = new Random(System.currentTimeMillis());
     
        SAMPLE_RATE = 44444;
        AUDIO_FORMAT = new AudioFormat(SAMPLE_RATE, SAMPLE_SIZE_IN_BITS, CHANNELS, SIGNED, BIG_ENDIAN);
        LINE_INFO = new DataLine.Info(SourceDataLine.class, AUDIO_FORMAT);
     
        bytes = new byte[10000];
        buffer = ByteBuffer.wrap(bytes, 0, bytes.length);
     
        valueLeft = (short)random.nextInt(1000);
        dValueLeft = (short)random.nextInt(100);
        valueRight = (short)random.nextInt(1000);
        dValueRight = (short)random.nextInt(100);
        try {
          line = (SourceDataLine)AudioSystem.getLine(LINE_INFO);
          line.open();
          line.start();
        }
        catch(Exception e) {
          e.printStackTrace();
        }
        new Thread(this).start();
      }
     
      public void next() {
        int bs = bytes.length / 2;
        int min = random.nextInt(bs / 2);
        int max = random.nextInt(bs / 2) + bs / 2;
        next(min, max);
      }
     
      public void next(int min, int max) {
        for (int i = min ; i < max; i++) {
          dValueLeft += random.nextInt(7) - 3;
          valueLeft += dValueLeft;
          if (Math.abs(valueLeft) >= 16380)
            dValueLeft = (short)-dValueLeft;
          buffer.putShort(i, valueLeft);
     
          dValueRight += random.nextInt(7) - 3;
          valueRight += dValueRight;
          if (Math.abs(valueRight) >= 16380)
            dValueRight = (short)-dValueRight;
          buffer.putShort(i + bytes.length / 2, valueRight);
        }
        line.write(bytes, 0, bytes.length);
      }
     
      public void run() {
        while (true) {
          next();
          try {
            Thread.sleep(50);
          }
          catch (Exception e) {
            e.printStackTrace();
          }
        }
      }
     
      public static void main(String[] args) {
        System.out.println("Brouillon de fond sonore.");
        System.out.println("Appuyez sur Ctrl-C pour terminer le programme.");
        for (int i = 0 ; i < 7 ; i++)
          new Sounder();
      }
     
    }


    J'utilise un codage de son linéaire PCM avec les canaux stéréo. Cependant je ne maitrise pas du tout l'aspect stéréo.
    J'ai essayé deux méthodes :
    - En supposant que le canal gauche et le canal droit sont entrelacés, j'ai codé ainsi la séquence : [gauche][droite][gauche][droite] etc...
    - En supposant que le canal gauche est avant le canal droit ou inversement, j'ai codé la séquence ainsi : [gauche][gauche]...[gauche][droite][droite]...[droite]
    Mais aucune n'a semblé fonctionner.

    Je cherche à comprendre comment encoder les données pour contrôler l'aspect stéréo du son généré.

    Comment dois-je m'y prendre ?
    __________________________________
    | +
    | Sylvain Tournois - Création logicielle
    |
    | sylv.tournois.free.fr
    |

  2. #2
    Modérateur

    Je ne comprends pas trop ta question entres nous. (EDIT : Si c'est claire en fait c'est moi qui suis un peu mal reveillé)

    Mais une chose est certaine a mon avis (mais cela ne resoudra pas ton probleme pour la cause).

    SAMPLE_RATE = 44444; -> SAMPLE_RATE = 44100;

    Je pense qu'il faut faire [gauche] [droite] [gauche] [droite] [gauche] [droite]...

    Sinon apres une recherche sur google je suis tombé sur :

    http://www.developer.com/java/other/article.php/2226701

    Ou il te donne un exemple comme tu le chercher pour le stereo. (cherche 'Creating a stereo sweep')
    (Les "ça ne marche pas", même écrits sans faute(s), vous porteront discrédit ad vitam æternam et malheur pendant 7 ans)

    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Membre actif
    vive la séréo
    Salut,

    Citation Envoyé par wax78 Voir le message

    SAMPLE_RATE = 44444; -> SAMPLE_RATE = 44100;
    Non, le problème ne vient pas de là, il n'y a pas de restriction quant à la fréquence d'échantillonage, sinon la vitesse à laquelle on peut fournir des données. 44100Hz est la valeur standard des gravures CD, qui nous permet d'éviter d'obtenir un son de trop bonne qualité, son que nous avions par la qualité analogique des cassettes et vinyles. En plus, le son numérique peut être filtré par inversion de données (équivalent d'un négatif d'image) pour obtenir un silence artificiel. Cela suppose que les normes soient respectées.
    44100Hz est la norme en vigueur pour la qualité audio, mais on peut utiliser d'autres fréquences.

    Citation Envoyé par wax78 Voir le message

    Je pense qu'il faut faire [gauche] [droite] [gauche] [droite] [gauche] [droite]...
    C'est exactement ça, les données sont entrelacées. L'erreur que j'avais faite était de fournir un mauvais index d'écriture de données. En fait j'écrivais deux octets, puis les deux suivants sur un index qui écrasait un des octets précédents.

    Voici les méthodes corrigées :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
      public void next() {
        int bs = bytes.length / 4;
        int min = random.nextInt(bs / 2);
        int max = random.nextInt(bs / 2) + bs / 2;
        next(min, max);
      }
     
      public void next(int min, int max) {
        for (int i = min ; i < max; i++) {
          dValueLeft += random.nextInt(19) - 9;
          valueLeft += dValueLeft;
          if (Math.abs(valueLeft) >= 16000)
            dValueLeft = (short)-dValueLeft;
          buffer.putShort(i * 4, valueLeft);
     
          dValueRight += random.nextInt(19) - 9;
          valueRight += dValueRight;
          if (Math.abs(valueRight) >= 16000)
            dValueRight = (short)-dValueRight;
          buffer.putShort(i * 4 + 2, valueRight);
        }
        line.write(bytes, 0, bytes.length);
      }


    Merci
    __________________________________
    | +
    | Sylvain Tournois - Création logicielle
    |
    | sylv.tournois.free.fr
    |

###raw>template_hook.ano_emploi###