[java] socket e audio capture

di il
5 risposte

[java] socket e audio capture


import javax.sound.sampled.*;
import java.io.*;
import java.net.*;

/**
 * A sample program is to demonstrate how to record sound in Java
 */
public class JavaSoundRecorder {
    // record duration, in milliseconds
    static final long RECORD_TIME = 30000;  // 30 seconds

    // format of audio file
    AudioFileFormat.Type fileType = AudioFileFormat.Type.WAVE;

    // the line from which audio data is captured
    TargetDataLine line;

    /**
     * Defines an audio format
     */
    AudioFormat getAudioFormat() {
        float sampleRate = 16000;
        int sampleSizeInBits = 8;
        int channels = 2;
        boolean signed = true;
        boolean bigEndian = true;
        AudioFormat format = new AudioFormat(sampleRate, sampleSizeInBits,
                channels, signed, bigEndian);
        return format;
    }

    /**
     * Captures the sound and record into a WAV file
     */
    void start() {
        try {
            AudioFormat format = getAudioFormat();
            DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);

            // checks if system supports the data line
            if (!AudioSystem.isLineSupported(info)) {
                System.out.println("Line not supported");
                System.exit(0);
            }
            line = (TargetDataLine) AudioSystem.getLine(info);
            line.open(format);
            line.start();   // start capturing

            System.out.println("Start capturing...");

            AudioInputStream ais = new AudioInputStream(line);

            Socket soc = new Socket("127.0.0.1" ,4444);
            DataOutputStream socOut = new DataOutputStream(soc.getOutputStream());
            if (AudioSystem.write(ais, fileType, socOut) == -1) {
                throw new IOException("Problems connecting to server");
            }

        } catch (LineUnavailableException ex) {
            ex.printStackTrace();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }

    /**
     * Closes the target data line to finish capturing and recording
     */
    void finish() {
        line.stop();
        line.close();
        System.out.println("Finished");
    }

    /**
     * Entry to run the program
     */
    public static void main(String[] args) {
        final JavaSoundRecorder recorder = new JavaSoundRecorder();

        // creates a new thread that waits for a specified
        // of time before stopping
        Thread stopper = new Thread(new Runnable() {
            public void run() {
                try {
                    Thread.sleep(RECORD_TIME);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
                recorder.finish();
            }
        });

        stopper.start();

        // start recording
        recorder.start();
    }
}
Sto provando e studiando questo codice che cattura da microfono l'audio. Dovrebbe inviare i byte audio dello stream al socket server.
Una volta compilato
javac JavaSoundRecorder.java
Eseguo
java JavaSoundRecorder
Mostra il seguente errore
java.io.IOException: stream length not specified
at java.desktop/com.sun.media.sound.WaveFileWriter.write(WaveFileWriter.java:100)
at java.desktop/javax.sound.sampled.AudioSystem.write(AudioSystem.java:1197)
at JavaSoundRecorder.start(JavaSoundRecorder.java:59)
at JavaSoundRecorder.main(JavaSoundRecorder.java:101)

prima di vedere il codice server come si specifica la lunghezza dell' AudioInputStream per non avere quell'errore?

import java.net.*;
import java.io.*;
import java.util.Arrays;
import javax.sound.sampled.*;

class datagramReceiver{
    static AudioFormat getAudioFormat() {
        float sampleRate = 16000;
        int sampleSizeInBits = 8;
        int channels = 2;
        boolean signed = true;
        boolean bigEndian = true;
        AudioFormat format = new AudioFormat(sampleRate, sampleSizeInBits,
                channels, signed, bigEndian);
        return format;
    }

    static byte[] MethodChangerBytes(byte[] incoming) {
        byte[] outgoing = new byte[incoming.length];
        for (int i = 0; i < incoming.length; i ++) {
            // Really is not important what happens here
            double Sample = (double)(short)(((incoming[i] - 128) & 0xFF) << 8);
            Sample *= 2.0;
            outgoing[i] = (byte)((((int)Sample >> 8) + 128) & 0xFF);
        }
        return outgoing;
    }

