java - एंड्रॉइड ऑडियो रिकॉर्डॉर्ड क्लास-लाइव माइक्रो ऑडियो को जल्दी से संसाधित करें, कॉलबैक फ़ंक्शन सेट करें
android audiorecord (3)
नोटिफिकेशन के साथ बहुत कुछ प्रयोग करने और अन्य तकनीकों का एक समूह मैंने इस कोड पर बसने के बाद:
private class AudioIn extends Thread {
private boolean stopped = false;
private AudioIn() {
start();
}
@Override
public void run() {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
AudioRecord recorder = null;
short[][] buffers = new short[256][160];
int ix = 0;
try { // ... initialise
int N = AudioRecord.getMinBufferSize(8000,AudioFormat.CHANNEL_IN_MONO,AudioFormat.ENCODING_PCM_16BIT);
recorder = new AudioRecord(AudioSource.MIC,
8000,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT,
N*10);
recorder.startRecording();
// ... loop
while(!stopped) {
short[] buffer = buffers[ix++ % buffers.length];
N = recorder.read(buffer,0,buffer.length);
//process is what you will do with the data...not defined here
process(buffer);
}
} catch(Throwable x) {
Log.w(TAG,"Error reading voice audio",x);
} finally {
close();
}
}
private void close() {
stopped = true;
}
}
अब तक यह आधे दर्जन एंड्रॉइड फोन पर काफी मजबूत काम कर रहा है जिस पर मैंने कोशिश की है।
मैं mic से ऑडियो रिकॉर्ड करना चाहता हूं और वास्तविक रीयल-टाइम में संभावित प्लेबैक के लिए इसे एक्सेस करना चाहता हूं। मैं कुछ माइक्रो ऑडियो रिकॉर्ड करने और इसे तुरंत एक्सेस करने के लिए एंड्रॉइड ऑडियो रिकॉर्डॉर्ड क्लास का उपयोग करने के बारे में अनिश्चित हूं।
ऑडियो रिकॉर्डॉर्ड क्लास के लिए, आधिकारिक साइट कहती है कि 'ऐप चुनाव में ऑडियो रिकॉर्डॉर्ड ऑब्जेक्ट का चुनाव करता है' और 'बफर का आकार भरने से पहले अपठित डेटा चलाने से पहले रिकॉर्डिंग की समय-सीमा निर्धारित करता है'। बाद में यह सुझाव दिया गया है कि कम बार मतदान करते समय एक बड़ा बफर इस्तेमाल किया जाना चाहिए। वे वास्तव में कोड में एक उदाहरण कभी नहीं दिखाते हैं।
एक पुस्तक में मैंने देखा है कि एक उदाहरण ऑडियो रिकॉर्डर क्लास का उपयोग लाइव माइक्रो ऑडियो के साथ ताजा आबादी वाले बफर को लगातार पढ़ने के लिए करता है, और फिर ऐप इस डेटा को एक एसडी फाइल में लिखता है। छद्म कोड कुछ ऐसा दिखता है -
set up AudioRecord object with buffer size and recording format info
set up a file and an output stream
myAudioRecord.startRecording();
while(isRecording)
{
// myBuffer is being filled with fresh audio
read audio data into myBuffer
send contents of myBuffer to SD file
}
myAudioRecord.stop();
यह कोड रिकॉर्डिंग की दर के साथ अपने पढ़ने को सिंक्रनाइज़ कैसे करता है अस्पष्ट है - क्या बूलियन "isRecording" कहीं और ठीक से अनुक्रमित है? ऐसा लगता है कि यह कोड या तो पढ़ने या लिखने में कितना समय लगता है, इस पर निर्भर करता है कि यह अक्सर बहुत बार या बहुत बार पढ़ा जा सकता है।
साइट डॉक में यह भी कहा गया है कि ऑडियो रिकॉर्डॉर्ड क्लास में एक नेस्टेड क्लास है जिसे ऑनरकोर्डपोशनअपडेट लिस्टनर नाम दिया गया है जिसे इंटरफ़ेस के रूप में परिभाषित किया गया है। सूचना से पता चलता है कि किसी भी तरह, आप रिकॉर्डिंग की प्रगति के अधिसूचित होने के लिए इच्छित अवधि निर्दिष्ट करते हैं, और आपके ईवेंट हैंडलर का नाम, और निर्दिष्ट आवृत्ति पर आपके ईवेंट हैंडलर को स्वचालित रूप से कॉल किया जाता है। मुझे लगता है कि संरचना, छद्म कोड में कुछ ऐसा होगा -
set target of period update message = myListener
set period to be about every 250 ms
other code
myListener()
{
if(record button was recently tapped)
handle message that another 250 ms of fresh audio is available
ie, read it and send it somewhere
)
मुझे कुछ विशिष्ट कोड खोजने की ज़रूरत है जो मुझे 500 एमएस से कम की देरी के साथ माइक्रो ऑडियो को कैप्चर और प्रोसेस करने की अनुमति देता है। एंड्रॉइड MediaRecorder नामक एक और वर्ग प्रदान करता है, लेकिन यह स्ट्रीमिंग का समर्थन नहीं करता है, और मैं लाइव रीयल-टाइम में वाई-फाई नेटवर्क पर लाइव माइक्रो ऑडियो स्ट्रीम करना चाहता हूं। मुझे कुछ विशिष्ट उदाहरण कहां मिल सकते हैं?
मुझे आश्चर्य है कि क्या आप इन उत्तरों को निम्न तरीके से जोड़ सकते हैं ...
जबकि लूप से पहले setPositionNotificationPeriod (160) का उपयोग करें। 160 फ्रेम पढ़ने के दौरान हर बार कॉलबैक को कॉल करने का कारण बनना चाहिए। थ्रेड के अंदर प्रक्रिया (बफर) को कॉल करने के बजाय जो रीड लूप कर रहा है, कॉलबैक से कॉल प्रक्रिया (बफर)। अंतिम पढ़ने वाले बफर का ट्रैक रखने के लिए एक चर का उपयोग करें ताकि आप सही प्रक्रिया कर सकें। जैसा कि अब है, आप पढ़ने पर अवरुद्ध करते हैं, फिर आप प्रसंस्करण करते समय पढ़ नहीं रहे हैं। मुझे लगता है कि उन दोनों को अलग करना बेहतर हो सकता है।
private int freq =8000;
private AudioRecord audioRecord = null;
private Thread Rthread = null;
private AudioManager audioManager=null;
private AudioTrack audioTrack=null;
byte[] buffer = new byte[freq];
//call this method at start button
protected void Start()
{
loopback();
}
protected void loopback() {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
final int bufferSize = AudioRecord.getMinBufferSize(freq,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT);
audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, freq,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
MediaRecorder.AudioEncoder.AMR_NB, bufferSize);
audioTrack = new AudioTrack(AudioManager.ROUTE_HEADSET, freq,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
MediaRecorder.AudioEncoder.AMR_NB, bufferSize,
AudioTrack.MODE_STREAM);
audioTrack.setPlaybackRate(freq);
final byte[] buffer = new byte[bufferSize];
audioRecord.startRecording();
Log.i(LOG_TAG, "Audio Recording started");
audioTrack.play();
Log.i(LOG_TAG, "Audio Playing started");
Rthread = new Thread(new Runnable() {
public void run() {
while (true) {
try {
audioRecord.read(buffer, 0, bufferSize);
audioTrack.write(buffer, 0, buffer.length);
} catch (Throwable t) {
Log.e("Error", "Read write failed");
t.printStackTrace();
}
}
}
});
Rthread.start();
}
यह 100 एमएस देरी से कम दर्ज ऑडियो चलाता है।