Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Wednesday, January 1, 2014

How to: Record audio from MIC and save raw PCM values into a file (in Android)

Note: I have been working on some audio processing related projects at work and thought I could share some code which others find useful. This one is the first in the series. Please let me know if you find this useful; I can do share more reusable code.
First thing to remember is that it is better to run the audio recording code in a background thread or in an AysnTask. You can set the priority of that thread to THREAD_PRIORITY_URGENT_AUDIO.
Below is the code snippet; code is pretty self-explanatory.

public static final int SAMPLING_RATE = 44100;
public static final int AUDIO_SOURCE = MediaRecorder.AudioSource.MIC;
public static final int CHANNEL_IN_CONFIG = AudioFormat.CHANNEL_IN_MONO;
public static final int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
public static final int BUFFER_SIZE = AudioRecord.getMinBufferSize(SAMPLING_RATE, CHANNEL_IN_CONFIG, AUDIO_FORMAT);
public static final String AUDIO_RECORDING_FILE_NAME = "recording.raw";

@Override
public void run() {
    android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
    Log.v(LOGTAG, "Starting recording…");

    byte audioData[] = new byte[BUFFER_SIZE];
    AudioRecord recorder = new AudioRecord(AUDIO_SOURCE,
                SAMPLING_RATE, CHANNEL_IN_CONFIG,
                AUDIO_FORMAT, BUFFER_SIZE);
    recorder.startRecording();

    String filePath = Environment.getExternalStorageDirectory().getPath()
                + "/" + AUDIO_RECORDING_FILE_NAME;
    BufferedOutputStream os = null;
    try {
        os = new BufferedOutputStream(new FileOutputStream(filePath));
    } catch (FileNotFoundException e) {
        Log.e(LOGTAG, "File not found for recording ", e);
    }

    while (!mStop) {
        int status = recorder.read(audioData, 0, audioData.length);

        if (status == AudioRecord.ERROR_INVALID_OPERATION ||
            status == AudioRecord.ERROR_BAD_VALUE) {
            Log.e(LOGTAG, "Error reading audio data!");
            return;
        }

        try {
            os.write(audioData, 0, audioData.length);
        } catch (IOException e) {
            Log.e(LOGTAG, "Error saving recording ", e);
            return;
        }
    }

    try {
        os.close();

        recorder.stop();
        recorder.release();

        Log.v(LOGTAG, "Recording done…");
        mStop = false;

    } catch (IOException e) {
        Log.e(LOGTAG, "Error when releasing", e);
    }
}

You will need to add the following permissions in AndroidManifest.xml.
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

Friday, August 10, 2012

JNI : Step-by-step tutorial on OS X with GCC

Here is a simple step-by-step tutorial to write a sample JNI application on Mac OS X using gcc compiler.
Stand alone GCC  (i.e, without Xcode) can be installed from here.

Step 1: Write the java code

public class JniSample {

   public native int sayHello();

   public static void main(String[] args) {

       System.loadLibrary("JniSample");
       System.out.println("In java main");

       JniSample s = new JniSample();
       s.sayHello();
   }
}

Step 2: Compile the java code

$ javac JniSample.java

Step 3: Create the header file

$ jahah JniSample

It looks like:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class JniSample */

#ifndef _Included_JniSample
#define _Included_JniSample
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:     JniSample
* Method:    sayHello
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_JniSample_sayHello
 (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

Step 4: Write C code

#include <stdio.h>
#include "JniSample.h"

JNIEXPORT jint JNICALL Java_JniSample_sayHello (JNIEnv *env, jobject obj) {
 printf("Hello World\n");
 return 0;
}

Step 5: Compile C code and create native library

$ cc -v -c -fPIC -I/System/Library/Frameworks/JavaVM.framework/Versions/A/Headers/ JniSample.c -o libJniSample.o
$ libtool -dynamic -lSystem libJniSample.o -o libJniSample.dylib

Step 6: Set LD_LIBRARY_PATH env variable:

$ LD_LIBRARY_PATH=.
$ export $LD_LIBRARY_PATH

Step 7: Run

$ java JniSample
In java main
Hello World