Record audio from mic in pcm format using native code/librar

All your problems with Audio, Video and Images.

Record audio from mic in pcm format using native code/librar

Postby vishalgaonkar » Fri Oct 09, 2009 5:01 pm

Hello,

My application cannot handle the JNIE overhead, as I need to make 2 JNIE calls to the native C/C++ code for every 20msec. So I am trying to use the native media libraries and the realted C/C++ files provided by Android in the folder "//external/srec/audio/test" of the donut build. Ex. AudioHardwareRecord, AudioInRecord etc.. I am implementing all the calls in the native layer.

I am using the sampling rate as 8000 and want to read 160 samples (320 bytes) at a time.

I used the following values to create the AudioRecord..

record = new android::AudioRecord(
android::AudioRecord::MIC_INPUT, /* Input Source */
sampleRate, /* Sample Rate - 8000 */
android::AudioSystem::PCM_16_BIT, /* Format */
numChannels, /* Channel Count - 1 */
1, /* Frame Count */
android::AudioRecord::RECORD_AGC_ENABLE, /* Flags*/
NULL, /* Callback Function */
NULL, /* Context for use by the callback receiver*/
1 /* Notification Frames */ );

It says "success" after creating this interface but I am getting the error "Bad Value" if I am doing the InitCheck.

And it is crashing once I start reading the samples or if I try to retrieve the configured sampling rate.

Has anybody tried to access this native code? Any clue in this regard will be very helpful.

Thanks in advance.

Vishal Gaonkar
vishalgaonkar
Junior Developer
Junior Developer
 
Posts: 11
Joined: Wed Sep 23, 2009 10:03 am

Top

Postby vishalgaonkar » Fri Oct 09, 2009 5:05 pm

My Code Samples:

#define SAMPLING_RATE 8000
#define N_FRAMES_PER_BUFFER 1 /* low-level driver counts in terms of frames, not samples */
#define N_TUPLES_PER_FRAME 1 /* tuple: a set of samples (set of 1 if mono, set of 2 if stereo */
#define N_CHANNELS_PER_TUPLE 1 /* 1: mono; 2: stereo */
#define N_TUPLES_PER_BUFFER (N_FRAMES_PER_BUFFER * N_TUPLES_PER_FRAME)
#define N_SAMPLES_PER_BUFFER (N_TUPLES_PER_BUFFER * N_CHANNELS_PER_TUPLE)
#define N_SECONDS_TO_RECORD 10
#define N_SAMPLES_TO_RECORD (SAMPLING_RATE * N_SECONDS_TO_RECORD * N_CHANNELS_PER_TUPLE) /* 80000 = 8000 * 10 * 1 */

int AudioCap(void)
{
/* Audio record - Start */
short AudBuf[N_SAMPLES_TO_RECORD * 1];
int AudBufSize = 160;
int rc;
unsigned int i;

memset(AudBuf, 0, (N_SAMPLES_TO_RECORD * sizeof(short)));

rc = AudioSetInputFormat(SAMPLING_RATE, N_CHANNELS_PER_TUPLE);
if (rc != 0) {
LOGE("AudioSetInputFormat() Failed! RetVal: %d", rc);
exit(1);
}
else {
LOGE("AudioSetInputFormat() Success! RetVal: %d", rc);
}

rc = AudioOpen();
if (rc < 0) {
LOGE("AudioOpen() Failed! RetVal: %d", rc);
exit(1);
}
else {
LOGE("AudioOpen() Success! RetVal: %d", rc);
}

/*i = 0;
while (i <= N_SAMPLES_TO_RECORD - N_SAMPLES_PER_BUFFER)
{
rc = AudioRead(&(AudBuf[i]), N_FRAMES_PER_BUFFER);
if (rc > 0) {
i += (rc * N_TUPLES_PER_FRAME * N_CHANNELS_PER_TUPLE);
LOGE("AudioRead() Success");
}
else {
LOGE("ERROR: AudioRead() returns %d\n", rc);
}
}*/

rc = AudioRead(AudBuf, AudBufSize);
if (rc == AudBufSize) {
LOGE("AudioRead() Success! Read Samples: %d ", rc);
}
else {
LOGE("AudioRead() Error! Read Samples: %d ", rc);
}

rc = AudioClose();
if (rc != 0) {
LOGE("AudioClose() Failed! RetVal: %d", rc);
exit(1);
}
else {
LOGE("AudioClose() Success! RetVal: %d", rc);
}

return 0;
}



using namespace android;

