2013-03-11 10 views
46

現在、AndroidデバイスからJavaプログラムにライブマイクオーディオをストリーミングしようとしています。私は2つのアンドロイドデバイスの間でライブオーディオを送信して、自分の方法が正しいことを確認し始めました。受信デバイスの遅延がほとんどなく、オーディオが完全に聞こえます。次に、同じオーディオストリームを小さなJavaプログラムに送信し、データが正しく送信されていることを確認しました。今私がやりたいことは、このデータをエンコードして、何とかJavaプログラムを実行しているサーバーでそれを再生することです。むしろ、HTML5やJavaScriptを使用してWebブラウザで再生したいと思っていますが、VLCのような別の方法にも対応しています。ここでStreamライブAndroidオーディオをサーバ

は、ライブマイクオーディオ

public class MainActivity extends Activity { 


private Button startButton,stopButton; 

public byte[] buffer; 
public static DatagramSocket socket; 
    AudioRecord recorder; 

private int sampleRate = 44100; 
private int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;  
private int audioFormat = AudioFormat.ENCODING_PCM_16BIT;  
int minBufSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat); 
    private boolean status = true; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    startButton = (Button) findViewById (R.id.start_button); 
    stopButton = (Button) findViewById (R.id.stop_button); 

    startButton.setOnClickListener(startListener); 
    stopButton.setOnClickListener(stopListener); 

    minBufSize += 2048; 
} 

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    getMenuInflater().inflate(R.menu.main, menu); 
    return true; 
} 

private final OnClickListener stopListener = new OnClickListener() { 

    @Override 
    public void onClick(View arg0) { 
       status = false; 
       recorder.release(); 
       Log.d("VS","Recorder released"); 
    } 
}; 

private final OnClickListener startListener = new OnClickListener() { 

    @Override 
    public void onClick(View arg0) { 
       status = true; 
       startStreaming();   
    } 
}; 



public void startStreaming() 
{ 
    Thread streamThread = new Thread(new Runnable(){ 
     @Override 
     public void run() 
     { 
      try{ 

       DatagramSocket socket = new DatagramSocket(); 
       Log.d("VS", "Socket Created"); 

       byte[] buffer = new byte[minBufSize]; 

       Log.d("VS","Buffer created of size " + minBufSize); 


       Log.d("VS", "Address retrieved"); 
       recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,sampleRate,channelConfig,audioFormat,minBufSize); 
       Log.d("VS", "Recorder initialized"); 


       recorder.startRecording(); 


       InetAddress IPAddress = InetAddress.getByName("192.168.1.5"); 
       byte[] sendData = new byte[1024]; 
       byte[] receiveData = new byte[1024]; 


       while (status == true) 
       { 
        DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, 50005); 
        socket.send(sendPacket); 
       } 

      } catch(UnknownHostException e) { 
       Log.e("VS", "UnknownHostException"); 
      } catch (IOException e) { 
       Log.e("VS", "IOException"); 
       e.printStackTrace(); 
      } 


     } 

    }); 
    streamThread.start(); 
} 
} 

を送信し、ここにデータを読み込むJavaプログラムのためのコードであるAndroidアプリ..

class Server 
{ 
    public static void main(String args[]) throws Exception 
     { 
     DatagramSocket serverSocket = new DatagramSocket(50005); 
      byte[] receiveData = new byte[1024]; 
      byte[] sendData = new byte[1024]; 
      while(true) 
       { 
        DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); 



       serverSocket.receive(receivePacket); 
       String sentence = new String(receivePacket.getData().toString()); 

       System.out.println("RECEIVED: " + sentence); 
      } 
    } 
} 

のコードがあること私は知っているありますこれをJavaプログラムに送信する前に、アプリケーション側でオーディオをエンコードする必要がありますが、AudioRecorderを使用しているときにエンコーディングの仕方を確認するのは難しいです。私はそれを経験していないので、実際にそれを使用する方法を学ぶための時間がないので、NDKを使用しないことを好むでしょう:)まだ

+0

ストリームオーディオをどのように使用しましたか?私は片方だけのためにそれをしたい。 – Atieh

+0

Androidデバイスからデスクトップアプリケーションにライブマイクオーディオをストリームするアンドロイドアプリを書くことに興味があります。あなたが投稿したコンテンツに関連するいくつかのリソースへのいくつかの役に立つポインタを提供してください。それは非常に役に立つでしょう!ありがとうございました! :) – wayway

+0

あなたは2つのAndroid搭載デバイス間でライブオーディオをやりましたか? – pkBhati

答えて

47

私は問題を修正しました。問題は主に受信側にありました。受信機はオーディオストリームを取り込み、PCのスピーカーにプッシュします。結果として得られる声はまだかなり遅れていて壊れていますが、それほど効果はありません。バッファサイズで再生すると、これが改善される可能性があります。

編集:スレッドを使用して、遅延を避けるためにオーディオを読み込みます。また、16000のサンプリングサイズを使用する方が良いです。

のAndroidコード:

package com.example.mictest2; 

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

import android.app.Activity; 
import android.media.AudioFormat; 
import android.media.AudioRecord; 
import android.media.MediaRecorder; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.Button; 

public class Send extends Activity { 
private Button startButton,stopButton; 

public byte[] buffer; 
public static DatagramSocket socket; 
private int port=50005; 

AudioRecord recorder; 

private int sampleRate = 16000 ; // 44100 for music 
private int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;  
private int audioFormat = AudioFormat.ENCODING_PCM_16BIT;  
int minBufSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat); 
private boolean status = true; 


