2015-10-12 105 views
1

我正在尝试创建一个应用程序,该应用程序记录来自麦克风的音频并通过套接字将其发送到另一部手机上的服务器。为了模拟另一部手机,我正在使用本地主机上的ServerSocket。现在我知道,我可能不会在服务器上发生44100Hz,立体声,PCM_16BIT音频不振荡但没有一些疯狂的压缩,但是我的套接字的传输速度非常低。我大约16kB/s。在本地主机上!Android慢速插座读取

这是我的客户(运行在一个服务为两个线程):

LinkedBlockingQueue<byte[]> audioQueue = new LinkedBlockingQueue<>(100); 
boolean isRecording; 

int sample_rate = 44100; 
int buff_size = AudioRecord.getMinBufferSize(sample_rate, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT); 

void recorderThread_func() throws InterruptedException, IOException{ 
    int s_read; 
    byte[] tmp_buff; 
    byte[] buffer = new byte[buff_size]; 

    AudioRecord recorder = new AudioRecord(
      MediaRecorder.AudioSource.MIC, 
      sample_rate, 
      AudioFormat.CHANNEL_IN_STEREO, 
      AudioFormat.ENCODING_PCM_16BIT, 
      buff_size); 
    recorder.startRecording(); 
    isRecording = true; 

    while (isRecording) { 
     tmp_buff = new byte[buff_size]; 
     s_read = recorder.read(buffer, 0, buff_size); 
     System.arraycopy(buffer, 0, tmp_buff, 0, s_read); 

     audioQueue.put(tmp_buff); 
    } 

    isRecording = false; 
    recorder.stop(); 
} 

void socketThread_func() throws IOException, InterruptedException { 
    byte[] tmp_buffer; 

    Thread.sleep(250); 

    Socket audioSocket = new Socket("127.0.0.1", 2004); 
    OutputStream out = audioSocket.getOutputStream(); 
    InputStream in = audioSocket.getInputStream(); 
    out.flush(); 

    tmp_buffer = new byte[]{ 
      (byte) 0xde, 
      (byte) ((buff_size >> 24) & 0xff), 
      (byte) ((buff_size >> 16) & 0xff), 
      (byte) ((buff_size >> 8) & 0xff), 
      (byte) ((buff_size  ) & 0xff)}; 
    out.write(tmp_buffer, 0, 5); 
    out.flush(); 

    long a; 
    long b; 
    long c = 1; 
    long d = 1; 
    while (isRecording) { 
     tmp_buffer = audioQueue.take(); 

      a = System.currentTimeMillis(); 
     out.write(tmp_buffer, 0, buff_size); 
     out.flush(); 
      b = System.currentTimeMillis(); 
      c += b-a; 
      d++; 
      System.out.println("speed=" + ((1000*buff_size*(d++))/c)); 

     in.read(tmp_buffer, 0, 1); 
     if (tmp_buffer[0] != (byte)'A') 
      break; 
    } 

    isRecording = false; 
    out.flush(); 
    audioSocket.close(); 
} 

这是我的服务器代码(在两个独立的线程中运行):

int buff_size = 0; 
boolean isPlaying; 

LinkedBlockingQueue<byte[]> audioQueue = new LinkedBlockingQueue<>(100); 

void socketThread_func() throws IOException, InterruptedException{ 
    byte[] msg = new byte[5]; 
    byte[] tmp_buffer; 
    int s_read; 

    ServerSocket audioSocket = new ServerSocket(); 
    audioSocket.setReceiveBufferSize(1024 * 1024 * 16); 
    audioSocket.bind(new InetSocketAddress("127.0.0.1", 2004)); 

    Socket connSocket = audioSocket.accept(); 
    OutputStream out = connSocket.getOutputStream(); 
    InputStream in = connSocket.getInputStream(); 
    out.flush(); 

    in.read(msg, 0, 5); 
    if (msg[0] != ((byte)0xde)) { 
     return; 
    } 
    buff_size = ((int)msg[4] & 0xff) + (((int)msg[3] & 0xff) << 8) + (((int)msg[2] & 0xff) << 16) + (((int)msg[1] & 0xff) << 24); 
    msg = new byte[buff_size]; 
    System.out.println("read: " + buff_size); 

    isPlaying = true; 

    long a; 
    long b; 
    long c = 1; 
    long d = 1; 
    while (isPlaying) { 
      a = System.currentTimeMillis(); 
     s_read = in.read(msg); 
      b = System.currentTimeMillis(); 
      c += b-a; 
      d++; 
      System.out.println("speed_sv=" + ((1000*buff_size*(d++))/c)); 
     if (s_read == -1) 
      break; 

     tmp_buffer = new byte[buff_size]; 
     System.arraycopy(msg, 0, tmp_buffer, 0, s_read); 
     audioQueue.put(tmp_buffer); 

     out.write('A'); 
     out.flush(); 
    } 
    isPlaying = false; 

    connSocket.close(); 
    audioSocket.close(); 
} 

private static void playerThread_func() throws InterruptedException{ 
    byte[] tmp_buffer; 

    Thread.sleep(750); 

    AudioTrack mAudioTrack = new AudioTrack(
      AudioManager.STREAM_MUSIC, 
      sample_rate, 
      AudioFormat.CHANNEL_IN_STEREO, 
      AudioFormat.ENCODING_PCM_16BIT, 
      buff_size, 
      AudioTrack.MODE_STREAM); 
    mAudioTrack.play(); 

    while (isPlaying) { 
     tmp_buffer = audioQueue.take(); 
     mAudioTrack.write(tmp_buffer, 0, buff_size); 
    } 

    isPlaying = false; 
    mAudioTrack.stop(); 
} 

的代码是一个由于我试图弄清楚为什么它如此缓慢,我有点混乱。这可能是某种愚蠢的错误,但我看不到它。

编辑:我修改了代码,以便现在它有不同的线程记录/播放和套接字处理。事实证明,代码的发送部分在高速下工作得很好,这足以传输44100Hz的音频(通过127.0.0.1)。但服务器的in.read()函数似乎是减慢了一切。

速度= 272243612

speed_sv = 459849

+0

记录先发送。不要同时录制和发送。你还用什么连接?无线上网?这里有很多事情可能会出错。 – Namphibian

+0

我还没有使用任何连接。这一切都在本地主机上。这就是为什么我对速度感到惊讶。我会尝试你的建议并回报。 – uneasy

+0

那么它的16kB/s不变?没有变化?如果是这种情况,问题不是你的代码,而是一个localhost config/setup/throttle问题。通过网络进行测试,看看是否有差异。 – Namphibian

回答

0

这是没有办法写一个副本循环。您每次读取分配两个字节数组。记住这一点:

byte[] buffer = new byte[8192]; 
int count; 
while ((count = in.read(buffer)) > 0) 
{ 
    out.write(buffer, 0, count); 
} 
+0

感谢您的建议,但是它并没有解决我的问题,实际上是我的代码的以前版本,现在我知道我应该在编辑它时保留在我的文章中。 – uneasy