    public static void main(String[ ] args){
        // format of audio file
        File wavFile = new File("C:\\Users\\franc\\ideaProjects\\mic\\out\\production\\mic\\rec.wav");

        AudioFileFormat.Type fileType = AudioFileFormat.Type.WAVE;

        try{
            String message = "ciao mamma";
            int serverPortNumber = Integer.parseInt("4444");
            ServerSocket connectionSocket = new ServerSocket(serverPortNumber);
            Socket dataSocket = connectionSocket.accept();

            AudioFormat format = getAudioFormat();
            DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
            TargetDataLine line = (TargetDataLine) AudioSystem.getLine(info);
            AudioInputStream ais = new AudioInputStream(line);


            DataInputStream input = new DataInputStream(new BufferedInputStream(dataSocket.getInputStream()));

            AudioFormat adfmt = new AudioFormat(8000.0f, 8, 1, true , true);
            int bufferSize = (int) adfmt.getSampleRate()* adfmt.getFrameSize();
            byte[] buffer = new byte[bufferSize];
            String fileName = System.getProperty("file.separator") + "SomeFile.wav";
            File fileStreamedWav = new File((new File("")).getAbsolutePath() + fileName);
            AudioFileFormat.Type afType = AudioFileFormat.Type.WAVE;
            ByteArrayInputStream bis;
            boolean bRunningI = true;
            while (bRunningI) {
                try {
                    int read = input.read(buffer); //Socket Reading bytes
                    byte[] incomingBytes;
                    if (read > 0) {
                        incomingBytes = Arrays.copyOf(buffer, read);
                        if (incomingBytes!= null) {
                            //sdLine.write(incomingBytes, 0, incomingBytes.length);

                            //Same Size bytes, but isn't necessary submit the put Code
                            byte[] changedBytes = MethodChangerBytes(incomingBytes);
                            bis = new ByteArrayInputStream(changedBytes);
                            ais = new AudioInputStream(bis, adfmt,
                                    changedBytes.length/adfmt.getFrameSize());
                            int W = AudioSystem.write(ais, afType, fileStreamedWav);
                            System.out.println("AudioSystem.write:" + W);
                        }
                    }
                } catch (IOException e) {
                    bRunningI = false;
                }
            }
            System.out.println("sent response to client…");
            dataSocket.close( );
            connectionSocket.close( );
        }
        catch(Exception e){
            e.printStackTrace( );
        }
    }
}

5 Risposte

  • Re: [java] socket e audio capture

    zabnicola ha scritto:


    java.io.IOException: stream length not specified
    at java.desktop/com.sun.media.sound.WaveFileWriter.write(WaveFileWriter.java:100)
    Sì, lo dice chiaramente la documentazione di AudioSystem.write:

    Some file types require that the length be written into the file header; such files cannot be written from start to finish unless the length is known in advance. An attempt to write a file of such a type will fail with an IOException if the length in the audio file type is AudioSystem.NOT_SPECIFIED.

    Quindi penserei: o scegli un formato audio supportato/supportabile dalla JavaSound API che possa funzionare in streaming, oppure devi bufferizzare prima tutto in memoria/file e solo alla fine inviare su socket.

    Non saprei dire altro ora, i miei "ricordi" sulla JavaSound API purtroppo sono un po' vaghi al momento ..
  • Re: [java] socket e audio capture

    andbin ha scritto:


    Sì, lo dice chiaramente la documentazione di AudioSystem.write
    Grazie, scusami che non ho letto la documentazione. Cerco il modo di settare il formato wav che si vede negli esempi, anche se penso non sia quello.
        // format of audio file
        AudioFileFormat.Type fileType = AudioFileFormat.Type.WAVE;
        line.open(format,4096);
    
  • Re: [java] socket e audio capture

    Nessuno mi scrive, sa di cosa parlo.

    Niente non ne vengo a capo, ho provato a bufferizzare invece che trasferire tutto lo stream del microfono direttamente nel socket ma stranamente mi dà di nuovo errore della lunghezza che la vuole conosciuta a priori.
  • Re: [java] socket e audio capture

    Ho capito forse perché dell'errore cerco di spiegarlo. I file WAV vogliono per come sono fatti che nel file header dello stesso WAV sia specificata anche la lunghezza di tutto il WAV.


    Pertanto penso di procedere così, catturando i byte dal microfono e raggiunti i 100 kb creare un file1 poi altri 100 kb file2 .... E trasferire (così ho piccoli file audio WAV da 100 kb in sequenza al server di destinazione che a sua volta li salva in locale e inizia in automatico a fare partire la playlist. In questo modo ottengo il RealTime da microfono al server.

    Vi faccio sapere se funziona
  • Re: [java] socket e audio capture

    Funziona, appena posso posto il codice se qualcuno è interessato.


    Ora il problema che devo affrontare è "ricevere una chiamata dalla stanza".
    In pratica dal numero 3273509509 chiamo con zoiper (client sip) la stanza (la stanza è un server sip quindi) Quindi puo esserci attiva solo una chiamata alla volta che "si inserisce" nella stanza.
    Dal microfono attivo degli utenti creo i file audio "che devo far sentire nella chiamata con 3273509509"
    Come si fa a fare tutto cio?
    1 - quali librerie java sip client e server devo usare per far diventare server la stanza in cui i partecipanti si scambiano l'audio dal microfono
    2 - quali librerie java sip client e server devo usare per chiamare il server sip


    Asterisk non centrà in tutto cio giusto? Help.
Devi accedere o registrarti per scrivere nel forum
5 risposte