0

I believe the major problem comes from the read method in MicrophoneManager but cant see where the problem is. My console output for bytesread is 0 (this is in the other class AudioTransmitter). It seems to me like its not streaming audio data since the data sent off is none changing and like I said bytes read is 0.

    public class MicrophoneManager{
    //  private     TargetDataLine   targetDataLine;
      private   float            sampleRate       = 8000.0F;    //8000,11025,16000,22050,44100
      private   int              sampleSizeInBits = 16;         //8,16
      private   int              channels         = 1;          //1,2
      private   boolean          signed           = true;       //true,false
      private   boolean          bigEndian        = false;      //true,false
      private   AudioFormat      audioFormat;
    //  private AudioRecord      audioRecord;
    //  private AudioInputStream ais;
      private static MicrophoneManager singletonMicrophoneManager = null;

      public AudioRecord audioRecord; 
      public int mSamplesRead; //how many samples read 
      public int buffersizebytes; 
      public int buflen; 
      public int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO; 
      public int audioEncoding = AudioFormat.ENCODING_PCM_16BIT; 
      public static byte[] buffer; //+-32767 
      public static final int SAMPPERSEC = 8000; //samp per sec 8000, 11025, 22050 44100 or 48000 


      public class MicrophoneManager{
//  private     TargetDataLine   targetDataLine;
  private   float            sampleRate       = 8000.0F;    //8000,11025,16000,22050,44100
  private   int              sampleSizeInBits = 16;         //8,16
  private   int              channels         = 1;          //1,2
  private   boolean          signed           = true;       //true,false
  private   boolean          bigEndian        = false;      //true,false
  private   AudioFormat      audioFormat;
//  private AudioRecord      audioRecord;
//  private AudioInputStream ais;
  private static MicrophoneManager singletonMicrophoneManager = null;

  public AudioRecord audioRecord; 
  public int mSamplesRead; //how many samples read 
  public int buffersizebytes; 
  public int buflen; 
  public int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO; 
  public int audioEncoding = AudioFormat.ENCODING_PCM_16BIT; 
  public static short[] buffer; //+-32767 
  public static final int SAMPPERSEC = 8000; //samp per sec 8000, 11025, 22050 44100 or 48000 


  public MicrophoneManager() { 
      System.out.println("Initializing");   
//      audioFormat = new AudioFormat(sampleRate,sampleSizeInBits,channels,signed,bigEndian);

//      audioRecord = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, (int) sampleRate, channels, AudioFormat.ENCODING_PCM_16BIT, buffersizebytes);

      buffersizebytes = AudioRecord.getMinBufferSize(SAMPPERSEC,channelConfiguration,audioEncoding); //4096 on ion 
      buffer = new short[buffersizebytes]; 
      buflen=buffersizebytes/2; 
      audioRecord = new AudioRecord(android.media.MediaRecorder.AudioSource.MIC,SAMPPERSEC, 
      channelConfiguration,audioEncoding,buffersizebytes); //constructor       
  }

  public static MicrophoneManager getMicrophoneManager() throws Exception {
      if (singletonMicrophoneManager == null) {
          singletonMicrophoneManager = new MicrophoneManager();
          singletonMicrophoneManager.initialize();
      }
      return singletonMicrophoneManager;
  }

  public void initialize() throws Exception {      
  }

  public void startAudioInput(){

      try { 
          audioRecord.startRecording(); 
          mSamplesRead = audioRecord.read(buffer, 0, buffer.length); 
          audioRecord.stop(); 
          } catch (Throwable t) { 
          // Log.e("AudioRecord", "Recording Failed"); 
              System.out.println("Error Starting audio input"+t);
          } 
  }

  public void stopAudioInput(){
      audioRecord.stop(); 
      System.out.println("Stopping audio input");         
  }

  public void finishAudioInput(){
      audioRecord.release(); 
      System.out.println("Finishing audio input");        
  }

  public boolean available() throws Exception {
      return true;
  }

  public int read(byte[] inBuf) throws Exception {
     return audioRecord.read(inBuf,0,inBuf.length);
  }    

}

AudioTransmitter:

public class AudioTransmitter extends Thread{

    private MicrophoneManager mm=null;
    private boolean transmittingAudio = false;
    private String host;
    private int port;
    private long id=0;
    boolean run=true;

    public AudioTransmitter(String host, int port, long id) {
        this.host = host;
        this.port = port;
        this.id = id;
        this.start();
    }

    public void run() {

        System.out.println("creating audio transmitter host "+host+" port "+port+" id "+id);

        TrustManager[] trustAllCerts = new TrustManager[]{
                new X509TrustManager() {
                    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                        return null;
                    }
                    public void checkClientTrusted(
                            java.security.cert.X509Certificate[] certs, String authType) {
                    }
                    public void checkServerTrusted(
                            java.security.cert.X509Certificate[] chain, String authType) {
                        for (int j=0; j<chain.length; j++)
                        {
                            System.out.println("Client certificate information:");
                            System.out.println("  Subject DN: " + chain[j].getSubjectDN());
                            System.out.println("  Issuer DN: " + chain[j].getIssuerDN());
                            System.out.println("  Serial number: " + chain[j].getSerialNumber());
                            System.out.println("");
                        }
                    }
                }
        };

        while (run) {
            if(transmittingAudio) {

                try {
                    if(mm==null) {
                        mm = new MicrophoneManager();
//                      mm.initialize();
                    }
                    SSLContext sc = SSLContext.getInstance("SSL");
                    sc.init(null, trustAllCerts, new java.security.SecureRandom());
                    SSLSocketFactory sslFact = sc.getSocketFactory();
                    SSLSocket socket = (SSLSocket)sslFact.createSocket(host, port);

                    socket.setSoTimeout(10000);
                    InputStream inputStream = socket.getInputStream();
                    DataInputStream in = new DataInputStream(new BufferedInputStream(inputStream));
                    OutputStream outputStream = socket.getOutputStream();
                    DataOutputStream os = new DataOutputStream(new BufferedOutputStream(outputStream));
                    PrintWriter socketPrinter = new PrintWriter(os);
                    BufferedReader br = new BufferedReader(new InputStreamReader(in));

//                  socketPrinter.println("POST /transmitaudio?patient=1333369798370 HTTP/1.0");
                    socketPrinter.println("POST /transmitaudio?id="+id+" HTTP/1.0");
                    socketPrinter.println("Content-Type: audio/basic");
                    socketPrinter.println("Content-Length: 99999");
                    socketPrinter.println("Connection: Keep-Alive");
                    socketPrinter.println("Cache-Control: no-cache");
                    socketPrinter.println();
                    socketPrinter.flush();

//                  in.read();

                    mm.startAudioInput();

                    int buffersizebytes = AudioRecord.getMinBufferSize(8000, AudioFormat.CHANNEL_CONFIGURATION_MONO,AudioFormat.ENCODING_PCM_16BIT); //4096 on ion 

                    System.out.println("audio started");
                    byte[] data = new byte[buffersizebytes];
                    while(transmittingAudio) {
                            //              byte[] data = new byte[mm.available()];
                            int bytesRead = mm.read(data);
                            os.write(data,0,bytesRead);
                            os.flush();
                            //              ca.transmitAxisAudioPacket(data);
//                          System.out.println("read "+data);
                            System.out.println("bytesRead "+bytesRead);
                            System.out.println("data "+Arrays.toString(data));
                    }
                    os.close();
                    mm.stopAudioInput();
                } catch (Exception e) {
                    System.out.println("excpetion while transmitting audio connection will be closed"+e);
                    transmittingAudio=false;
                }
            }
            else {
                try {
                Thread.sleep(1000);
                } catch (Exception e){
                    System.out.println("exception while thread sleeping"+e);}
            }
        }

    }

    public void setTransmittingAudio(boolean transmittingAudio) {
        this.transmittingAudio = transmittingAudio;
    }

    public void finished() {
        this.transmittingAudio = false;
        mm.finishAudioInput();
    }


}
owen gerig
  • 6,165
  • 6
  • 52
  • 91
  • You forgot the part that explains "something wrong" in details – zapl May 16 '12 at 18:38
  • "My console output for bytesread is 0" basically it doesnt seem like its reading anything. whenever i output the bytes being read from the stream they are static (always the same value). I dont understand why the read method feeds the returning value into the first argument and returns the length. So when i try to pull the data out i get nothing. – owen gerig May 16 '12 at 18:47
  • 1
    `mm.read(data)` reads the data into `data` and then `mm.getBuffer()` returns you some other buffer with some other data. `mm.read()` reading 0 could also mean that the recording was not started (and you stop it in the start function and read data into some buffer). – zapl May 16 '12 at 18:54
  • ok i see that now. originally i thought because mm.read() returns the length that data wasnt being set. so then why if i do System.out.println("read "+data); i get [B@4053c125 over and over again. is this an address and not the value? as well as the fact that bytesread is 0 when outputed, it kinda of seems like nothing is read – owen gerig May 16 '12 at 19:08
  • 1
    `data` is an object without a `toString` method defined. So it prints you the object id (`getClass().getName() + '@' + Integer.toHexString(hashCode())`). `Arrays.toString(data)` should print you the actual content. – zapl May 16 '12 at 19:12
  • data [0, 0, 0,... which is probably 1024 bytes all 0. And thats what i thought, its not getting any audio data – owen gerig May 16 '12 at 19:18

2 Answers2

3

You are calling

mSamplesRead = audioRecord.read(buffer, 0, buffersizebytes); 

There are a few problems with that.

audioRecord.read() wants the length of the array you are reading in to, not the size in bytes. You have set your encoding to 16 bit. You should really be doing something like:

new short[] buffer = short[1024]; // or whatever length you like
mSampleRead = audioRecord.read(buffer,0,buffer.length);

You are calling to read buffersizebytes but you set buffer = new byte[1024];. No particular reason to think buffersizebytes is the right number is there? You want a short[] array with 16 bit encoding, and you want the number of SAMPLES (not bytes) you read to be less than or equal to the length of that short[] buffer.

Also, you will be in better shape if you print out the exception you get when they are thrown, change

System.out.println("Error Starting audio input");

to

System.out.println("Error Starting audio input" + t);

and you will at least have a hint why android is throwing you in the dustbin.

mwengler
  • 2,738
  • 1
  • 19
  • 32
  • why do i want a short[]? because then when i go to stream those bytes my os.write does not like short[] it wants a byte[] array. Going to update code above to reflect the other changes you outlined. – owen gerig May 16 '12 at 20:11
  • audioRecord = new AudioRecord(android.media.MediaRecorder.AudioSource.MIC,SAMPPERSEC,channelConfiguration,audioEncoding,buffersizebytes); // should this be buffersizebytes or buffer.length? – owen gerig May 16 '12 at 20:17
  • I haven't checked it but it looks like you can use byte[]. Just remember that .read() you put in SAMPLES to read so you will need your byte[] array to be 2X as long as the number of samples you are requesting. The call to AudioRecord() constructor does want the buffersize in bytes. So you want it to be at least 2X as long as your reads will be unless you don't mind blocking on every reads until your read request is filled. If you are trying to do other things in this same thread you should avoid blocking, if you put this read in its own thread, you are fine with blocking. – mwengler May 17 '12 at 01:15
  • Read the documentation of AudioRecord. You can have byte[] in your read() function. What @mwengler said is very true though. http://developer.android.com/reference/android/media/AudioRecord.html – marienke Mar 05 '13 at 09:43
0

Thank you guys for you help however I found a better way to do whats needed (here). Here is the code. Notice this also uses http://www.devdaily.com/java/jwarehouse/android/core/java/android/speech/srec/UlawEncoderInputStream.java.shtml to convert the audio to ulaw

public class AudioWorker extends Thread
{ 
    private boolean stopped = false;

    private String host;
    private int port;
    private long id=0;
    boolean run=true;
    AudioRecord recorder;

    //ulaw encoder stuff
    private final static String TAG = "UlawEncoderInputStream";

    private final static int MAX_ULAW = 8192;
    private final static int SCALE_BITS = 16;

    private InputStream mIn;

    private int mMax = 0;

    private final byte[] mBuf = new byte[1024];
    private int mBufCount = 0; // should be 0 or 1

    private final byte[] mOneByte = new byte[1];
    ////
    /**
     * Give the thread high priority so that it's not canceled unexpectedly, and start it
     */
    public AudioWorker(String host, int port, long id)
    { 
        this.host = host;
        this.port = port;
        this.id = id;
        android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
//        start();
    }

    @Override
    public void run()
    { 
        Log.i("AudioWorker", "Running AudioWorker Thread");
        recorder = null;
        AudioTrack track = null;
        short[][]   buffers  = new short[256][160];
        int ix = 0;

        /*
         * Initialize buffer to hold continuously recorded AudioWorker data, start recording, and start
         * playback.
         */
        try
        {
            int N = AudioRecord.getMinBufferSize(8000,AudioFormat.CHANNEL_IN_MONO,AudioFormat.ENCODING_PCM_16BIT);
            recorder = new AudioRecord(AudioSource.MIC, 8000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, N*10);
            track = new AudioTrack(AudioManager.STREAM_MUSIC, 8000, 
                    AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, N*10, AudioTrack.MODE_STREAM);
            recorder.startRecording();
            track.play();
            /*
             * Loops until something outside of this thread stops it.
             * Reads the data from the recorder and writes it to the AudioWorker track for playback.
             */


            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            SSLSocketFactory sslFact = sc.getSocketFactory();
            SSLSocket socket = (SSLSocket)sslFact.createSocket(host, port);

            socket.setSoTimeout(10000);
            InputStream inputStream = socket.getInputStream();
            DataInputStream in = new DataInputStream(new BufferedInputStream(inputStream));
            OutputStream outputStream = socket.getOutputStream();
            DataOutputStream os = new DataOutputStream(new BufferedOutputStream(outputStream));
            PrintWriter socketPrinter = new PrintWriter(os);
            BufferedReader br = new BufferedReader(new InputStreamReader(in));

//          socketPrinter.println("POST /transmitaudio?patient=1333369798370 HTTP/1.0");
            socketPrinter.println("POST /transmitaudio?id="+id+" HTTP/1.0");
            socketPrinter.println("Content-Type: AudioWorker/basic");
            socketPrinter.println("Content-Length: 99999");
            socketPrinter.println("Connection: Keep-Alive");
            socketPrinter.println("Cache-Control: no-cache");
            socketPrinter.println();
            socketPrinter.flush();


            while(!stopped)
            { 
                Log.i("Map", "Writing new data to buffer");
                short[] buffer = buffers[ix++ % buffers.length];

                N = recorder.read(buffer,0,buffer.length);
                track.write(buffer, 0, buffer.length);

                byte[] bytes2 = new byte[buffer.length * 2];
                ByteBuffer.wrap(bytes2).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().put(buffer);

                read(bytes2, 0, bytes2.length);
//              os.write(bytes2,0,bytes2.length);
                os.write(bytes2,0,bytes2.length);

                System.out.println("bytesRead "+buffer.length);
                System.out.println("data "+Arrays.toString(buffer));
            }
            os.close();
        }
        catch(Throwable x)
        { 
            Log.w("AudioWorker", "Error reading voice AudioWorker", x);
        }
        /*
         * Frees the thread's resources after the loop completes so that it can be run again
         */
        finally
        { 
            recorder.stop();
            recorder.release();
            track.stop();
            track.release();
        }
    }

    /**
     * Called from outside of the thread in order to stop the recording/playback loop
     */

/**
 * Called from outside of the thread in order to stop the recording/playback loop
 */
public void close()
{ 
     stopped = true;
}
public void resumeThread()
{ 
     stopped = false;
     run();
}

    TrustManager[] trustAllCerts = new TrustManager[]{
            new X509TrustManager() {
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
                public void checkClientTrusted(
                        java.security.cert.X509Certificate[] certs, String authType) {
                }
                public void checkServerTrusted(
                        java.security.cert.X509Certificate[] chain, String authType) {
                    for (int j=0; j<chain.length; j++)
                    {
                        System.out.println("Client certificate information:");
                        System.out.println("  Subject DN: " + chain[j].getSubjectDN());
                        System.out.println("  Issuer DN: " + chain[j].getIssuerDN());
                        System.out.println("  Serial number: " + chain[j].getSerialNumber());
                        System.out.println("");
                    }
                }
            }
    };


    public static void encode(byte[] pcmBuf, int pcmOffset,
            byte[] ulawBuf, int ulawOffset, int length, int max) {

        // from  'ulaw' in wikipedia
        // +8191 to +8159                          0x80
        // +8158 to +4063 in 16 intervals of 256   0x80 + interval number
        // +4062 to +2015 in 16 intervals of 128   0x90 + interval number
        // +2014 to  +991 in 16 intervals of  64   0xA0 + interval number
        //  +990 to  +479 in 16 intervals of  32   0xB0 + interval number
        //  +478 to  +223 in 16 intervals of  16   0xC0 + interval number
        //  +222 to   +95 in 16 intervals of   8   0xD0 + interval number
        //   +94 to   +31 in 16 intervals of   4   0xE0 + interval number
        //   +30 to    +1 in 15 intervals of   2   0xF0 + interval number
        //     0                                   0xFF

        //    -1                                   0x7F
        //   -31 to    -2 in 15 intervals of   2   0x70 + interval number
        //   -95 to   -32 in 16 intervals of   4   0x60 + interval number
        //  -223 to   -96 in 16 intervals of   8   0x50 + interval number
        //  -479 to  -224 in 16 intervals of  16   0x40 + interval number
        //  -991 to  -480 in 16 intervals of  32   0x30 + interval number
        // -2015 to  -992 in 16 intervals of  64   0x20 + interval number
        // -4063 to -2016 in 16 intervals of 128   0x10 + interval number
        // -8159 to -4064 in 16 intervals of 256   0x00 + interval number
        // -8192 to -8160                          0x00

        // set scale factors
        if (max <= 0) max = MAX_ULAW;

        int coef = MAX_ULAW * (1 << SCALE_BITS) / max;

        for (int i = 0; i < length; i++) {
            int pcm = (0xff & pcmBuf[pcmOffset++]) + (pcmBuf[pcmOffset++] << 8);
            pcm = (pcm * coef) >> SCALE_BITS;

            int ulaw;
            if (pcm >= 0) {
                ulaw = pcm <= 0 ? 0xff :
                        pcm <=   30 ? 0xf0 + ((  30 - pcm) >> 1) :
                        pcm <=   94 ? 0xe0 + ((  94 - pcm) >> 2) :
                        pcm <=  222 ? 0xd0 + (( 222 - pcm) >> 3) :
                        pcm <=  478 ? 0xc0 + (( 478 - pcm) >> 4) :
                        pcm <=  990 ? 0xb0 + (( 990 - pcm) >> 5) :
                        pcm <= 2014 ? 0xa0 + ((2014 - pcm) >> 6) :
                        pcm <= 4062 ? 0x90 + ((4062 - pcm) >> 7) :
                        pcm <= 8158 ? 0x80 + ((8158 - pcm) >> 8) :
                        0x80;
            } else {
                ulaw = -1 <= pcm ? 0x7f :
                          -31 <= pcm ? 0x70 + ((pcm -   -31) >> 1) :
                          -95 <= pcm ? 0x60 + ((pcm -   -95) >> 2) :
                         -223 <= pcm ? 0x50 + ((pcm -  -223) >> 3) :
                         -479 <= pcm ? 0x40 + ((pcm -  -479) >> 4) :
                         -991 <= pcm ? 0x30 + ((pcm -  -991) >> 5) :
                        -2015 <= pcm ? 0x20 + ((pcm - -2015) >> 6) :
                        -4063 <= pcm ? 0x10 + ((pcm - -4063) >> 7) :
                        -8159 <= pcm ? 0x00 + ((pcm - -8159) >> 8) :
                        0x00;
            }
            ulawBuf[ulawOffset++] = (byte)ulaw;
        }
    }
    public static int maxAbsPcm(byte[] pcmBuf, int offset, int length) {
        int max = 0;
        for (int i = 0; i < length; i++) {
            int pcm = (0xff & pcmBuf[offset++]) + (pcmBuf[offset++] << 8);
            if (pcm < 0) pcm = -pcm;
            if (pcm > max) max = pcm;
        }
        return max;
    }

    public int read(byte[] buf, int offset, int length) throws IOException {
        if (recorder == null) throw new IllegalStateException("not open");

        // return at least one byte, but try to fill 'length'
        while (mBufCount < 2) {
            int n = recorder.read(mBuf, mBufCount, Math.min(length * 2, mBuf.length - mBufCount));
            if (n == -1) return -1;
            mBufCount += n;
        }

        // compand data
        int n = Math.min(mBufCount / 2, length);
        encode(mBuf, 0, buf, offset, n, mMax);

        // move data to bottom of mBuf
        mBufCount -= n * 2;
        for (int i = 0; i < mBufCount; i++) mBuf[i] = mBuf[i + n * 2];

        return n;
    }

}
Community
  • 1
  • 1
owen gerig
  • 6,165
  • 6
  • 52
  • 91