2013-03-11 20 views
46

Şu anda bir Android cihazından bir Java programına canlı mikrofon ses akışı yürütmeye çalışıyorum. Yöntemimin doğru olduğunu onaylamak için iki android cihaz arasında canlı ses göndermeyle başladım. Ses, alıcı cihazda neredeyse hiç gecikme olmadan mükemmel bir şekilde duyulabilir. Daha sonra aynı ses akışını küçük bir Java programına gönderiyorum ve verilerin doğru bir şekilde buraya gönderildiğini doğruladım. Şimdi yapmak istediğim, bu verileri kodlamak ve bir şekilde Java programını çalıştıran sunucuda oynatmak. HTML5 veya JavaScript kullanarak bir web tarayıcısında oynamayı tercih ederim ancak VLC gibi alternatif yöntemlere açığım. İşte Akışı Canlı Android Audio - Sunucu

bunu biliyorum canlı mikrofon ses ya

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(); 
} 
} 

gönderir Ve burada verilerde Java programı okumak için kodudur Android uygulaması için kod ..

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

olduğunu Bunu, Java programına göndermeden önce uygulama tarafında ses kodlamalıyım, ancak AudioRecorder'ı kullanırken kodlama hakkında nasıl gideceğimi bilmiyorum. Ben hiç deneyimim yok gibi NDK kullanmamayı tercih ediyorum ve bunu nasıl kullanacağımı öğrenmek için gerçekten zamanım yok .... henüz :)

+0

yerine CHANNEL_IN_MONO kullanın. Akış sesini ne kullandınız? Sadece tek yolla istiyorum. – Atieh

+0

Bir Android uygulamasından bir masaüstü uygulamasına mikrofon akışı sağlayan bir android uygulaması yazmak istiyorum. Gönderdiğiniz içerikle ilgili bazı kaynaklara birkaç yararlı işaretçi sağlayabilir misiniz? Bu son derece yararlı olurdu! Teşekkür ederim! :) – wayway

+0

İki android cihaz arasında ses nasıl geçti? – pkBhati

cevap

47

Sorunum düzeltildi. Sorun esas olarak alıcı taraftaydı. Alıcı ses akışını alır ve PC'nin hoparlörlerine iter. Ortaya çıkan ses hala oldukça sarsıntılı ve kırılmış ama hiçbiri daha az işe yaramıyor. Tampon boyutuyla oynamak, bunu geliştirebilir.

Düzenleme: Gecikmeyi önlemek için sesi okumak için bir iş parçacığı kullanın. Ayrıca, ses için tamam olarak 16 000 örnekleme boyutu kullanmak daha iyidir.

Android Kodu:

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> 

Sunucu kodu: Umarım

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(); 
    } 
} 
} 

bu birilerine ağrısı :)

+0

Bu, sabit bir titreşim yaratır ve sesler net değildir. Ne yapılabilir? – kittu88

+0

Ses akışınızı bir android cihazdan birden fazla android cihaza grup sohbeti gibi olan bir sunucu üzerinden göndermekteyim. Bunu öğrenmeye çalışıyorum ama hiçbir şey bulamadım. –

+0

u ile iletişime geçebilir miyim? –

12
birkaç saat tasarruf sağlar

Verimliliği arttırmak için koduma 2 kuruş. Sesli çünkü android kod aşağıdaki satırın bozuldu

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

Bu gerçekten gürültüyü azaltmaya yardımcı olur mu? –

3

İyi deneme:

minBufSize += 2048; 

sadece boş bayt ekliyoruz. Ayrıca, CHANNEL_CONFIGURATION_MONO

İlgili konular