UtlBoolean MpBuf_isActiveAudio(MpBufPtr buf) { MpBufSpeech speech; UtlBoolean ret = TRUE; assert(!MpBuf_invalid(buf, FALSE, TRUE)); if (MpBuf_isPoolSilent(buf)) { return FALSE; } speech = MpBuf_getSpeech(buf); switch (speech) { case MP_SPEECH_UNKNOWN: MpBuf_doVAD(buf); speech = MpBuf_getSpeech(buf); assert(MP_SPEECH_UNKNOWN != speech); ret = MpBuf_isActiveAudio(buf); break; case MP_SPEECH_ACTIVE: case MP_SPEECH_TONE: break; case MP_SPEECH_SILENT: case MP_SPEECH_COMFORT_NOISE: case MP_SPEECH_MUTED: ret = FALSE; break; } return ret; }
UtlBoolean MprFromMic::doProcessFrame(MpBufPtr inBufs[], MpBufPtr outBufs[], int inBufsSize, int outBufsSize, UtlBoolean isEnabled, int samplesPerFrame, int samplesPerSecond) { MpBufPtr out = NULL ; MpBufferMsg* pMsg; if (0 == outBufsSize) { return FALSE; } // Clear the the number of empty frames every 512 frames mNumFrames++; if (0 == (mNumFrames & 0x1ff)) { mNumEmpties = 0; } if (isEnabled) { // If the microphone queue (holds unprocessed mic data) has more then // the max_mic_buffers threshold, drain the queue until in range) OsMsgQ* pMicOutQ; pMicOutQ = MpMisc.pMicQ; while (pMicOutQ && MpMisc.max_mic_buffers < pMicOutQ->numMsgs()) { if (OS_SUCCESS == pMicOutQ->receive((OsMsg*&) pMsg, OsTime::NO_WAIT)) { MpBuf_delRef(pMsg->getTag()); MpBuf_delRef(pMsg->getTag(1)); pMsg->releaseMsg(); } } if (pMicOutQ && pMicOutQ->numMsgs() <= 0) { // osPrintf("MprFromMic: No data available (total frames=%d, starved frames=%d)\n", // mNumFrames, mNumEmpties); } else { if (pMicOutQ && OS_SUCCESS == pMicOutQ->receive((OsMsg*&) pMsg, OsTime::NO_WAIT)) { out = pMsg->getTag(); pMsg->releaseMsg(); if (NULL != out) { #ifdef REAL_SILENCE_DETECTION /* [ */ Sample* shpTmpFrame; MpBufPtr tpBuf; int n; #endif /* REAL_SILENCE_DETECTION ] */ switch(MpBuf_getSpeech(out)) { case MP_SPEECH_TONE: break; case MP_SPEECH_MUTED: MpBuf_setSpeech(out, MP_SPEECH_SILENT); break; default: #ifdef REAL_SILENCE_DETECTION /* [ */ Sample *shpSamples; n = MpBuf_getNumSamples(out); shpSamples = MpBuf_getSamples(out); tpBuf = MpBuf_getBuf(MpMisc.UcbPool, n, 0, MP_FMT_T12); assert(NULL != tpBuf); shpTmpFrame = MpBuf_getSamples(tpBuf); highpass_filter800(shpSamples, shpTmpFrame, n); if(0 == speech_detected(shpTmpFrame,n)) { MpBuf_setSpeech(out, MP_SPEECH_SILENT); } else { MpBuf_setSpeech(out, MP_SPEECH_ACTIVE); } MpBuf_delRef(tpBuf); #else /* REAL_SILENCE_DETECTION ] [ */ // 24 April 2001 (HZM) I am disabling this because it takes // too long to recognize the beginning of a talk spurt, and // causes the bridge mixer to drop the start of each word. MpBuf_isActiveAudio(out); #endif /* REAL_SILENCE_DETECTION ] */ break; } } } } #ifdef INSERT_SAWTOOTH /* [ */ if (NULL == out) { out = MpBuf_getBuf(MpMisc.UcbPool, MpMisc.frameSamples, 0, MP_FMT_T12); } MpBuf_insertSawTooth(out); MpBuf_setSpeech(out, MP_SPEECH_ACTIVE); #endif /* INSERT_SAWTOOTH ] */ if (s_fnMicDataHook) { // // Allow an external identity to source microphone data. Ideally, // this should probably become a different resource, but abstracting // a new CallFlowGraph is a lot of work. // if (NULL == out) { out = MpBuf_getBuf(MpMisc.UcbPool, MpMisc.frameSamples, 0, MP_FMT_T12); } if (NULL != out) { int n = 0; Sample* s = NULL; s = MpBuf_getSamples(out); n = MpBuf_getNumSamples(out); s_fnMicDataHook(n, s) ; MpBuf_setSpeech(out, MP_SPEECH_UNKNOWN); MpBuf_isActiveAudio(out); } } if (NULL == out) { out = MpBuf_getFgSilence(); } } *outBufs = out; return TRUE; }
UtlBoolean MpBuf_isSilence(MpBufPtr buf) { return !MpBuf_isActiveAudio(buf); }
UtlBoolean MprRecorder::doProcessFrame(MpBufPtr inBufs[], MpBufPtr outBufs[], int inBufsSize, int outBufsSize, UtlBoolean isEnabled, int samplesPerFrame, int samplesPerSecond) { int numBytes = 0; int numSamples = 0; MpBufPtr in = NULL; Sample* input; // Lock so that mFileDescriptor and file contents cannot be changed out // from under us while we are updating the file. OsLock lock(mMutex); //try to pass along first input if (inBufsSize > 0) { in = *inBufs; } if (numOutputs() > 0) { if (inBufsSize > 0) *inBufs = NULL; *outBufs = in; } if (!isEnabled) { return TRUE; } if (mFileDescriptor < 0) { OsSysLog::add(FAC_MP, PRI_DEBUG, "MprRecorder::doProcessFrame to disable recording because mFileDescriptor=%d, mStatus=%d", mFileDescriptor, mStatus); disable(RECORD_STOPPED); // just in case... } if (inBufsSize == 0) { // no input buffers, indicate config error disable(INVALID_SETUP); return TRUE; } // maximum record time reached or final silence timeout. if ((0 >= mFramesToRecord--) || (mSilenceLength <= mConsecutiveInactive)) { // Get previous MinVoiceEnergy for debug printouts, and reset it to MIN_SPEECH_ENERGY_THRESHOLD. unsigned long prevValue = MpBuf_setMVE(MIN_SPEECH_ENERGY_THRESHOLD); OsSysLog::add(FAC_MP, PRI_INFO, "MprRecorder::doProcessFrame to disable recording because" " mFramesToRecord=%d, mStatus=%d mSilenceLength=%d," " mConsecutiveInactive=%d, MinVoiceEnergy=%lu", mFramesToRecord, mStatus, mSilenceLength, mConsecutiveInactive, prevValue); disable(RECORD_FINISHED); } else { int bytesWritten = 0; //now write the buffer out if (NULL == in) { in = MpBuf_getFgSilence(); } else { MpBuf_addRef(in); } if (MpBuf_isActiveAudio(in)) { mConsecutiveInactive = 0; } else { mConsecutiveInactive++; } input = MpBuf_getSamples(in); numSamples = MpBuf_getNumSamples(in); numBytes = numSamples * sizeof(Sample); if (mFileDescriptor > -1) { #ifdef __BIG_ENDIAN__ //We are running on a big endian processor - 16-bit samples are in the big endian //byte order - convert them to little endian before writing them to the file. unsigned short *pData; int index; for ( index = 0, pData = (unsigned short *)input; index < numSamples; index++, pData++ ) *pData = htoles(*pData); #endif bytesWritten = write(mFileDescriptor, (char *)input, numBytes); #ifdef __BIG_ENDIAN__ if (numOutputs() > 1) { //There is more than one output - convert the samples back to big endian for ( index = 0, pData = (unsigned short *)input; index < numSamples; index++, pData++ ) *pData = letohs(*pData); } #endif } if (bytesWritten != numBytes) { disable(WRITE_ERROR); } else { mTotalBytesWritten += numBytes; mTotalSamplesWritten += samplesPerFrame; } MpBuf_delRef(in); } return TRUE; }