Can system sleep while AudioRecord is recording?


Last Updated:

  1. alex

    alex New Member This Topic's Starter

    Joined:
    Sep 8, 2009
    Messages:
    2
    Likes Received:
    0
    Hi,
    I am new to Android and has been trying to find out if Android 1.5 on HTC magic is able to put system to sleep while collecting audio data through microphone.

    What I am trying to accomplish is to continously collecting audio (PCM 16bit at 8K Hz) from microphone as long as possible. I have tested with AudioRecord class and is able to record audio continously for 7 hours before battery running out. 7 hours is good but not enough.

    I noticed that during recording, although screen is turned off automatically, the system is never put into sleep mode. I wish sleep mode will allow recording go much longer. I found out by comparing SystemClock.uptimeMillis() and System.currentTimeMillis() before and after recording.

    However as I reviewed David Sparks presentation at Google I/O (Google I/O - Mastering the Android Media Framework). David suggested at the end of the presentation that system should be automatically go to sleep mode while AudioRecord is collecting data into the preconfigured buffer(1 M bytes in my example). There are two problems I was facing while trying a simple recording 8k PCM 16bit using buffer of 1 Mbytes.

    1. AudioRecord.setPositionNotificationPeriod() or AudioReocrd.setNotificationMarkerPosition() does not seem to work. I wish to periodically wake up to retrieve data by calling AudioRecord.read().
    However, I do not get call back at all as I configured. Eventually AudioRecord stopped when record buffer overflowed. Below is the code.


    2. With problem 1, I have to call AudioRecord.read() in a while loop from a separate thread. When I read(), the thread will block on the read() until read buffer is filled. During the block, I hope the system may go to sleep mode. My program works and audio data were successfully read but system never went to sleep during the block.

    I appreciate any help that either prove or disapprove my idea of putting system into sleep while recording audio continously.

    Alex




    public class AsyncAudioRecorder {

    public static final int DEFAULT_SAMPLE_RATE = 8000;
    private static final int DEFAULT_BUFFER_SIZE = 1000000;
    private static final int CALLBACK_PERIOD = 500;
    private final AudioRecord recorder;
    private int runningOffset = 0;
    byte[] bytes = new byte[DEFAULT_BUFFER_SIZE];
    private AsyncAudioRecorder(int sampleRate) {
    recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,
    sampleRate, AudioFormat.CHANNEL_CONFIGURATION_MONO,
    AudioFormat.ENCODING_PCM_16BIT, DEFAULT_BUFFER_SIZE);

    recorder.setRecordPositionUpdateListener(mNotification);
    int retval = recorder.setPositionNotificationPeriod(CALLBACK_PERIOD);
    Log.d("setPeriodNotificationPeriod",Integer.toString(retval));
    int notificationPeriod = recorder.getPositionNotificationPeriod();
    Log.d("getPeriodNotificationPeriod", Integer.toString(notificationPeriod));

    retval = recorder.setNotificationMarkerPosition(1000);
    Log.d("setNotificationMarkerPosition",Integer.toString(retval));
    int notificationMarker = recorder.getNotificationMarkerPosition();
    Log.d("getNotificationMarkerPosition", Integer.toString(notificationMarker));
    //read once, doesn't help
    int byteCount = recorder.read(bytes, 0, DEFAULT_BUFFER_SIZE);
    Log.d(this.getClass().getSimpleName(), "Bytes read: " + Integer.toString(byteCount));
    }
    public AudioRecord.OnRecordPositionUpdateListener mNotification = new
    AudioRecord.OnRecordPositionUpdateListener() {
    @Override
    public void onMarkerReached(AudioRecord argRecorder) {
    try{
    Log.d(this.getClass().getSimpleName(), "onMarkerReached Called");
    int byteCount = argRecorder.read(bytes, runningOffset, DEFAULT_BUFFER_SIZE);
    runningOffset = runningOffset + byteCount;
    Log.d(this.getClass().getSimpleName(), "Bytes read: " + Integer.toString(byteCount));
    }
    catch (Exception e){
    Log.e(this.getClass().getSimpleName(), "error in onMarkerReached");
    }
    }

    @Override
    public void onPeriodicNotification(AudioRecord argRecorder) {
    try
    {
    Log.d(this.getClass().getSimpleName(), "onPeriodicNotification Called");
    int byteCount = argRecorder.read(bytes, runningOffset, DEFAULT_BUFFER_SIZE);
    runningOffset = runningOffset + byteCount;
    Log.d(this.getClass().getSimpleName(), "Bytes read: " + Integer.toString(byteCount));
    }
    catch (Exception e){
    Log.e(this.getClass().getSimpleName(), "error in onPeriodicNotification");
    }
    }

    };

    public void start() {
    try{
    recorder.startRecording();
    }
    catch (Exception e)
    {
    Log.e(this.getClass().getSimpleName(), "Error while starting the recording!");
    }
    }

    public void stop() {
    try{
    recorder.stop();
    recorder.release();
    }
    catch (Exception e){
    Log.e(this.getClass().getSimpleName(), "Error while starting the recording!");
    }
    }

    }
     

    Advertisement
  2. Wanderer

    Wanderer New Member

    Joined:
    Feb 15, 2010
    Messages:
    1
    Likes Received:
    0
    I have exactly this problem now when implementing an Andoird App.

    Did you ever get to solve it?

    (I mean did you get the Callback actually called?)

    BTW, read() does not seems to put your thread to sleep, at least not on all Phones.
     
  3. alex

    alex New Member This Topic's Starter

    Joined:
    Sep 8, 2009
    Messages:
    2
    Likes Received:
    0
    AudioRecord will keep the system awake until recording is stopped. I think this depends on audio driver implementation. On G1 phone, the driver aquires wake lock when opening audio channel and release the wak lock when closing the audio channel. You can verify it on other platforms.

    I had problem with AudioRecord callback in 1.5 but not in 1.6 and after. Good luck.
     
  4. khushbu.shah

    khushbu.shah New Member

    Joined:
    Jan 4, 2011
    Messages:
    1
    Likes Received:
    0
    Did any one try code of sipdroid given in sipdroid - Project Hosting on SIP/VoIP client for Android. If yes than please help me. I have to read samples from microphone and send it to udp socket. For this I'm using AudioRecord class as given in RtpStreamSender.java and I have use read method to read the samples which is given below:
    public int read (byte[] audioData, int offsetInBytes, int sizeInBytes).This method reads audio data from the audio hardware for recording into a buffer.
    Its Parameters are :
    audioData :the array to which the recorded audio data is written.
    offsetInBytes: index in audioData from which the data is written expressed in bytes.
    sizeInBytes :the number of requested bytes.

    It Returns:
    the number of bytes that were read or or ERROR_INVALID_OPERATION if the object wasn't properly initialized, or ERROR_BAD_VALUE if the parameters don't resolve to valid data and indexes. The number of bytes will not exceed sizeInBytes.

    I have written this method in my code like this :
    int num;
    byte[] buf = new byte[160]; num = record.read(buf, 0, 160);

    The problem is that it always returns 160 (i.e. the requested byte to be read) not less than 160 even if the data is not available. I am getting voice sample from microphone and My sampling rate is 8000 Hz so 8000 samples per second encoding in 16 bit so to read 160 byte it requires at least 10 milliseconds but it send data at every 1 ms. If it is a blocking method than it should return the value 160 after reading 160 bytes. Why it returns maximum value even if it reads 10-20bytes ? what's the problem? please help me. Thanks in advance.
    My code is like :
    public void run()
    {
    running = true;
    int frame_size = 160;
    android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
    try
    {
    minBuffersize= AudioRecord.getMinBufferSize(8000, AudioFormat.CHANNEL_CONFIGURATION_MONO,AudioFormat.ENCODING_PCM_16BIT);
    Log.i(TAG, "trying to capture " + String.format("%d", frameSize) + " bytes");
    record = new AudioRecord(MediaRecorder.AudioSource.MIC, 8000, AudioFormat.CHANNEL_CONFIGURATION_MONO,AudioFormat.ENCODING_PCM_16BIT, 20000);
    record.startRecording();
    byte[] buffer = new byte[frameSize];
    while (running)
    {
    record.read(buffer, 0, frameSize);
    Log.i(TAG, "Captured " + String.format("%d", frameSize) + " bytes of audio");
    }
    }
    catch (Exception e)
    { Log.e(TAG, "Failed to capture audio"); }
    }
     

Share This Page

Loading...