第一次安卓開發,初次體會到如此深刻的版本差異。
我的AudioRecord代碼在三星S5670測試成功。
小米,朵唯D210T測試失敗。錯誤資訊如下:
04-01 12:58:44.368: E/AudioRecord(19808): Could not get audio input for record source 1
04-01 12:58:44.368: E/AudioRecord-JNI(19808): Error creating AudioRecord instance: initialization check failed.
04-01 12:58:44.368: E/AudioRecord-Java(19808): [ android.media.AudioRecord ] Error code -20 when initializing native AudioRecord object.
網上的相關資料整理在此:
You problem here is probably actually twofold. First, you have to get all of the parameters just right for the AudioRecord, ie, I can see that you tried all the various sampling rates and channel configurations, but did you try different bit depths? If you don't get it all just right, it doesn't work. Furthermore, it would appear that some android devices seem to report the wrong minBufferSize.
After using audio recorder, you must stop and release it. Then when you init the audio recorder the next time, it's ok.
Had the same error, till I restarted the device.
It seems that on my Galaxy S the native impl is buggy: several times acquiring and releasing anAudioRecorder (during whole phone uptime) causes that error.
For me, the cause was failure to call AudioRecord.release() for a previous instance of AudioRecord; it tied up native resources in AudioFlinger and interfered with subsequent AudioRecord instances. Saw it on a Samsung Fascinate (Galaxy S) Android 2.1 (Eclair); either the Eclair or the Samsung implementation may be particularly intolerant.
×
You are now talking to an expert. The transcript of your session will be available online.
Expert: Hi, are also trying to handle the buffer?
You: no,
Expert: Noted.
You: I faced the problem of AudioRecord
Expert: Well said.
You: 04-01 12:58:44.368: E/AudioRecord(19808): Could not get audio input for record source 1 04-01 12:58:44.368: E/AudioRecord-JNI(19808): Error creating AudioRecord instance: initialization check failed.
Expert: I wonder if people who want to process of microphone input have similar problems.
You: yeah
Expert: Okay.
You: the strange thing is,
Expert: We're talking past each other here.
You: it just happens on some phones
Expert: What is "it" in that case?
You: the error
Expert: O... kay...
Expert: Maybe you could attempt to create tuner.
Expert: Why do you want to know?
You: i am trying to work out a tuner
Expert: You're not the only one who is trying to work out a tuner.
You: i see
Expert: Whatever you say.
You: i will google and have a try
Expert: Are you trolling me?
You: just now, i searched in chinese, with nothing useful
Expert: I once tried to instantiate activity componentinfo, it worked remarkably well.
You: my program works well on my phone, but fails on my classmates'
Expert:
You: could u tell your email to me?
Expert: Can you rephrase that?
You: sorry, what is "rephase"? record?
Expert: Why do you want to know?
You: I am working on a tunner
Expert: Oh really? I'm kind of working on a tunner myself.
You: and i want to get the main f of the input sound
Expert: Do you know anyone who could help you get the main f of the input sound?
You: i have already finished it with matlab
Expert: Well, then you know who to ask.
You: i just can not get the sound from microphone with some cellphones
Expert: Hey, would you like to be recording in android instead?
You: i want to work on realtime
Expert: It takes a lot of resources to work on realtime. Just sayin'.
You: yeah
Expert: No matter what?
You: in my mind, when tuning an instrument, it will be more convinent if it is realtime
Expert: I thought so.
You: r u in the US?
Expert: So we've given up on getting the main f of the input sound?
You: absolutely not
Expert: If you really want to get the sound with some cellphones from microphone, you have to start working now.
You: ok, i'v got someone that has the same question with me
Expert: About working on realtime -- what have you tried so far?
You: fft
Expert: While we're on the topic, recording with audiorecord on android speeds is a pretty interesting challenge.
You: my program has the f delay for about 1s
Expert: You don't say.
The trick with using AudioRecord is that each device may have different initialization settings, so you will have to create a method that loops over all possible combinations of bit rates, encoding, etc.
Since the buffer size for recording is limited, once your "analyzing process" is slower than the rate of recording, the data in the buffer will be stuck, but the recording bytes are always coming thus buffer overflows.
As we discussed in the chat room, decoding the audio data and displaying it on the screen should be straightforward. You mentioned that the audio buffer has 8000 samples per second, each sample is 16 bit, and it's mono audio.
Displaying this should be straightforward. Treat each sample as a vertical offset in your view. You need to scale the range -32k to +32k to the vertical height of your view. Starting at the left edge of the view, draw one sample per column. When you reach the right edge, wrap around again (erasing the previous line as necessary).
This will end up drawing each sample as a single pixel, which may not look very nice. You can also draw a line between adjacent samples. You can play around with line widths, colors and so on to get the best effect.
One last note: You'll be drawing 8000 times per second, plus more to blank out the previous samples. You may need to take some shortcuts to make sure the framerate can keep up with the audio. You may need to skip samples.
Well, after spending my free time for the last 5 days working on theAudioRecord class I´m here again to post my findings.
But first let me make myself clear:
- What I´m about to write is the result of my tests and findings after having a lot of trouble to use the basic routines of the class. I found a lot of forums posts over the internet about the same problems so my idea here is to help people so they don´t face the same problems I´ve faced.
- It may be beginner´s stuff, but a lot of people have faced or are
facing the same problems.
- If something here is wrong please don´t come here just to say it,
share your knowledge with us and post not only what´s wrong but how to
do it right.
- I´ve done all tests on the EMULATOR provided by google. Also I´m
using the sdk 2.1 (build 7)
Ok, let´s go.
Creating an AudioRecord object:
When you create a new instance of AudioRecord there are two ways of
finding out if it was created properly (the device can handle the
audio parameters and resources were trully allocated to your object):
by catching an exception or by verifying the return of the getState()
method.
- Handling the IllegalArgumentException : Well, tricky is what I can
say. Exceptions will only be thrown if any of the parameters you have
used are NOT acceptable by the CLASS (not if the device can´t handle
it). For example, a sample rate = 12345 is not a standard value and
then the class will throw an exception. If SR = 44100 is not supported
by the DEVICE, the object will be created and no exception will be
launched.
* An interesting thing is that the official documentation says:
"sampleRateInHz the sample rate expressed in Hertz. Examples of rates
are (but not limited to) 44100, 22050 and 11025."
If you try SR = 11025 the system will throw an exception as it
considers this an illegal parameter. Strange, huh?
- Then ok, you have created an instance of AudioRecord but you don´t
know if the parameters you have set are available in an specific
device. What you do? Verify AudioRecord.getState(), right?
Ok then, it works. But if you find out your instance is not ok and
then you have to create a new AudioRecord object you will be in
trouble. Why? Even after running AudioRecord.release() the resources
for the audio input you are interested in will keep being in use and
you won´t be abble to recreate your object in a way it would work.
To verify this create an instace of AudioRecord with parameters that
are known not to work on the emulator (ex. SR = 44100). Then verify
the errors on logcat. After that call release() and then try to create
another instance of AudioRecorder with the parameters that work (sr =
8000, mono channel, pcm 16 bits) and check the first error line.
Then how should you find out which parameters the device will allow
you to use? Say with me: AudioRecord.getMinBufferSize() is my
solution!
Loop checking from the best combination of parameters to the worst. If
it returns -2, you should try another combination, if it returns -1
the audio input source is already being in use or isn´t even available
for the specific device. If it returns something > 0 then you´re ok
and can proceed creating a new AudioRecord object.
AudioRecord notification:
YES, IT WORKS! Believe me. The trick is: the notification will only be
called AFTER you call read() for the first time! And not only one time
(Oo). After a periodic notification you need to read from the audio
buffer again to receive another notification. A marker notification
will be called only once: if you need it to be called again, set the
marker again!
I guess it covers the basics.
Good luck and believe me, android is great!
Gabriel Simões
解決方案:
朵唯D210T的解決方案為修改AudioRecord建構函式的sample rate。當使用4000的sample rate時,無法構造成功。而當我採用8000的sample rate時即可採集成功。