extern "C"
{

static AudioRecord* record;
static int sampleRate;
static int numChannels;

typedef void (*callback_t)(int event, void* user, void *info);

int AudioSetInputFormat(int sample_rate, int channel_count)
{
sampleRate = sample_rate;
numChannels = channel_count;
LOGE ( "AudioSetInputFormat Success! SampleRate: %d, ChannelCount: %d ", sampleRate, numChannels );
return 0;
}

int AudioOpen(void)
{
int retVal = NO_ERROR;
unsigned int Val = 0;

record = new android::AudioRecord(
android::AudioRecord::MIC_INPUT, /* Input Source */
sampleRate, /* Sample Rate */
android::AudioSystem::PCM_16_BIT, /* Format */
numChannels, /* Channel Count */
1, /* Frame Count */
android::AudioRecord::RECORD_AGC_ENABLE, /* Flags */
NULL, /* Callback Function */
NULL, /* Context for use by the callback receiver */
1 /* Notification Frames */ );
if (!record) {
LOGE ( "AudioOpen->AudioRecord Failed! RetVal: 0x%x ", record );
return -1;
}
else {
LOGE ( "AudioOpen->AudioRecord Success! RetVal: 0x%x ", record );
}

retVal = record->set(
android::AudioRecord::MIC_INPUT, /* Input Source */
sampleRate, /* Sample Rate */
android::AudioSystem::PCM_16_BIT, /* Format */
numChannels, /* Channel Count */
1, /* Frame Count */
android::AudioRecord::RECORD_AGC_ENABLE, /* Flags */
NULL, /* Callback Function */
NULL, /* Context for use by the callback receiver */
1 /* Notification Frames */ );
if (retVal == NO_ERROR) {
LOGE ( "AudioOpen->set Success! retVal: %d ", retVal );
}
else if (retVal == INVALID_OPERATION) {
LOGE ( "AudioOpen->set Invalid Operation! retVal: %d ", retVal );
}
else if (retVal == BAD_VALUE) {
LOGE ( "AudioOpen->set Bad Value! retVal: %d ", retVal );
}
else if (retVal == NO_INIT) {
LOGE ( "AudioOpen->set Not Initialized! retVal: %d ", retVal );
}
else if (retVal == PERMISSION_DENIED) {
LOGE ( "AudioOpen->set Permission Denied! retVal: %d ", retVal );
}

retVal = record->initCheck();
if (retVal == NO_ERROR) {
LOGE ( "AudioOpen->initCheck Success! retVal: %d ", retVal );
}
else if (retVal == INVALID_OPERATION) {
LOGE ( "AudioOpen->initCheck Invalid Operation! retVal: %d ", retVal );
}
else if (retVal == BAD_VALUE) {
LOGE ( "AudioOpen->initCheck Bad Value! retVal: %d ", retVal );
}
else if (retVal == NO_INIT) {
LOGE ( "AudioOpen->initCheck Not Initialized! retVal: %d ", retVal );
}
else if (retVal == PERMISSION_DENIED) {
LOGE ( "AudioOpen->initCheck Permission Denied! retVal: %d ", retVal );
}

Val = record->latency();
LOGE ( "AudioOpen->latency! Latency: %d ms ", Val );

retVal = record->format();
LOGE ( "AudioOpen->format! Format: %d ", retVal );

retVal = record->channelCount();
LOGE ( "AudioOpen->channelCount! ChannelCount: %d ", retVal );

Val = record->frameCount();
LOGE ( "AudioOpen->frameCount! FrameCount: %d ", Val );

retVal = record->frameSize();
LOGE ( "AudioOpen->frameSize! FrameSize: %d ", retVal );

retVal = record->inputSource();
LOGE ( "AudioOpen->inputSource! InputSource: %d ", retVal );

Val = record->getSampleRate();
LOGE ( "AudioOpen->getSampleRate! SampleRate: %d ", Val );

retVal = record->start();
if (retVal == NO_ERROR) {
LOGE ( "AudioOpen->start Success! RetVal: %d ", retVal );
return 0;
}
else {
LOGE ( "AudioOpen->start Failed! RetVal: %d ", retVal );
return -1;
}
}

int AudioClose(void)
{
int retVal = NO_ERROR;
retVal = record->stop();
if (retVal == NO_ERROR) {
LOGE ( "AudioClose->stop Success! RetVal: %d ", retVal );
delete record;
return 0;
}
else {
LOGE ( "AudioClose->stop Failed! RetVal: %d ", retVal );
delete record;
return -1;
}
}

int AudioRead(short *buffer, int frame_count)
{
int n;
int nreq = frame_count * sizeof(short);

n = record->read(buffer, nreq);
if (n > 0) {
if (n != nreq) {
LOGE ( "AudioRead->read error! not enough data. Read bytes: %d ", n );
n /= sizeof(short);
}
else {
LOGE ( "AudioRead->read Success! Read bytes: %d ", n );
n /= sizeof(short);
}
}

return n;
}

} // extern "C"

Anything wrong in this approach?
vishalgaonkar
Junior Developer
Junior Developer
 
Posts: 11
Joined: Wed Sep 23, 2009 10:03 am

Postby vishalgaonkar » Fri Oct 16, 2009 1:33 pm

Have found the solution. It was an issue with "1, /* Frame Count */". It should be the number of samples you want to read at a time.
vishalgaonkar
Junior Developer
Junior Developer
 
Posts: 11
Joined: Wed Sep 23, 2009 10:03 am

Top

Return to Multimedia Problems

Who is online

Users browsing this forum: No registered users and 17 guests