@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    startButton = (Button) findViewById (R.id.start_button); 
    stopButton = (Button) findViewById (R.id.stop_button); 

    startButton.setOnClickListener (startListener); 
    stopButton.setOnClickListener (stopListener); 

} 

private final OnClickListener stopListener = new OnClickListener() { 

    @Override 
    public void onClick(View arg0) { 
       status = false; 
       recorder.release(); 
       Log.d("VS","Recorder released"); 
    } 

}; 

private final OnClickListener startListener = new OnClickListener() { 

    @Override 
    public void onClick(View arg0) { 
       status = true; 
       startStreaming();   
    } 

}; 

public void startStreaming() { 


    Thread streamThread = new Thread(new Runnable() { 

     @Override 
     public void run() { 
      try { 

       DatagramSocket socket = new DatagramSocket(); 
       Log.d("VS", "Socket Created"); 

       byte[] buffer = new byte[minBufSize]; 

       Log.d("VS","Buffer created of size " + minBufSize); 
       DatagramPacket packet; 

       final InetAddress destination = InetAddress.getByName("192.168.1.5"); 
       Log.d("VS", "Address retrieved"); 


       recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,sampleRate,channelConfig,audioFormat,minBufSize*10); 
       Log.d("VS", "Recorder initialized"); 

       recorder.startRecording(); 


       while(status == true) { 


        //reading data from MIC into buffer 
        minBufSize = recorder.read(buffer, 0, buffer.length); 

        //putting buffer in the packet 
        packet = new DatagramPacket (buffer,buffer.length,destination,port); 

        socket.send(packet); 
        System.out.println("MinBufferSize: " +minBufSize); 


       } 



      } catch(UnknownHostException e) { 
       Log.e("VS", "UnknownHostException"); 
      } catch (IOException e) { 
       e.printStackTrace(); 
       Log.e("VS", "IOException"); 
      } 
     } 

    }); 
    streamThread.start(); 
} 
} 

AndroidのXML:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:tools="http://schemas.android.com/tools" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:paddingBottom="@dimen/activity_vertical_margin" 
android:paddingLeft="@dimen/activity_horizontal_margin" 
android:paddingRight="@dimen/activity_horizontal_margin" 
android:paddingTop="@dimen/activity_vertical_margin" 
tools:context=".MainActivity" > 

<TextView 
    android:id="@+id/textView1" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="@string/hello_world" /> 

<Button 
    android:id="@+id/start_button" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_below="@+id/textView1" 
    android:layout_centerHorizontal="true" 
    android:layout_marginTop="130dp" 
    android:text="Start" /> 

<Button 
    android:id="@+id/stop_button" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_alignLeft="@+id/button1" 
    android:layout_below="@+id/button1" 
    android:layout_marginTop="64dp" 
    android:text="Stop" /> 

</RelativeLayout> 

Serverコード:

package com.datagram; 

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.FloatControl; 
import javax.sound.sampled.SourceDataLine; 

class Server { 

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

public static void main(String args[]) throws Exception { 


    DatagramSocket serverSocket = new DatagramSocket(50005); 


    byte[] receiveData = new byte[1280]; 
    // (1280 for 16 000Hz and 3584 for 44 100Hz (use AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat) to get the correct size) 

    format = new AudioFormat(sampleRate, 16, 1, true, false); 

    while (status == true) { 
     DatagramPacket receivePacket = new DatagramPacket(receiveData, 
       receiveData.length); 

     serverSocket.receive(receivePacket); 

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

     ais = new AudioInputStream(baiss, format, receivePacket.getLength()); 

     // A thread solve the problem of chunky audio 
     new Thread(new Runnable() { 
      @Override 
      public void run() { 
       toSpeaker(receivePacket.getData(), sourceDataLine); 
      } 
     }).start(); 
    } 
} 

public static void toSpeaker(byte soundbytes[]) { 
    try { 

     DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class, format); 
     SourceDataLine sourceDataLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo); 

     sourceDataLine.open(format); 

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

     sourceDataLine.start(); 
     sourceDataLine.open(format); 

     sourceDataLine.start(); 

     System.out.println("format? :" + sourceDataLine.getFormat()); 

     sourceDataLine.write(soundbytes, 0, soundbytes.length); 
     System.out.println(soundbytes.toString()); 
     sourceDataLine.drain(); 
     sourceDataLine.close(); 
    } catch (Exception e) { 
     System.out.println("Not working in speakers..."); 
     e.printStackTrace(); 
    } 
} 
} 

私はこれが誰かに痛みの数時間を節約することができます願っています:)

+0

これにより、一定のジッタが生成され、音声がはっきりしません。何ができますか? – kittu88

+0

あなたはグループの会話のようなサーバーを介して、1つのアンドロイドデバイスから複数のアンドロイドデバイスにあなたの音声ストリームを送ります。私はそれを学ぼうとしていますが、何も見つかりませんでした。 –

+0

私はuと連絡できますか? –

12

あなたのコードに2セントを入れて効率を上げてください。声が原因であなたのAndroidのコードに次の行を切断された

package com.datagram; 

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.FloatControl; 
import javax.sound.sampled.SourceDataLine; 

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 { 

    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 { 
      sourceDataLine.write(soundbytes, 0, soundbytes.length); 
     } catch (Exception e) { 
      System.out.println("Not working in speakers..."); 
      e.printStackTrace(); 
     } 
    } 
} 
+0

これは本当にノイズを減らすのに役立ちますか? –

3

惜しい:

minBufSize += 2048; 

は、あなただけの空のバイトを追加しています。また、CHANNEL_CONFIGURATION_MONOの代わりにCHANNEL_IN_MONOを使用してください。

関連する問題