Подтвердить что ты не робот

Потоковое голосование между телефонами Android через WiFi

Я пытаюсь передать аудио с микрофона с одного Android на другой через WiFi. Посмотрев на некоторые примеры, я сделал 2 приложения с одним активным действием в каждом, 1 - для записи и отправки звука, а другой для приема.

Я использовал классы Audiorecord и Audiotrack для захвата и игры. Тем не менее, я просто слышу какой-то потрескивающий звук (который теперь остановился после того, как я сделал некоторые изменения, хотя я вернулся назад)

Активность для отправки голоса.

public class VoiceSenderActivity extends Activity {

private EditText target;
private TextView streamingLabel;
private Button startButton,stopButton;

public byte[] buffer;
public static DatagramSocket socket;
private int port=50005;         //which port??
AudioRecord recorder;

//Audio Configuration. 
private int sampleRate = 8000;      //How much will be ideal?
private int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;    
private int audioFormat = AudioFormat.ENCODING_PCM_16BIT;       

private boolean status = true;




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

    target = (EditText) findViewById (R.id.target_IP);
    streamingLabel = (TextView) findViewById(R.id.streaming_label);
    startButton = (Button) findViewById (R.id.start_button);
    stopButton = (Button) findViewById (R.id.stop_button);

    streamingLabel.setText("Press Start! to begin");

    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 {


                int minBufSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);
                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(target.getText().toString());
                Log.d("VS", "Address retrieved");


                recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,sampleRate,channelConfig,audioFormat,minBufSize);
                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);


                }



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


        }

    });
    streamThread.start();
 }
 }

Активность для приема голоса

public class VoiceReceiverActivity extends Activity {


private Button receiveButton,stopButton;

public static DatagramSocket socket;
private AudioTrack speaker;

//Audio Configuration. 
private int sampleRate = 8000;      //How much will be ideal?
private int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;    
private int audioFormat = AudioFormat.ENCODING_PCM_16BIT;       

private boolean status = true;


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

    receiveButton = (Button) findViewById (R.id.receive_button);
    stopButton = (Button) findViewById (R.id.stop_button);
    findViewById(R.id.receive_label);

    receiveButton.setOnClickListener(receiveListener);
    stopButton.setOnClickListener(stopListener);

}


private final OnClickListener stopListener = new OnClickListener() {

    @Override
    public void onClick(View v) {
        status = false;
        speaker.release();
        Log.d("VR","Speaker released");

    }

};


private final OnClickListener receiveListener = new OnClickListener() {

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

    }

};

public void startReceiving() {

    Thread receiveThread = new Thread (new Runnable() {

        @Override
        public void run() {

            try {

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


                byte[] buffer = new byte[256];


                //minimum buffer size. need to be careful. might cause problems. try setting manually if any problems faced
                int minBufSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);

                speaker = new AudioTrack(AudioManager.STREAM_MUSIC,sampleRate,channelConfig,audioFormat,minBufSize,AudioTrack.MODE_STREAM);

                speaker.play();

                while(status == true) {
                    try {


                        DatagramPacket packet = new DatagramPacket(buffer,buffer.length);
                        socket.receive(packet);
                        Log.d("VR", "Packet Received");

                        //reading content from packet
                        buffer=packet.getData();
                        Log.d("VR", "Packet data read into buffer");

                        //sending data to the Audiotrack obj i.e. speaker
                        speaker.write(buffer, 0, minBufSize);
                        Log.d("VR", "Writing buffer content to speaker");

                    } catch(IOException e) {
                        Log.e("VR","IOException");
                    }
                }


            } catch (SocketException e) {
                Log.e("VR", "SocketException");
            }


        }

    });
    receiveThread.start();
}

}

Я использовал wirehark, чтобы проверить, отправляются ли пакеты, и я вижу пакеты. Однако источником является MAC-адрес отправляющего устройства и адресата, что-то вроде физического адреса. Не уверен, что это актуально.

Так что же проблема с?

4b9b3361

Ответ 1

Привет, есть библиотека с открытым исходным кодом под названием "Libstreaming", которая используется для потоковой передачи голоса/видео по сети с использованием WIFI. Просто взгляните на это:

https://github.com/fyhertz/libstreaming

Есть также некоторые примеры, любезно посмотрите на него:

https://github.com/fyhertz/libstreaming-examples

Я использовал библиотеку для Stream RTSP Audio по сети, надеюсь, что это может быть полезно.

Ответ 2

Я бы попытался разделить проблему на три части.

Часть 1

Убедитесь, что Socket Connection работает нормально комментируя все, что связано с аудио

Часть 2

Отправьте просто просто текстовое сообщение [ Hello WiFi] от отправителя, затем получите и распечатайте его в приложении-получателе.

Часть 3

Работает ли рекордер? попробуйте проверить свой способ записи в отдельном проекте, чтобы убедиться, что он работает правильно или нет.

Используйте этот > код для захвата микрофона и воспроизведения его.

Мой опыт

Когда-то я работал над подобным проектом и тестировал его, что я сделал после записи. Я записал записанные аудиоданные в виде файла на SD-карте.

(это будет сырой звук, поэтому большинство музыкальных плееров не смогут его воспроизвести... mPlayer должен играть в него, я думаю)

Ответ 3

Вам необходимо внимательно изучить использование UDP (класс DatagramSocket) в качестве сетевого протокола.

UDP - это легкий протокол, который не гарантирует поддержание порядка приема принятых пакетов. Это может быть частью причины искажения звука. Пакет, полученный не по порядку, приведет к тому, что звуковые пакеты будут воспроизводиться не в порядке. На границе этих пакетов несовпадения вы услышите щелчки/всплывающие окна, где образец звука будет эффективно поврежден. В дополнение к этому пакеты UDP не гарантированно будут доставлены успешно. Любые упавшие пакеты, очевидно, будут добавлены к искажению или искажению, которое будет услышано.

TCP (класс Socket) будет лучшим вариантом для оптимального качества звука. TCP - это более надежный протокол, который будет поддерживать порядок приема пакетов. Он также имеет встроенную проверку ошибок и будет отправлять любые упавшие пакеты. Однако из-за этой функции внимания TCP имеет более высокие сетевые издержки.

Я начал этот ответ, сказав, что вам нужно тщательно изучить, какой протокол вы используете. Это потому, что есть случай использования либо в зависимости от того, что для вас важно.

Если вы хотите воспроизведение с наименьшей задержкой, но готовы пожертвовать качеством звука, тогда UDP будет работать. Однако для определения наилучшего размера буфера и выборки потребуется некоторое экспериментирование.

Если вы хотите наилучшее возможное воспроизведение звука с нулевым искажением, но рады представить немного больше латентности, тогда TCP - это маршрут.

Я не могу сказать, сколько еще добавит TCP. Но возможно, что он может быть реализован без влияния на пользователя. Единственный способ узнать это попробовать и посмотреть.