Comment jouer un son sinusoidale fait en fichier java

  • Réponses :0
Lobna Hamdi
  • Posts de Forum 1

7 mai 2016 à 16:06:58 via site

Salut j'ai une une petite problème au niveau de mon projet. En fait j'ai réalisé un fichier java qui fonctionne correctement en émettant le son voulu mais lorsque je réalise un projet android contenant uniquement ce fichier , le son ne marche pas lors de la mise de cette application sur l'appareil . pouvez vous m'expliquer?
Voici le code :public class SonSimple {
/**
* Joue un son sinusoïdal de fréquence et de durée donnés sur une ligne audio.
* @param freq est la fréquence du son en Hertz
* @param duree est la durée du son en millisecondes
* @param line est la ligne audio sur laquelle le son doit être joué
*/
public static void jouer(double freq, long duree, SourceDataLine line) {
// Format de son utilisé par la ligne
AudioFormat fmt = line.getFormat();
// On récupère la fréquence d'échantillonnage de la ligne
float sampleRate = fmt.getSampleRate();
// ainsi que la taille du tampon utilisé par cette ligne
int bufsize = line.getBufferSize();
// la taille des échantillons
int sampleSize = fmt.getSampleSizeInBits();
int nbOctets = 0; // nombre d'octets par échantillon
int maxVal = 0; // valeur maximal d'un échantillon
if (sampleSize == 8) {
nbOctets = 1; // 8 bits => 1 octet, max = 127
maxVal = 0x7F;
} else if (sampleSize == 16) {
nbOctets = 2; // 16 bits => 2 octets, max = 32767
maxVal = 0x7FFF;
} else {
throw new Error("# Nombre de bits par échantillon non supporté : " + sampleSize);
}
// Ordre des octets dans un échantillon
boolean bigEndian = fmt.isBigEndian();
// Le nombre d'échantillons à générer est le produit de la durée
// en secondes par la fréquence d'échantillonnage en Hertz
int nbEchantillons = (int)Math.ceil((double)duree / 1000 * sampleRate);
// On alloue un tableau d'octets de la taille du tampon de la ligne
byte audiosamples[] = new byte[bufsize];
int i = 0;
while (i < nbEchantillons) {
// on génère les échantillons et on les transmet à la ligne tampon
// par tampon, ce qui est plus efficace.
int j = 0;
while ((j < bufsize) && (i < nbEchantillons)) {
// sample donne la valeur de l'échantillon en double avec amplitude
// -1,0/1.0, on la multiplie par maxVal pour obtenir la valeur pour la ligne
int val = (int)(maxVal * sample(i++, freq, sampleRate));
if (nbOctets == 1) {
// Un seul octet : il suffit de le mettre dans le tableau
audiosamples[j++] = (byte)val;
} else if (bigEndian) {
// deux octets en big endian : on met l'octet de poids fort en premier
audiosamples[j++] = (byte)((val & 0xFF00) >> 8);
audiosamples[j++] = (byte)(val & 0x00FF);
} else {
// deux octets en little endian : on met l'octet de poids faible en premier
audiosamples[j++] = (byte)(val & 0x00FF);
audiosamples[j++] = (byte)((val & 0xFF00) >> 8);
}
}
// on transmet le tampon à la ligne
line.write(audiosamples, 0, j);
}
}

/**
* Calcule un échantillon d'un signal sinusoïdal.
* @param i est l'indice de l'échantillon (débute à 0)
* @param freq est la fréquence du signal en Hertz
* @param rate est la fréquence d'échantillonnage en Hertz
* @return la valeur de l'échantillon, comprise en -1.0 et 1.0
*/
public static double sample(int i, double freq, double rate) {
// On ramène d'abord le temps dans la période [0, 1/freq[
double t = Math.IEEEremainder(i/rate, 1/freq);
// IEEEremainder nous ramène dans [-1/2freq, 1/2freq[, donc
// on ajoute 1/freq pour être dans [0, 1/freq[
if (t < 0) {
t += 1 / freq;
}
// f(t) = sin(wt) = sin(2*pi*freq*t)
return Math.sin(2 * Math.PI * freq * t);
}

public static void main(String args[]) {
final float sampleRate = 20500; // fréquence d'échantillonnage
final int sampleSize = 8; // nombre de bits par échantillon : ici un octet
final boolean bigEndian = true; // ordre des octets dans l'échantillon (si sampleSize = 16)
final boolean signed = true; // les échantillons sont signés (valeurs de -128 à 127)
// Ces paramètres définissent un format audio échantillonné
AudioFormat audiofmt = new AudioFormat(sampleRate, sampleSize, 1, signed, bigEndian);
// On va maintenant chercher une ligne audio qui supporte ce format
// Une SourceDataLine est une ligne audio qui produit du son. C'est une source pour
// le système audio, même si du point de vue de notre programme, c'est plutôt un puits.
SourceDataLine line = null;
try {
line = AudioSystem.getSourceDataLine(audiofmt);
line.open(audiofmt); // on ouvre la ligne pour pouvoir y écrire des échantillons
} catch (LineUnavailableException lue) {
System.out.println("# Erreur : impossible de trouver une ligne de sortie audio au format :");
System.out.println("# " + audiofmt);
System.exit(1);
}

line.start();  // on active la ligne afin qu'elle transforme les échantillons en son 
jouer(440.0, 800, line);  // jouer un la pendant 2 secondes 

// On attend que la ligne ait fini de jouer les échantillons 
line.drain(); 
// Il faut faire un exit car le système audio crée un thread qui ne termine pas tout seul. 
System.exit(0); 

}
}

Répondre