1

I am sorry if this is a trivial question but I am new in Android and have spent a few days searching but there is no answer or information satisfies me.

I want to record an audio record of length approximately 3 seconds for every 30 seconds by using an Android phone. Every record is sent to my PC (using TCP/IP protocol) for further processing.

Here is the code in Android side (I refer to the code of @TechEnd in this question: Android AudioRecord example):

private final int AUD_RECODER_SAMPLERATE = 44100; // 44.1 kHz
private final int AUD_RECORDER_CHANNELS = AudioFormat.CHANNEL_IN_MONO;
private final int AUD_RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;
private final int AUD_RECORDER_BUFFER_NUM_ELEMENTS = 131072; // ~~ 1.486 second ???
private final int AUD_RECORDER_BUFFER_BYTES_PER_ELEMENT = 2;

private AudioRecord audioRecorder = null;
private boolean isAudioRecording = false;
private Runnable runnable = null;
private Handler handler = null;
private final int AUD_RECORDER_RECORDING_PERIOD = 30000; // one fire every 30 seconds

private byte[] bData = new byte[AUD_RECORDER_BUFFER_NUM_ELEMENTS*AUD_RECORDER_BUFFER_BYTES_PER_ELEMENT];

public void start() {
    audioRecorder = new AudioRecord(MediaRecorder.AudioSource.MIC, AUD_RECODER_SAMPLERATE, AUD_RECORDER_CHANNELS, AUD_RECORDER_AUDIO_ENCODING, AUD_RECORDER_BUFFER_NUM_ELEMENTS*AUD_RECORDER_BUFFER_BYTES_PER_ELEMENT);
    audioRecorder.startRecording();
    isAudioRecording = true;

    handler = new Handler();
    runnable = new Runnable() {
        @Override
        public void run() {
            if (isAudioRecording) {
                int nElementRead = audioRecorder.read(bData, 0, bData.length);
                net_send(bData, 0, nElementRead);
            }
            handler.postDelayed(this, AUD_RECORDER_RECORDING_PERIOD);
        }
    };
    handler.postDelayed(runnable, AUD_RECORDER_RECORDING_PERIOD);
}

public void stop() {
    isAudioRecording = false;
    if (audioRecorder != null) {
        audioRecorder.stop();
        audioRecorder.release();
        audioRecorder = null;
    }
    handler.removeCallbacks(runnable);
}

public void net_send(byte[] data, int nbytes) {
    try {
        dataOutputStream.writeInt(nbytes);
        dataOutputStream.write(data,0,nbytes);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

And in PC side (server written in C), after receive a record (I checked and they are all 262144 bytes), I first write the byte array to a binary file (with extension .raw) and open with Free Audio Editor (http://www.free-audio-editor.com/) and obtain the result with duration 1.486 seconds https://www.dropbox.com/s/xzml51jzvagl6dy/aud1.PNG?dl=0

And then I convert every two consecutive bytes into a 2-bytes integer using this function

short bytes2short( const char num_buf[2] )
{
    return( 
        ( ( num_buf[1] & 0xFF ) << 8 ) | 
          ( num_buf[0] & 0xFF )
    );
}

and write to file (length is 131072 bytes) and plot (the normalized one) with Excel, the similar graph is obtained.

As I calculated, the number of bytes recorded in one second is 44100(sample/sec)*1(sec)*2(byte/sample/channel)*1(channel) = 88200 bytes. So with my buffer of length 131072*2 (bytes), the corresponding duration should be 262144/88200 = 2.97 seconds. But the result I obtain is just a half. I tried on three different devices running Android OS version 2.3.3, 2.3.4 and 4.3 and obtain the same result. Thus, this is my own problem.

Could anyone tell me where is the problem, in my calculation or in my code? I my understanding is correct? Any comments or suggestion would be appreciated.

Community
  • 1
  • 1
vdo
  • 11
  • 2

0 Answers0