java - 麦克风直播不清晰

标签 java udp streaming

我正在尝试通过 UDP 传输麦克风,但我的输出非常嘈杂,它无法理解输入音频。这是我的代码:

服务器端:

import java.io.DataOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.Port;
import javax.sound.sampled.TargetDataLine;

public class MicPlayer {

    private static final String IP_TO_STREAM_TO   = "localhost" ;
    private static final int PORT_TO_STREAM_TO     = 8888 ;

    /** Creates a new instance of MicPlayer */
    public MicPlayer() {

    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
    Mixer.Info minfo[] = AudioSystem.getMixerInfo() ;
    for( int i = 0 ; i < minfo.length ; i++ )
    {
     System.out.println( minfo[i] ) ;    
    }


    if (AudioSystem.isLineSupported(Port.Info.MICROPHONE)) {
    try {


      DataLine.Info dataLineInfo = new DataLine.Info(
              TargetDataLine.class , getAudioFormat() ) ;
     final TargetDataLine targetDataLine = (TargetDataLine)AudioSystem.getLine( dataLineInfo  ) ;
      targetDataLine.open( getAudioFormat() );
      targetDataLine.start();
      byte tempBuffer[] = new byte[targetDataLine.getBufferSize() / 5] ;
      int cnt = 0 ;
      while( true )
      {
      targetDataLine.read( tempBuffer , 0 , tempBuffer.length );
      sendThruUDP( tempBuffer ) ;
      }

    }
    catch(Exception e )
    {
    System.out.println(" not correct " ) ;
    System.exit(0) ;
    }
    }



    }


    public static 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 );
    }


    public static void sendThruUDP( byte soundpacket[] )
    {
       try
       {
       DatagramSocket sock = new DatagramSocket() ; 
       sock.send( new DatagramPacket( soundpacket , soundpacket.length , InetAddress.getByName( IP_TO_STREAM_TO ) , PORT_TO_STREAM_TO ) ) ; 
       sock.close() ;
       }
       catch( Exception e )
       {
       e.printStackTrace() ;
       System.out.println(" Unable to send soundpacket using UDP " ) ;   
       }

    }

    }

我不认为客户端有问题,但这是代码;

客户端:

import java.io.DataInputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

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

public class RadioReceiver extends Thread {
    private static final String IP_TO_STREAM_TO   = "localhost" ;
    private static final int PORT_TO_STREAM_TO     = 8888 ;

    /** Creates a new instance of RadioReceiver */
    public RadioReceiver() {
    }

    public void run()
    {
        byte b[] = null ;
        while( true )
        {
           b = receiveThruUDP() ; 
           toSpeaker( b ) ;
        }        
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {

    RadioReceiver r = new RadioReceiver() ;
    r.start() ;

    }

    public static byte[] receiveThruUDP()
    {
       try
       {
       DatagramSocket sock = new DatagramSocket(PORT_TO_STREAM_TO) ; 
       byte soundpacket[] = new byte[1230] ;
       DatagramPacket datagram = new DatagramPacket( soundpacket , soundpacket.length , InetAddress.getByName( IP_TO_STREAM_TO ) , PORT_TO_STREAM_TO ) ;
       sock.receive( datagram ) ; 
       sock.close() ;       return datagram.getData() ; // soundpacket ;
       }
       catch( Exception e )
       {
       System.out.println(" Unable to send soundpacket using UDP " ) ;   
       return null ;
       } 

    }


     public static void toSpeaker( byte soundbytes[] )
     {

      try{  
      DataLine.Info dataLineInfo = new DataLine.Info( SourceDataLine.class , getAudioFormat() ) ;
      SourceDataLine sourceDataLine = (SourceDataLine)AudioSystem.getLine( dataLineInfo );
      sourceDataLine.open( getAudioFormat() ) ;
      sourceDataLine.start();

      int cnt = 0;
      sourceDataLine.write( soundbytes , 0, soundbytes.length );
      sourceDataLine.drain() ;
      sourceDataLine.close() ;
      }
      catch(Exception e )
      {
      System.out.println("not working in speakers " ) ;
      }

    }


    public static 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 );
    }


}

我确定我的连接正常,但我不知道为什么我的输出如此嘈杂。这让我抓狂,我已经工作了 1 周了,请帮助我。谢谢。

最佳答案

原因可能是你的数据报包太小,导致你发送一大堆包,造成很大的开销。这可能会导致巨大的丢包率,并使它们以错误的顺序到达。

因此,增大缓冲区大小:

byte tempBuffer[] = new byte[8192] ;

这来自 DatagramSocket.receive() Java文档:

This method blocks until a datagram is received. The length field of the datagram packet object contains the length of the received message. If the message is longer than the packet's length, the message is truncated.

这也可能是一个问题。尝试使用相同的大小来发送和接收数据包。

byte soundpacket[] = new byte[8192];

此外,请勿连续打开和关闭扬声器的 AudioLine。也不要连续创建 DatagramSocket。创建一个并保留它。

关于java - 麦克风直播不清晰,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20885134/

相关文章:

streaming - Camel : split(). 标记化 ("\r").streaming() 无法按预期工作

java - 即 11 : How Can we Detect Browser Version IE 11 Using Java?

encryption - 加密传输有哪些选项

streaming - 如何从网站录制直播流媒体

udp - 使用 STUN 将 UDP 发送到 nat 后面的客户端

python - Python 中的套接字编程

c - 试图写一个代理服务器。内容长度管理问题

java - Envers在没有审计记录时在ValidityAuditStrategy中抛出RuntimeException(表分区)

java - Android - 关闭特定的蓝牙套接字

java - 这种滚动速度效果叫什么,如何实现?