2013-04-11 12 views
12

मैं एक साधारण एंड्रॉइड एप्लिकेशन बनाने की कोशिश कर रहा हूं जो प्लेबैक के लिए सर्वर पर लाइव माइक्रोफ़ोन ऑडियो स्ट्रीम करता है। परिणामस्वरूप प्लेबैक अजीब लगता है, ऑडियो में बड़े अंतराल के साथ। क्या कोई जानता है कि मुझसे क्या गलती हो रही है?यूडीपी प्लेबैक मुद्दे पर सर्वर पर एंड्रॉइड ऑडियो रिकॉर्डॉर्ड

संपादित करें: हल किया गया। बाहर निकलता है मैं मान रहा था कि प्रत्येक आने वाले बफर पूरी तरह से भरा होगा, मेरे हिस्से पर एक दोषपूर्ण धारणा।

यहाँ मेरी गतिविधि है:

public class MainActivity extends Activity { 
    private static String TAG = "AudioClient"; 

    // the server information 
    private static final String SERVER = "xx.xx.xx.xx"; 
    private static final int PORT = 50005; 

    // the audio recording options 
    private static final int RECORDING_RATE = 44100; 
    private static final int CHANNEL = AudioFormat.CHANNEL_IN_MONO; 
    private static final int FORMAT = AudioFormat.ENCODING_PCM_16BIT; 

    // the button the user presses to send the audio stream to the server 
    private Button sendAudioButton; 

    // the audio recorder 
    private AudioRecord recorder; 

    // the minimum buffer size needed for audio recording 
    private static int BUFFER_SIZE = AudioRecord.getMinBufferSize(
      RECORDING_RATE, CHANNEL, FORMAT); 

    // are we currently sending audio data 
    private boolean currentlySendingAudio = false; 

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

     Log.i(TAG, "Creating the Audio Client with minimum buffer of " 
       + BUFFER_SIZE + " bytes"); 

     // set up the button 
     sendAudioButton = (Button) findViewById(R.id.start_button); 
     sendAudioButton.setOnTouchListener(new OnTouchListener() { 

      @Override 
      public boolean onTouch(View v, MotionEvent event) { 

       switch (event.getAction()) { 

       case MotionEvent.ACTION_DOWN: 
        startStreamingAudio(); 
        break; 

       case MotionEvent.ACTION_UP: 
        stopStreamingAudio(); 
        break; 
       } 

       return false; 
      } 
     }); 
    } 

    private void startStreamingAudio() { 

     Log.i(TAG, "Starting the audio stream"); 
     currentlySendingAudio = true; 
     startStreaming(); 
    } 

    private void stopStreamingAudio() { 

     Log.i(TAG, "Stopping the audio stream"); 
     currentlySendingAudio = false; 
     recorder.release(); 
    } 

    private void startStreaming() { 

     Log.i(TAG, "Starting the background thread to stream the audio data"); 

     Thread streamThread = new Thread(new Runnable() { 

      @Override 
      public void run() { 
       try { 

        Log.d(TAG, "Creating the datagram socket"); 
        DatagramSocket socket = new DatagramSocket(); 

        Log.d(TAG, "Creating the buffer of size " + BUFFER_SIZE); 
        byte[] buffer = new byte[BUFFER_SIZE]; 

        Log.d(TAG, "Connecting to " + SERVER + ":" + PORT); 
        final InetAddress serverAddress = InetAddress 
          .getByName(SERVER); 
        Log.d(TAG, "Connected to " + SERVER + ":" + PORT); 

        Log.d(TAG, "Creating the reuseable DatagramPacket"); 
        DatagramPacket packet; 

        Log.d(TAG, "Creating the AudioRecord"); 
        recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, 
          RECORDING_RATE, CHANNEL, FORMAT, BUFFER_SIZE * 10); 

        Log.d(TAG, "AudioRecord recording..."); 
        recorder.startRecording(); 

        while (currentlySendingAudio == true) { 

         // read the data into the buffer 
         int read = recorder.read(buffer, 0, buffer.length); 

         // place contents of buffer into the packet 
         packet = new DatagramPacket(buffer, read, 
          serverAddress, PORT); 

         // send the packet 
         socket.send(packet); 
        } 

        Log.d(TAG, "AudioRecord finished recording"); 

       } catch (Exception e) { 
        Log.e(TAG, "Exception: " + e); 
       } 
      } 
     }); 

     // start the thread 
     streamThread.start(); 
    } 
} 

यहाँ मेरी सर्वर-साइड कोड है:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:padding="20dip"> 

    <ImageView 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:src="@drawable/ic_launcher" 
     android:scaleType="fitCenter"/> 

     <TextView 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:text="@string/app_info" 
     android:layout_weight="1.0" 
     android:textSize="20dip"/> 

    <LinearLayout 
     android:orientation="horizontal" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content"> 

     <Button 
       android:layout_width="wrap_content" 
       android:layout_height="wrap_content" 
       android:id="@+id/btnStart" 
       android:text="@string/start_recording" 
       android:layout_weight="1.0"/> 

       <Button 
       android:layout_width="wrap_content" 
       android:layout_height="wrap_content" 
       android:id="@+id/btnStop" 
       android:text="@string/stop_recording" 
       android:layout_weight="1.0"/> 
    </LinearLayout> 
</LinearLayout> 
:

class Server { 

