
本文共 10449 字,大约阅读时间需要 34 分钟。
Android ������ AudioRecord.read ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� AudioRecord.read ������������������������������
1. AudioRecord.read ������������
Java ���������
Java ������ read
��������������� native_read_in_byte_array
��������������������������������� buffer ������������������������������������������������������ byte���short���float���ByteBuffer��������������������������������� JNI ������������������ Java ������������������ native ���������������������������readMode ���������������������������READ_BLOCKING��������������� READ_NON_BLOCKING������������������
���������������
public int read(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes) { return read(audioData, offsetInBytes, sizeInBytes, READ_BLOCKING);}public int read(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes, @ReadMode int readMode) { // ������������ if (mState != STATE_INITIALIZED || mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT) { return ERROR_INVALID_OPERATION; } // ������ readMode ������������ if ((readMode != READ_BLOCKING) && (readMode != READ_NON_BLOCKING)) { return ERROR_BAD_VALUE; } // ��������������������� if (audioData == null || offsetInBytes < 0 || sizeInBytes < 0 || (offsetInBytes + sizeInBytes) < 0 || (offsetInBytes + sizeInBytes) > audioData.length) { return ERROR_BAD_VALUE; } // ������ native ������ return native_read_in_byte_array(audioData, offsetInBytes, sizeInBytes, readMode == READ_BLOCKING);}// ��������� JNI ������templatestatic jint android_media_AudioRecord_readInArray(JNIEnv *env, jobject thiz, T javaAudioData, jint offsetInSamples, jint sizeInSamples, jboolean isReadBlocking) { // ������ AudioRecord ������ sp lpRecorder = getAudioRecord(env, thiz); if (lpRecorder == null) { return (jint)AUDIO_JAVA_INVALID_OPERATION; } // ������������������������������ if (javaAudioData == null) { return (jint)AUDIO_JAVA_BAD_VALUE; } // ������������������ auto *recordBuff = envGetArrayElements(env, javaAudioData, null); if (recordBuff == null) { return (jint)AUDIO_JAVA_BAD_VALUE; } // ������������������������ size_t sizeInBytes = sizeInSamples * sizeof(*recordBuff); ssize_t readSize = lpRecorder->read(recordBuff + offsetInSamples, sizeInBytes, isReadBlocking ? JNI_TRUE : JNI_FALSE); // ������������������ envReleaseArrayElements(env, javaAudioData, recordBuff, 0); if (readSize < 0) { return (jint)interpretReadSizeError(readSize); } return (jint)(readSize / sizeof(*recordBuff));}
C++ ���������
C++ ������ read
��������������������� audioBuffer
������������������������������������������������������������ buffer
������
���������������
ssize_t AudioRecord::read(void* buffer, size_t userSize, bool blocking) { // ������������������������������ if (mTransfer != TRANSFER_SYNC) { return INVALID_OPERATION; } if (userSize < 0 || (buffer == null && userSize != 0)) { return BAD_VALUE; } // ������������������ userSize ������ mFrameSize ssize_t read = 0; Buffer audioBuffer; while (userSize >= mFrameSize) { audioBuffer.frameCount = userSize / mFrameSize; status_t err = obtainBuffer(&audioBuffer, blocking ? &ClientProxy::kForever : &ClientProxy::kNonBlocking); if (err < 0) { // ������������������ if (read > 0) { break; } if (err == TIMED_OUT || err == -EINTR) { err = WOULD_BLOCK; } return (ssize_t)err; } // ��������������������� buffer size_t bytesRead = audioBuffer.size; memcpy(buffer, audioBuffer.i8, bytesRead); buffer = ((char*)buffer) + bytesRead; userSize -= bytesRead; read += bytesRead; releaseBuffer(&audioBuffer); } // ��������������������������� if (read > 0) { mFramesRead += read / mFrameSize; } return read;}
obtainBuffer ������������ obtainBuffer
��������������� AudioRecord
��������������������������������������������������������������������������������� AudioTrack
��� obtainBuffer
���������������������������������������������������
���������������
status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, const struct timespec* requested, struct timespec* elapsed, size_t* nonContig) { // ������������ AutoMutex lock(mLock); // ��������������������������������������������� uint32_t oldSequence = 0; uint32_t newSequence; Proxy::Buffer buffer; status_t status = NO_ERROR; static const int32_t kMaxTries = 5; int32_t tryCounter = kMaxTries; do { // ������ AudioTrackClientProxy ������ spproxy = mProxy; // ������������������������ sp iMem = mCblkMemory; sp bufferMem = mBufferMemory; AutoMutex lockScope; // ������������ newSequence = mSequence; if (status == DEAD_OBJECT) { // ������������������������������������ if (newSequence == oldSequence) { // ������������������ status = restoreRecord_l("obtainBuffer"); if (status != NO_ERROR) { buffer.mFrameCount = 0; buffer.mRaw = null; buffer.mNonContig = 0; break; } } } oldSequence = newSequence; // ������ proxy ������ proxy = mProxy; // ��������������� if (!mActive) { requested = &ClientProxy::kNonBlocking; } // ������������������ buffer.mFrameCount = audioBuffer->frameCount; // ������ AudioTrackClientProxy::obtainBuffer status = proxy->obtainBuffer(&buffer, requested, elapsed); } while ((status == DEAD_OBJECT) && (tryCounter-- > 0)); // ������ audioBuffer ��������� audioBuffer->frameCount = buffer.mFrameCount; audioBuffer->size = buffer.mFrameCount * mFrameSize; audioBuffer->raw = buffer.mRaw; if (nonContig != null) { *nonContig = buffer.mNonContig; } return status;}
.obtainBuffer ������������
AudioRecord
������������������������������������������������������������AudioTrackClientProxy
��� obtainBuffer
���������������������������������������audioBuffer
��������������� frameCount
���size
��� raw
���DEAD_OBJECT
������������������������������������������2. AudioRecord.stop ������������
stop
������������������������������������������������������������������������
���������������
public void stop() throws IllegalStateException { if (mState != STATE_INITIALIZED) { throw new IllegalStateException("stop() called on an uninitialized AudioRecord."); } synchronized(mRecordingStateLock) { handleFullVolumeRec(false); native_stop(); mRecordingState = RECORDSTATE_STOPPED; }}// ��������� JNI ������static void android_media_AudioRecord_stop(JNIEnv *env, jobject thiz) { splpRecorder = getAudioRecord(env, thiz); if (lpRecorder == null) { jniThrowException(env, "java/lang/IllegalStateException", null); return; } lpRecorder->stop();}
native_stop ������
void AudioRecord::stop() { AutoMutex lock(mLock); if (!mActive) { return; } mActive = false; mProxy->interrupt(); mAudioRecord->stop(); // ������������ spt = mAudioRecordThread; if (t != null) { t->pause(); } else { setpriority(PRIO_PROCESS, 0, mPreviousPriority); set_sched_policy(0, mPreviousSchedulingGroup); } // ������������������ mMediaMetrics.logStop(systemTime());}
stop() ���������������
mRecordingStateLock
���������������������mActive
���������������3. AudioRecord.release ������������
release
������������������ AudioRecord
������������������������������������������������������
���������������
public void release() { try { stop(); } catch (IllegalStateException ise) { // ������������ } native_release(); mState = STATE_UNINITIALIZED;}
native_release ������
void AudioRecord::native_release() { splpRecorder = setAudioRecord(env, thiz, 0); if (lpRecorder == null) { return; } lpRecorder->stop(); // ������ native ��������� audiorecord_callback_cookie *lpCookie = (audiorecord_callback_cookie *)env->GetLongField(thiz, javaAudioRecordFields.nativeCallbackCookie); env->SetLongField(thiz, javaAudioRecordFields.nativeCallbackCookie, 0); // ������ callback ������ if (lpCookie != null) { Mutex::Autolock l(sLock); while (lpCookie->busy) { if (lpCookie->cond.waitRelative(sLock, milliseconds(CALLBACK_COND_WAIT_TIMEOUT_MS)) != NO_ERROR) { break; } } sAudioRecordCallBackCookies.remove(lpCookie); env->DeleteGlobalRef(lpCookie->audioRecord_class); env->DeleteGlobalRef(lpCookie->audioRecord_ref); delete(lpCookie); }}
release() ���������������
release
���������������������callbackCookie
������������������AudioTrack
������������������������������
��������� AudioRecord.read
���stop
��� release
������������������������������ Android ��������������������������������������������������������������������������������������� native ���������������������������������������������������������������������������������������������������������������������������
发表评论
最新留言
关于作者
