2015-01-24 17 views
5

Tôi đang triển khai phát trực tiếp từ MIC đến máy chủ java tại một máy tính khác. Nhưng tôi chỉ nghe thấy một tiếng ồn trắng.Dòng âm thanh trực tiếp java

Tôi có kèm theo cả khách hàng và chương trình máy chủ

Client: 

import java.io.IOException; 
import java.net.DatagramPacket; 
import java.net.DatagramSocket; 
import java.net.InetAddress; 
import java.net.SocketException; 
import java.net.UnknownHostException; 

import javax.sound.sampled.AudioFormat; 
import javax.sound.sampled.AudioInputStream; 
import javax.sound.sampled.AudioSystem; 
import javax.sound.sampled.DataLine; 
import javax.sound.sampled.LineUnavailableException; 
import javax.sound.sampled.TargetDataLine; 

public class Mic 
{ 
    public byte[] buffer; 
    private int port; 
    static AudioInputStream ais; 

    public static void main(String[] args) 
    { 
     TargetDataLine line; 
     DatagramPacket dgp; 

     AudioFormat.Encoding encoding = AudioFormat.Encoding.PCM_SIGNED; 
     float rate = 44100.0f; 
     int channels = 2; 
     int sampleSize = 16; 
     boolean bigEndian = true; 
     InetAddress addr; 


     AudioFormat format = new AudioFormat(encoding, rate, sampleSize, channels, (sampleSize/8) * channels, rate, bigEndian); 

     DataLine.Info info = new DataLine.Info(TargetDataLine.class, format); 
     if (!AudioSystem.isLineSupported(info)) { 
      System.out.println("Line matching " + info + " not supported."); 
      return; 
     } 

     try 
     { 
      line = (TargetDataLine) AudioSystem.getLine(info); 

      int buffsize = line.getBufferSize()/5; 
      buffsize += 512; 

      line.open(format); 

      line.start(); 

      int numBytesRead; 
      byte[] data = new byte[buffsize]; 

      addr = InetAddress.getByName("127.0.0.1"); 
      DatagramSocket socket = new DatagramSocket(); 
      while (true) { 
        // Read the next chunk of data from the TargetDataLine. 
        numBytesRead = line.read(data, 0, data.length); 
        // Save this chunk of data. 
        dgp = new DatagramPacket (data,data.length,addr,50005); 

        socket.send(dgp); 
       } 

     }catch (LineUnavailableException e) { 
      e.printStackTrace(); 
     }catch (UnknownHostException e) { 
      // TODO: handle exception 
     } catch (SocketException e) { 
      // TODO: handle exception 
     } catch (IOException e2) { 
      // TODO: handle exception 
     } 
    } 
} 

và phía máy chủ là không có vấn đề. Nó đang chạy hoàn hảo với khách hàng Android AudioRecord.

Server: 

import java.io.ByteArrayInputStream; 
import java.net.DatagramPacket; 
import java.net.DatagramSocket; 

import javax.sound.sampled.AudioFormat; 
import javax.sound.sampled.AudioInputStream; 
import javax.sound.sampled.AudioSystem; 
import javax.sound.sampled.DataLine; 
import javax.sound.sampled.SourceDataLine; 

public class Server { 

    AudioInputStream audioInputStream; 
    static AudioInputStream ais; 
    static AudioFormat format; 
    static boolean status = true; 
    static int port = 50005; 
    static int sampleRate = 44100; 

    static DataLine.Info dataLineInfo; 
    static SourceDataLine sourceDataLine; 

    public static void main(String args[]) throws Exception 
    { 
     System.out.println("Server started at port:"+port); 

     DatagramSocket serverSocket = new DatagramSocket(port); 

     /** 
     * Formula for lag = (byte_size/sample_rate)*2 
     * Byte size 9728 will produce ~ 0.45 seconds of lag. Voice slightly broken. 
     * Byte size 1400 will produce ~ 0.06 seconds of lag. Voice extremely broken. 
     * Byte size 4000 will produce ~ 0.18 seconds of lag. Voice slightly more broken then 9728. 
     */ 

     byte[] receiveData = new byte[4096]; 

     format = new AudioFormat(sampleRate, 16, 1, true, false); 
     dataLineInfo = new DataLine.Info(SourceDataLine.class, format); 
     sourceDataLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo); 
     sourceDataLine.open(format); 
     sourceDataLine.start(); 

