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
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 type of approach?
Thanks in advance,
Vishal
Last edited by vishal.android; 10-14-2009 at 05:17 AM.
hi.
i'd like to help, but this is really more of a user forum than a developer forum.
you're more likely to get an answer at http://forum.xda-developers.com/forumdisplay.php?f=446
...or some other android app dev forum.
Bookmarks