2015-10-12 164 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