     //FloatControl volumeControl = (FloatControl) sourceDataLine.getControl(FloatControl.Type.MASTER_GAIN); 
     //volumeControl.setValue(1.00f); 

     DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); 

     ByteArrayInputStream baiss = new ByteArrayInputStream(receivePacket.getData()); 

     while (status == true) 
     { 
      serverSocket.receive(receivePacket); 
      ais = new AudioInputStream(baiss, format, receivePacket.getLength()); 
      toSpeaker(receivePacket.getData()); 
     } 

     sourceDataLine.drain(); 
     sourceDataLine.close(); 
    } 

    public static void toSpeaker(byte soundbytes[]) { 
     try 
     { 
      System.out.println("At the speaker"); 
      sourceDataLine.write(soundbytes, 0, soundbytes.length); 
     } catch (Exception e) { 
      System.out.println("Not working in speakers..."); 
      e.printStackTrace(); 
     } 
    } 
} 

Trả lời

2

Vì vậy, tôi đã lấp đầy micrô bằng sóng sin (hoặc cái gì đó, theo nghĩa mơ hồ nào đó, giống như sóng sin) và chương trình của bạn hoạt động tốt.

thay đổi cụ thể của tôi là như sau:

package audioclient; 

import java.io.*; 
import java.net.*; 
import java.nio.ByteBuffer; 

import javax.sound.sampled.*; 

public class Mic { 
    public byte[] buffer; 
    private int port; 
    static AudioInputStream ais; 

     public static void main(String[] args) { 
     TargetDataLine line; 
     DatagramPacket dgp; 

     AudioFormat.Encoding encoding = AudioFormat.Encoding.PCM_SIGNED; 
     float rate = 44100.0f; 
     int channels = 2; 
     int sampleSize = 16; 
     boolean bigEndian = true; 
     InetAddress addr; 

     AudioFormat format = new AudioFormat(encoding, rate, sampleSize, channels, (sampleSize/8) * channels, rate, bigEndian); 

     DataLine.Info info = new DataLine.Info(TargetDataLine.class, format); 
     if (!AudioSystem.isLineSupported(info)) { 
      System.out.println("Line matching " + info + " not supported."); 
      return; 
     } 

     try { 
      line = (TargetDataLine) AudioSystem.getLine(info); 

      //TOTALLY missed this. 
      int buffsize = line.getBufferSize()/5; 
      buffsize += 512; 

      line.open(format); 

      line.start(); 

      int numBytesRead; 
      byte[] data = new byte[buffsize]; 

      /* 
      * MICK's injection: We have a buffsize of 512; it is best if the frequency 
      * evenly fits into this (avoid skips, bumps, and pops). Additionally, 44100 Hz, 
      * with two channels and two bytes per sample. That's four bytes; divide 
      * 512 by it, you have 128. 
      * 
      * 128 samples, 44100 per second; that's a minimum of 344 samples, or 172 Hz. 
      * Well within hearing range; slight skip from the uneven division. Maybe 
      * bump it up to 689 Hz. 
      * 
      * That's a sine wave of shorts, repeated twice for two channels, with a 
      * wavelength of 32 samples. 
      * 
      * Note: Changed my mind, ignore specific numbers above. 
      * 
      */ 
      { 
       final int λ = 16; 
       ByteBuffer buffer = ByteBuffer.allocate(λ * 2 * 8); 
       for(int j = 0; j < 2; j++) { 
        for(double i = 0.0; i < λ; i++) { 
         System.out.println(j + " " + i); 
         //once for each sample 
         buffer.putShort((short)(Math.sin(Math.PI * (λ/i)) * Short.MAX_VALUE)); 
         buffer.putShort((short)(Math.sin(Math.PI * (λ/i)) * Short.MAX_VALUE)); 
        } 
       } 

       data = buffer.array(); 
      } 

      addr = InetAddress.getByName("127.0.0.1"); 
      try(DatagramSocket socket = new DatagramSocket()) { 
       while (true) { 
        for(byte b : data) System.out.print(b + " "); 

        // Read the next chunk of data from the TargetDataLine. 
//     numBytesRead = line.read(data, 0, data.length); 

        for(int i = 0; i < 64; i++) { 
         byte b = data[i]; 
         System.out.print(b + " "); 
        } 
        System.out.println(); 

        // Save this chunk of data. 
        dgp = new DatagramPacket(data, data.length, addr, 50005);  

        for(int i = 0; i < 64; i++) { 
         byte b = dgp.getData()[i]; 
         System.out.print(b + " "); 
        } 
        System.out.println(); 

        socket.send(dgp); 
       } 
      } 

     } catch (LineUnavailableException e) { 
      e.printStackTrace(); 
     } catch (UnknownHostException e) { 
      // TODO: handle exception 
     } catch (SocketException e) { 
      // TODO: handle exception 
     } catch (IOException e2) { 
      // TODO: handle exception 
     } 
    } 
} 