    AudioInputStream audioInputStream; 
    static AudioInputStream ais; 
    static AudioFormat format; 
    static boolean status = true; 
    static int port = 50005; 
    static int sampleRate = 11025; 
    static int bufferSize = 9728; 

    static Long lastTime; 
    static long totalBytesReceived = 0L; 

    private static final int audioStreamBufferSize = bufferSize * 20; 
    static byte[] audioStreamBuffer = new byte[audioStreamBufferSize]; 
    private static int audioStreamBufferIndex = 0; 

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

     Log("Starting the AudioServer..."); 

     Log("Creating the datagram socket on port " + port + "..."); 
     DatagramSocket serverSocket = new DatagramSocket(null); 
     serverSocket.setReuseAddress(true); 
     serverSocket.bind(new InetSocketAddress(port)); 

     Log("Creating the buffer to hold the received data of size " 
       + bufferSize + "..."); 
     byte[] receiveData = new byte[bufferSize]; 

     Log("Setting the audio rate to " + sampleRate + "hz..."); 
     format = new AudioFormat(sampleRate, 16, 1, true, false); 

     Log("Ready to receive audio data"); 
     while (status == true) { 

      DatagramPacket receivePacket = new DatagramPacket(receiveData, 
        receiveData.length); 
      serverSocket.receive(receivePacket); 
      bufferAudioForPlayback(receivePacket.getData(), 
        receivePacket.getOffset(), receivePacket.getLength()); 
     } 

     serverSocket.close(); 
    } 

    private static void bufferAudioForPlayback(byte[] buffer, int offset, 
      int length) { 

     byte[] actualBytes = new byte[length]; 

     for (int i = 0; i < length; i++) { 
      actualBytes[i] = buffer[i]; 
     } 

     for (byte sample : actualBytes) { 

      int percentage = (int) (((double) audioStreamBufferIndex/(double) audioStreamBuffer.length) * 100.0); 
      Log("buffer is " + percentage + "% full"); 

      audioStreamBuffer[audioStreamBufferIndex] = sample; 
      audioStreamBufferIndex++; 
      Log("Buffer " + audioStreamBufferIndex + "/" 
        + audioStreamBuffer.length + " " + percentage); 

      if (audioStreamBufferIndex == audioStreamBuffer.length - 1) { 
       toSpeaker(audioStreamBuffer); 
       audioStreamBufferIndex = 0; 
       System.exit(0); 
      } 
     } 
    } 

    private static void Log(String log) { 
     System.out.println(log); 
    } 

    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(); 
      sourceDataLine.write(soundbytes, 0, soundbytes.length); 
      sourceDataLine.drain(); 
      sourceDataLine.close(); 
     } catch (Exception e) { 
      System.out.println("Error with audio playback: " + e); 
      e.printStackTrace(); 
     } 
    } 
} 

अंत में, यहाँ मुख्य गतिविधि के लिए संसाधन xml फ़ाइल है

संपादित करें: प्लेबैक ऑडियो suh-suh-suh-suh-o-ou-ou-ou-nds-nds-ds इस तरह। आप recorder से पूरी तरह से पढ़ने के बफर प्राप्त अपेक्षा न करें लेकिन का उपयोग वास्तविक पढ़ने मूल्य के बजाय

// read the data into the buffer 
int read = recorder.read(buffer, 0, buffer.length); 

// place contents of buffer into the packet 
packet = new DatagramPacket(buffer, read, serverAddress, PORT); 

या कुछ एक जैसे

// read the data into the buffer 
recorder.read(buffer, 0, buffer.length); 

// place contents of buffer into the packet 
packet = new DatagramPacket(buffer, buffer.length, serverAddress, PORT); 

:

+0

में अनुमति इस विधि मैं करने के लिए एक से अधिक डिवाइस धारा हो सकता है का उपयोग करने के लिए महान मदद के लिए धन्यवाद एक ही बंदरगाह? यदि हां, तो मैं सर्वर की तरफ कौन सी स्ट्रीम अलग कर सकता हूं? –

उत्तर

7

यहाँ कुछ आप की कोशिश कर सकते बजाय, है।

+0

मैंने आपके द्वारा सुझाए गए परिवर्तन किए हैं लेकिन ऑडियो आउटपुट अभी भी मशीन गन की तरह लगता है। आप बता सकते हैं कि यह सही ऑडियो है, यह सिर्फ अंतराल है। हालांकि प्रतिक्रिया के लिए धन्यवाद! –

+2

इसके अतिरिक्त आप भी पढ़ने वाले डेटा पैकेट को बदलना चाहेंगे। कुछ समान रूप से: bufferAudioForPlayback (getPacket.getData(), getPacket.getOffset(), getPacket.getLength() प्राप्त करें। – harism

+1

धन्यवाद! वह, नमूना दर को 11025 में बदलने के साथ संयुक्त रूप से मुझे अंतराल, स्पष्ट प्लेबैक दिया। तुम अद्भुत हो, धन्यवाद! –

0

पद यहोशू .... नई मधुमक्खियों :)

volumeControl.setValue(volumeControl.getMaximum()); 

removes illegalStateException at Server 

और एंड्रॉयड ग्राहक

<uses-permission android:name="android.permission.RECORD_AUDIO"/> 
+2

कोड के इन स्निपेट कैसे प्लेबैक को रोकने की समस्या से संबंधित हैं? – MarsAtomic

संबंधित मुद्दे