Salut, je voudrais faire un programme qui redirige la sortie standard de la carte son vers un ficiher.
Un peu come sous unix, on peut creer des pipes qui dedoublent la sortie du clavier je pense que cela est aussi possible en java.
Si quelqu'un a une idée, s'il vout plait veuillez m'en parler.
Meme si c'est possible en C dite le moi je pourrait toujours faire une JNI après.
mhh je n'ai jamais fait ça
mais un flux entrant dans un fichier devrait convenir non ?
tu reçoit ton flux de ta carte son que tu envois directement dans un fichier
Avec l'api joal(binding java pour openAl) on utilise un ByteBuffer (nio) pour stocker le fichier audio à utiliser sous forme numérique, après il est tout à fait possible de le sérialiser, ou de l'enregistrer en byte[] dans un File.
Si ça t'intéresse, tu trouveras des exemples sur le site de joal.
Avec l'api joal(binding java pour openAl) on utilise un ByteBuffer (nio) pour stocker le fichier audio à utiliser sous forme numérique, après il est tout à fait possible de le sérialiser, ou de l'enregistrer en byte[] dans un File.
Si ça t'intéresse, tu trouveras des exemples sur le site de joal.
Oh que wi c'a m'interresse , peut me m'en dire un peu plus sur OpenAl , et comment l'utiliser (les bases koi ...)
Mais quand meme ne serait-il pas faisable avec java.sound.*
Merci .
Avec l'API java sound, il se trouve que l'interface SourceDataLine qui permet l'écriture sur la carte son (= sortie dans les enceintes) est compparable à un flux ordinaire. Sachant que cette interface contient une méthode write(byte[] buffer, int offset, int length), tu peux en profiter pour, en même temps que tu écris dans le flux de la carte son, écrire en parralèle dans un flux de fichier...
Par contre je vois pas comment faire si tu utilises Clip...
Petit exemple à la rache, j'ai pas compilé pour tester et c'est pas très clean, notamment au niveau du traitement des exceptions :
import javax.sound.*;
import java.io.*;
public class Test {
public static void main (String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
AudioFormat fmt = new AudioFormat(44100, 16, 2, true, false);
DataLine.Info info = new DataLine.Info(SourceDataLine.class, fmt, (int)(44100 * 4 * 0.1));
final SourceDataLine line = (SourceDataLine)AudioSystem.getLine(info);
line.open();
final outputStream out2 = new BufferedOutputStream(new FileOutputStream("testaudio.raw"));
Runnable r = new Runnable(){ public void run() {
try {
line.start();
byte[] buf = new byte[4096];
while (!Thread.currentThread().isInterrupted()) {
// ON génère du bruit aléatoire ... pas très intéressant mais c'est pour l'exemple
for (int i=0; i < buf.length; i++) {
double d = (Math.random() *2) -1;
short sample = (short)Math.round(32768 * d);
buf[i++] = (byte)(sample&0xFF);
buf[i] = (byte)(sample>>8);
}
// ON écrit le bruit généré dans le flux de la carte son
line.write(buf, 0, buf.length);
// ET en parralèle on l'écrit aussi dans le fichier
out2.write(buf, 0, buf.length);
}
line.stop();
} catch (Exception e) { e.printStackTrace(); }
}};
Thread t = new Thread(r);
t.start();
System.out.println("Appuyez sur entrée pour arrêter");
br.readLine();
t.interrupt();
line.close();
br.close();
out2.flush();
out2.close();
System.exit(0);
}}
P.S. NE laisse pas tourner le programme trop longtemps, la taille du fichier généré augmente de 176 Ko/s (données audio brut non compressées en qualité CD)
par contre =/ si le sons ne viens pas du programme java à la base ça marche pas
mais je pense qu'il y'a même des sécurité pour t'empêcher d'enregistrer le sons sortant =/
enfin du moins sous vista on t'empêche de le faire via windobe =/
maintenant :/ si un programme peut le faire ... ça pourrait être bien
Ah si tu veux capturer tout ce qui sort de tes enceintes, c'est pas du Java.
Sous windows XP, faire les opérations suivantes :
1. Ouvrir le contrôle du volume
1a. Soit depuis le menu contextuel de l'icône du volume dans la barre des tâches
1b. Soit dans le menu démarrer : programmes > accessoires > multimédia > contrôle du volume
1c. Soit par la boîte exécuter : sndvol32
2. Aller dans le menu Options et cliquer propriétés
3. Cocher ajuster pour enregistrement et faire OK
4. Cocher la case en bas dans la colonne "ce que vous entendez" ou "stereo mix" ou "mono mix" ou "mixer" (les désignations changent selon la carte son)
A partir de maintenant, tu peux aller dans n'importe quel logiciel d'édition audio, par exemple le magnétophone. Tu n'enregistreras plus l'entrée micro mais tous les sons qui passent par tes hauts-parleurs.
En java, en utilisant une TargetDataLine pour lire des données depuis la carte son, ça ferait pareil que le magnétophone.
Malheureusement, le paramétrage dans le contrôle du volume ne peut pas se faire programmatiquement en Java, enfin je ne crois pas. Je ne suis même pas sûr que ce soit possible en C/C++.
N'oublie pas de recocher "microphone" pour de nouveau enregistrer normalement depuis le micro comme d'habitude.
Je sais pas si on peut toujours faire ça sous vista, probablement que le contrôle du volume n'a pas beaucoup changé (je ne peux pas vérifier; je n'ai pas vista)
Merci pour vos reponse, M'enfin je voudrais justement une solution portable et c'est pour cela que j'ai pensé au java. Quentin concerant ton code, je ne veux pas ecrire ce que je lit, je veux juste ecrire ce qui est lue par n'importe quel autre programme.
du moment ou il sort par la carte son, il doit bien y avoir une code qui le fait.
Merci encore pour es reponse !!!
Merci pour vos reponse, M'enfin je voudrais justement une solution portable et c'est pour cela que j'ai pensé au java. Quentin concerant ton code, je ne
veux pas ecrire ce que je lit, je veux juste ecrire ce qui est lue par n'importe quel autre programme.
du moment ou il sort par la carte son, il doit bien y avoir une code qui le fait.
DAns ce cas regarde ma deuxième réponse. Il n'y a malheureusement, du moins à ma connaissance, aucun moyen de faire ça automatiquement. En Java encore moins qu'en C/C++ ou autre langage compilé directement en binaire.
Cela dit, je n'ai jamais encore compris à quoi servait l'interface Port. Peut-être que la solution s'y cache.
EDIT : Dans le mille ! Il faudrait que je regarde plus attentivement la doc mais il semblerait que j'aie accès directement depuis Java à une grande partie des contrôles présents dans le contrôle du volume. Je vois déjà plus ou moins comment changer le volume principal des haut-parleurs par exemple.
Je me rends compte que personne n'est interressé.
De mon coté je comprend la classe Port qui peut lier a un "TargetDataline" le SPEAKER, le MICROPHONE, ...
Mais je bloque sur le passage de l'objet port au DataLine.
voila mon code
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.sound.sampled.*;
import javax.sound.sampled.DataLine.Info;
public class AudioRecorder02 extends JFrame{
AudioFormat audioFormat;
TargetDataLine targetDataLine;
final JButton captureBtn =
new JButton("Capture");
final JButton stopBtn = new JButton("Stop");
final JPanel btnPanel = new JPanel();
final ButtonGroup btnGroup = new ButtonGroup();
final JRadioButton aifcBtn =
new JRadioButton("AIFC");
final JRadioButton aiffBtn =
new JRadioButton("AIFF");
final JRadioButton auBtn =//selected at startup
new JRadioButton("AU",true);
final JRadioButton sndBtn =
new JRadioButton("SND");
final JRadioButton waveBtn =
new JRadioButton("WAVE");
public static void main( String args[]){
new AudioRecorder02();
}//end main
public AudioRecorder02(){//constructor
captureBtn.setEnabled(true);
stopBtn.setEnabled(false);
//Register anonymous listeners
captureBtn.addActionListener(
new ActionListener(){
public void actionPerformed(
ActionEvent e){
captureBtn.setEnabled(false);
stopBtn.setEnabled(true);
//Capture input data from the
// microphone until the Stop button is
// clicked.
captureAudio();
}//end actionPerformed
}//end ActionListener
);//end addActionListener()
stopBtn.addActionListener(
new ActionListener(){
public void actionPerformed(
ActionEvent e){
captureBtn.setEnabled(true);
stopBtn.setEnabled(false);
//Terminate the capturing of input data
// from the microphone.
targetDataLine.stop();
targetDataLine.close();
}//end actionPerformed
}//end ActionListener
);//end addActionListener()
//Put the buttons in the JFrame
getContentPane().add(captureBtn);
getContentPane().add(stopBtn);
//Include the radio buttons in a group
btnGroup.add(aifcBtn);
btnGroup.add(aiffBtn);
btnGroup.add(auBtn);
btnGroup.add(sndBtn);
btnGroup.add(waveBtn);
//Add the radio buttons to the JPanel
btnPanel.add(aifcBtn);
btnPanel.add(aiffBtn);
btnPanel.add(auBtn);
btnPanel.add(sndBtn);
btnPanel.add(waveBtn);
//Put the JPanel in the JFrame
getContentPane().add(btnPanel);
//Finish the GUI and make visible
getContentPane().setLayout(new FlowLayout());
setTitle("Exemple de Recorder");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(300,120);
setVisible(true);
}//end constructor
//This method captures audio input from a
// microphone and saves it in an audio file.
private void captureAudio(){
try{
//Get things set up for capture
audioFormat = getAudioFormat();
DataLine.Info dataLineInfo = new DataLine.Info(
TargetDataLine.class,
audioFormat);
// c'est ici que je dois changer la cible de lecture par la sortie carte son.
targetDataLine = (TargetDataLine)
AudioSystem.getLine(dataLineInfo);
//Create a thread to capture the microphone
// data into an audio file and start the
// thread running. It will run until the
// Stop button is clicked. This method
// will return after starting the thread.
new CaptureThread().start();
}catch (Exception e) {
e.printStackTrace();
System.exit(0);
}//end catch
}//end captureAudio method
//This method creates and returns an
// AudioFormat object for a given set of format
// parameters. If these parameters don't work
// well for you, try some of the other
// allowable parameter values, which are shown
// in comments following the declarations.
private AudioFormat getAudioFormat(){
float sampleRate = 8000.0F;
//8000,11025,16000,22050,44100
int sampleSizeInBits = 16;
//8,16
int channels = 1;
//1,2
boolean signed = true;
//true,false
boolean bigEndian = false;
//true,false
return new AudioFormat(sampleRate,
sampleSizeInBits,
channels,
signed,
bigEndian);
}//end getAudioFormat
//=============================================//
//Inner class to capture data from microphone
// and write it to an output audio file.
class CaptureThread extends Thread{
public void run(){
AudioFileFormat.Type fileType = null;
File audioFile = null;
//Set the file type and the file extension
// based on the selected radio button.
if(aifcBtn.isSelected()){
fileType = AudioFileFormat.Type.AIFC;
audioFile = new File("junk.aifc");
}else if(aiffBtn.isSelected()){
fileType = AudioFileFormat.Type.AIFF;
audioFile = new File("junk.aif");
}else if(auBtn.isSelected()){
fileType = AudioFileFormat.Type.AU;
audioFile = new File("junk.au");
}else if(sndBtn.isSelected()){
fileType = AudioFileFormat.Type.SND;
audioFile = new File("junk.snd");
}else if(waveBtn.isSelected()){
fileType = AudioFileFormat.Type.WAVE;
audioFile = new File("junk.wav");
}//end if
try{
targetDataLine.open(audioFormat);
targetDataLine.start();
AudioSystem.write(
new AudioInputStream(targetDataLine),
fileType,
audioFile);
}catch (Exception e){
e.printStackTrace();
}//end catch
}//end run
}//end inner class CaptureThread
//=============================================//
}//end outer class AudioRecorder02.java
En fait j'ai entrevu que c'était possible en faisant tourner le petit programme de test ci-dessous. IL affiche les différents ports disponibles et la liste des contrôles supportés. Ensuite, en théorie, il suffirait de changer les valeurs des paramètres qui nous intéressent...
import javax.sound.sampled.*;
import java.io.*;
import java.util.*;
public class Test644 {
public static void main (String[] args) throws Exception {
Port.Info infos[] = {
Port.Info.MICROPHONE,
Port.Info.LINE_IN,
Port.Info.LINE_OUT,
Port.Info.COMPACT_DISC,
Port.Info.HEADPHONE,
Port.Info.SPEAKER
};
for (Port.Info pi : infos) {
Port p = null;
try {
p = (Port)AudioSystem.getLine(pi);
} catch (Exception e) {}
System.out.printf("%s : %s%n", pi, (p==null? "not supported" : (p.isOpen()? "opened" : "closed")));
if (p!=null) {
System.out.printf("Class %s%n%s, data line %s, source data line %s, target dta line %s%n", p.getClass().getName(), (pi.isSource()? "Source port" : "Target port"), p instanceof DataLine, p instanceof SourceDataLine, p instanceof TargetDataLine);
boolean mustClose = false;
if (!p.isOpen()) { p.open(); mustClose=true; }
Control[] ctrls = p.getControls();
listControls(ctrls);
if (mustClose) p.close();
}
System.out.println("");
}
Mixer.Info[] infos2 = AudioSystem.getMixerInfo();
System.out.println("List of mixers : ");
for (Mixer.Info m : infos2) {
System.out.println(m);
}
}
private static void listControls (Control[] ctrls) throws Exception {
for (Control c : ctrls) {
System.out.println(c);
if (c instanceof CompoundControl) {
Control[] cs = ((CompoundControl)c).getMemberControls();
listControls(cs);
}}
}
}
J'obtiens la sortie suivante chez moi pour un de mes PC équipé de windows XP. En comparant avec ce que le contrôle du volume de XP propose en natif, on s'aperçoit qu'on peut enregistrer depuis java la sortie CD audio ou le modem en mettant le contrôle correspondant à true, mais pas la carte-son. Pourtant dans le contrôle du volume je peux. Tu auras peut-être plus de chance chez toi.
MICROPHONE source port : closed
Class com.sun.media.sound.PortMixer$PortMixerPort
Source port, data line false, source data line false, target dta line false
Microphone Control containing Select, and Volume Controls.
Select Control with current value: true
Volume with current value: 1.0 (range: 0.0 - 1.0)
LINE_IN source port : closed
Class com.sun.media.sound.PortMixer$PortMixerPort
Source port, data line false, source data line false, target dta line false
Entrée ligne Control containing Select, Volume, and Balance Controls.
Select Control with current value: false
Volume with current value: 1.0 (range: 0.0 - 1.0)
Balance with current value: 0.0 (range: -1.0 - 1.0)
LINE_OUT target port : not supported
COMPACT_DISC source port : closed
Class com.sun.media.sound.PortMixer$PortMixerPort
Source port, data line false, source data line false, target dta line false
CD audio Control containing Select, Volume, and Balance Controls.
Select Control with current value: false
Volume with current value: 0.2 (range: 0.0 - 1.0)
Balance with current value: -1.4901161E-8 (range: -1.0 - 1.0)
HEADPHONE target port : not supported
SPEAKER target port : closed
Class com.sun.media.sound.PortMixer$PortMixerPort
Target port, data line false, source data line false, target dta line false
Volume with current value: 0.2220035 (range: 0.0 - 1.0)
Balance with current value: 2.2257003E-8 (range: -1.0 - 1.0)
Mute Control with current value: false
Sons wave Control containing Volume, Balance, and Mute Controls.
Volume with current value: 0.8 (range: 0.0 - 1.0)
Balance with current value: -1.4901161E-8 (range: -1.0 - 1.0)
Mute Control with current value: false
Synthé. SW Control containing Volume, Balance, and Mute Controls.
Volume with current value: 0.4509804 (range: 0.0 - 1.0)
Balance with current value: -6.4787655E-9 (range: -1.0 - 1.0)
Mute Control with current value: false
Mono Control containing Volume, and Mute Controls.
Volume with current value: 0.50118256 (range: 0.0 - 1.0)
Mute Control with current value: false
Haut-parleur du PC Control containing Volume, and Mute Controls.
Volume with current value: 0.6 (range: 0.0 - 1.0)
Mute Control with current value: false
CD audio Control containing Volume, Balance, and Mute Controls.
Volume with current value: 0.09373617 (range: 0.0 - 1.0)
Balance with current value: -2.2510624E-9 (range: -1.0 - 1.0)
Mute Control with current value: false
Entrée ligne Control containing Volume, Balance, and Mute Controls.
Volume with current value: 1.0 (range: 0.0 - 1.0)
Balance with current value: 0.0 (range: -1.0 - 1.0)
Mute Control with current value: false
Microphone Control containing +20dB Gain, Volume, and Mute Controls.
+20dB Gain Control with current value: true
Volume with current value: 1.0 (range: 0.0 - 1.0)
Mute Control with current value: true
Ligne téléphonique Control containing Volume, and Mute Controls.
Volume with current value: 1.0 (range: 0.0 - 1.0)
Mute Control with current value: false
MICROPHONE source port : closed
Class com.sun.media.sound.PortMixer$PortMixerPort
Source port, data line false, source data line false, target dta line false
Microphone Control containing Select, Ampli microphone, and Volume Controls.
Select Control with current value: false
Ampli microphone Control with current value: false
Volume with current value: 0.5976501 (range: 0.0 - 1.0)
LINE_IN source port : closed
Class com.sun.media.sound.PortMixer$PortMixerPort
Source port, data line false, source data line false, target dta line false
Entrée ligne Control containing Select, Volume, and Balance Controls.
Select Control with current value: false
Volume with current value: 0.0 (range: 0.0 - 1.0)
Balance with current value: 0.0 (range: -1.0 - 1.0)
LINE_OUT target port : not supported
COMPACT_DISC source port : not supported
HEADPHONE target port : not supported
SPEAKER target port : closed
Class com.sun.media.sound.PortMixer$PortMixerPort
Target port, data line false, source data line false, target dta line false
Volume with current value: 1.0 (range: 0.0 - 1.0)
Balance with current value: 0.0 (range: -1.0 - 1.0)
Mute Control with current value: false
HP du PC muet Control with current value: false
Interface SPDIF Control with current value: true
Sons wave Control containing Volume, Balance, and Mute Controls.
Volume with current value: 0.5000076 (range: 0.0 - 1.0)
Balance with current value: 2.3283064E-10 (range: -1.0 - 1.0)
Mute Control with current value: false
Synthé. SW Control containing Volume, Balance, and Mute Controls.
Volume with current value: 0.36307317 (range: 0.0 - 1.0)
Balance with current value: -8.7450545E-9 (range: -1.0 - 1.0)
Mute Control with current value: false
Lecteur CD Control containing Volume, Balance, and Mute Controls.
Volume with current value: 1.0 (range: 0.0 - 1.0)
Balance with current value: 0.0 (range: -1.0 - 1.0)
Mute Control with current value: false
Haut-parleur du PC Control containing Volume, and Mute Controls.
Volume with current value: 0.50118256 (range: 0.0 - 1.0)
Mute Control with current value: false
List of mixers :
Périphérique audio principal, version Unknown Version
SigmaTel Audio, version Unknown Version
Pilote de capture audio principal, version Unknown Version
SigmaTel Audio, version Unknown Version
Java Sound Audio Engine, version 1.0
Port SigmaTel Audio, version 5.10
Mais ça ne m'aide pas trop pour lire a partir de la carte son. d'après ce que je comprend je dois lire sur le Port.LINE_OUT or il n'est pas supporté .
Est ce que je me trompe ou comment y parvenir ? je m'interroge.
Normalement dans le contrôle du volume, pour sélectionner la source du microphone, il faut cocher la case select en bas de la sortie dhoisie. En Java, je pense que ça doit être pareil. Normalement c'est microphone qui est coché par défaut, et chez toi la sortie de la carte son est symbolisée par SPDIFIn. Donc.... tu peux pas non plus.
Concernant line out en fait théoriquement il s'agit d'un port exactement inverse au line in. J'ai jamais vu aucun PC en avoir un...
j'ai encore pensé a quelque chose, est il possible de diriger la sortie son, vers l'entrée son et ensuite d'enregistrer l'entrée comme s'il s'agissait d'un microphone ?
Non, je ne pense pas qu'on puisse faire un truc aussi tordu. Le plus compliqué étant de redireger la sortie vers l'entrée... si la carte son ne le permet pas, il n'y a plus que le double-jack.
C'est un câble avec une prise jack mâle à chaque bout. Ca permet de connecter la sortie casque d'un périphérique avec l'entrée microphone d'un autre périphérique. Ce câble a normalement un autre nom, mais je ne le connais pas.
Je parlais un peu de ça en déconnant, parce que ce n'est pas une vraie solution : étant donné que l'audio circulent en analogique dans un câble jack, la perte de qualité est notoire (on joue un peu au pingouin manchot : numérique->analogique->numérique). Parfois on ne peut pas faire autrement ... Ca sert par exemple pour numériser ses vieilles K7.
ça ne resoud toujours pas mon probleme.
moi je ne veut pas que la personne ait un micro, ou un double jack, seule sa carte son et il peut enregistrer ce qu'il suit
ON en revient au point de départ : il faut qu'il coche lui-même l'option adéquate dans le contrôle du volume. Java n'y donne pas accès, donc... on ne peut pas faire autrement.
redirection de sortie
× 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.