Rõ ràng là tôi hiểu sai nó như là một mảnh 512-byte dài và hỏng làn sóng sin, nhưng vấn đề là, nó được sản xuất một cách chính xác các âm thanh mà nó có nghĩa là để - tâm trí-rít rít ở một sân cụ thể.

Điều này trong tâm trí, tôi không nghi ngờ rằng vấn đề là rõ ràng trong mã của bạn. Điều đầu tiên tôi sẽ kiểm tra là dòng hệ thống của bạn đang khai thác cho âm thanh. Bạn có nhiều micrô được kết nối không? Một mic webcam, có thể? Bạn có thể lấy một tiện ích như PulseAudio Volume Control để kiểm tra. Nếu bạn chưa kiểm tra chức năng của micrô, bạn cũng có thể làm điều đó; họ có tuổi thọ trên chúng.

Nó không phải là không phổ biến ở tất cả để tranh giành các bit trong một dòng âm thanh, cũng không phải là khó khăn; nhưng tôi không thấy bất cứ nơi nào bạn có thể làm điều đó.

Một ý nghĩ có thể là sửa đổi chương trình của bạn để cố gắng phát âm thanh cục bộ, trước khi gửi nó đến máy chủ. Bằng cách đó, bạn có thể ít nhất là xác định xem vấn đề là trước hay sau Mic.

0

Tôi khuyên bạn trước tiên nên ghi vào tệp âm thanh được ghi trên máy khách. Điều này sẽ cho phép bạn xác minh xem âm thanh đã ghi có OK hay không. Bạn có thể chuyển đổi PCM sang WAV bằng các tiện ích như sox.

1

Khi máy khách và máy chủ sử dụng bộ đệm dữ liệu có kích thước khác nhau, bộ đệm sẽ bị cắt bớt và có thể khiến một hoặc cả hai tạo ra các tạo phẩm.

kích thước máy chủ đệm của bạn được thiết lập để byte[] receiveData = new byte[4096];

kích thước bộ đệm Khách hàng của bạn là vì một lý do năng động, và thiết lập để byte[] data = new byte[buffsize];

Set kích thước bộ đệm khách hàng đến một tĩnh 4096 để phù hợp với máy chủ: byte[] data = new byte[4096];

Hoặc chỉ cần đảm bảo chúng có cùng kích thước ...

0

Điều quan trọng là phải khớp định dạng âm thanh trên cả máy khách và máy chủ, ví dụ: thay đổi định dạng trong C lient.java tới: format = new AudioFormat(sampleRate, 16, 1, true, false); Bạn cũng cần sử dụng cùng kích thước bộ đệm trên cả hai chương trình.

Các vấn đề liên quan