static MpBufPtr conceal(MpBufPtr prev, int concealed) { #ifdef XXX_DEBUG_WINDOZE /* [ */ MpBufPtr ret; Sample* src; Sample* dst; int len; int halfLen; int i; if (NULL == prev) { ret = MpBuf_getFgSilence(); return ret; } len = MpBuf_getNumSamples(prev); ret = MpBuf_getBuf(MpBuf_getPool(prev), len, 0, MpBuf_getFormat(prev)); src = MpBuf_getSamples(prev); dst = MpBuf_getSamples(ret); halfLen = (len + 1) >> 1; for (i=0; i<halfLen; i++) { dst[i] = src[len - i]; } for (i=halfLen; i<len; i++) { dst[i] = src[i]; } if (concealed > 2) { for (i=0; i<len; i++) { dst[i] = dst[i] >> 1; // attenuate } } return ret; #else /* DEBUG_WINDOZE ] [ */ return MpBuf_getFgSilence(); #endif /* DEBUG_WINDOZE ] */ }
MpBufSpeech MpBuf_doVAD(MpBufPtr buf) { int num, i = 1; Sample prev; Sample* data; unsigned long energy = 0; unsigned long t; MpBufSpeech ret = MP_SPEECH_SILENT; assert(!MpBuf_invalid(buf, FALSE, TRUE)); num = MpBuf_getNumSamples(buf); data = MpBuf_getSamples(buf); while ((i < num) && (MP_SPEECH_SILENT == ret)) { i++; prev = *data++; t = (prev - *data) >> 1; energy += t * t; if (energy >= MinVoiceEnergy) ret = MP_SPEECH_ACTIVE; } #ifdef DEBUG if (20 > numVads++) osPrintf(" %d %ld\n", i, energy); #endif MpBuf_setSpeech(buf, ret); return ret; }
MpBufPtr MpBuf_allowMods(MpBufPtr b) { MpBufPtr t; if (NULL == b) { return NULL; } if (MpBuf_invalid(b, FALSE, TRUE)) { Zprintf("MpBuf_allowMod(0x%X): invalid!\n", (int) b, 0,0,0,0,0); return NULL; } if (1 == b->refCnt) { return b; } t = MpBuf_getBuf(b->pPool, MpBuf_getNumSamples(b), MpBuf_getOffset(b), MpBuf_getFormat(b)); if (NULL == t) { return NULL; } memcpy((void*) MpBuf_getSamples(t), (void*) MpBuf_getSamples(b), MpBuf_getByteLen(t)); MpBuf_setOsTC(t, MpBuf_getOsTC(b)); MpBuf_setContentLen(t, MpBuf_getContentLen(b)); MpBuf_delRef(b); return t; } /* MpBuf_allowMods */
int showSpareBufs(int fixIt, char* tag) { MpBufPtr sb; Sample* src; Sample* dst; int i, j, n; int ok; int OK = 1; int fixed; if (NULL == tag) tag = ""; osPrintf("\n"); for (i=0; i<N_SPARE_BUFS; i++) { ok = 1; fixed = 0; sb = spareBufs[i]; if (NULL != sb) { src = MpBuf_getSamples(sb); n = MpBuf_getNumSamples(sb); for (j=0; ((j<n) && ok); j++) { if (*src++ != ((i<<8) + j)) ok = 0; } if ((!ok) & fixIt) { dst = MpBuf_getSamples(sb); n = MpBuf_getNumSamples(sb); for (j=0; j<n; j++) { *dst++ = (i<<8) + j; } fixed = 1; } src = MpBuf_getSamples(sb); } else { ok = 0; src = NULL; } OK &= ok; osPrintf("%sspare[%d] = 0x%X->0x%X (%sOK)%s\n", tag, i, (int) sb, (int) src, (ok ? "" : "NOT "), (fixed ? " (Fixed)" : "")); } return OK; }
void MpBuf_insertSawTooth(MpBufPtr b) { int i, n; Sample *s; if (NULL == b) return; if (!MpBuf_invalid(b, TRUE, TRUE)) { s = MpBuf_getSamples(b); n = MpBuf_getNumSamples(b); for (i=0; i<n; i++) *s++ = ((0xf & i) << 12); } }
UtlBoolean MprToneGen::doProcessFrame(MpBufPtr inBufs[], MpBufPtr outBufs[], int inBufsSize, int outBufsSize, UtlBoolean isEnabled, int samplesPerFrame, int samplesPerSecond) { MpBufPtr out = NULL; int16_t *outbuf; int count; OsStatus ret; if (0 == outBufsSize) return FALSE; *outBufs = NULL; if (0 == samplesPerFrame) return FALSE; if (isEnabled) { out = MpBuf_getBuf(MpMisc.UcbPool, samplesPerFrame, 0, MP_FMT_T12); assert(NULL != out); count = min(samplesPerFrame, MpBuf_getNumSamples(out)); MpBuf_setNumSamples(out, count); outbuf = (int16_t*)MpBuf_getSamples(out); ret = MpToneGen_getNextBuff(mpToneGenState, outbuf, count); switch (ret) { case OS_WAIT_TIMEOUT: /* one-shot tone completed */ ((MpCallFlowGraph*)getFlowGraph())->stopTone(); MpBuf_setSpeech(out, MP_SPEECH_TONE); break; case OS_NO_MORE_DATA: /* silent */ MpBuf_delRef(out); out = NULL; // Will replace with silence before returning... break; case OS_SUCCESS: default: MpBuf_setSpeech(out, MP_SPEECH_TONE); break; } } else { if (0 < inBufsSize) out = *inBufs; *inBufs = NULL; } if (NULL == out) { out = MpBuf_getFgSilence(); } *outBufs = out; return (NULL != mpToneGenState); }
/* //////////////////////////// PRIVATE /////////////////////////////////// */ MprDejitter* MprDecode::getMyDejitter(void) { assert(NULL != mpMyDJ); return mpMyDJ; } #ifdef DEBUG /* [ */ static void showRtpPacket(MpBufPtr rtp) { struct rtpHeader rh, *rp; int len; rp = (struct rtpHeader *) (MpBuf_getStorage(rtp)); memcpy((char *) &rh, (char *) rp, sizeof(struct rtpHeader)); rh.vpxcc = rp->vpxcc; rh.mpt = rp->mpt; rh.seq = ntohs(rp->seq); rh.timestamp = ntohl(rp->timestamp); rh.ssrc = ntohl(rp->ssrc); len = MpBuf_getNumSamples(rtp) - sizeof(struct rtpHeader); Zprintf("RcvRTP: %02X, %02X, %d, %d, %08X, and %d bytes of data\n", rh.vpxcc, rh.mpt, rh.seq, rh.timestamp, rh.ssrc, len); }
unsigned long MpBuf_getVAD(MpBufPtr buf) { int num, i = 1; Sample prev; Sample* data; unsigned long energy = 0; unsigned long t; assert(!MpBuf_invalid(buf, FALSE, TRUE)); num = MpBuf_getNumSamples(buf); data = MpBuf_getSamples(buf); while (i < num) { i++; prev = *data++; t = (prev - *data) >> 1; energy += t * t; } return energy; }
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 MprBridge::doProcessFrame(MpBufPtr inBufs[], MpBufPtr outBufs[], int inBufsSize, int outBufsSize, UtlBoolean isEnabled, int samplesPerFrame, int samplesPerSecond) { int i; int inIdx; int outIdx; int n; int scale; int inputs; int N = samplesPerFrame; MpBufPtr in; MpBufPtr out; Sample* input; Sample* output; Sample* outstart; if (0 == outBufsSize) { Zprintf("MprBridge::doPF: outBufsSize = %d! (inBufsSize=%d)\n", outBufsSize, inBufsSize, 0,0,0,0); return FALSE; } if (inBufsSize != outBufsSize) { Zprintf("MprBridge::doPF: outBufsSize(%d) != inBufsSize(%d)\n", outBufsSize, inBufsSize, 0,0,0,0); return FALSE; } if (0 == inBufsSize) return FALSE; // no input buffers, not allowed for (i=0; i < outBufsSize; i++) { outBufs[i] = NULL; } if (!isEnabled) { // Disabled. Mix all remote inputs onto local speaker, and copy // our local microphone to all remote outputs. // First, count how many contributing inputs inputs = 0; for (inIdx=1; inIdx < inBufsSize; inIdx++) { if (isPortActive(inIdx)) { if((MpBuf_getSpeech(inBufs[inIdx]) != MP_SPEECH_SILENT) && (MpBuf_getSpeech(inBufs[inIdx]) != MP_SPEECH_COMFORT_NOISE)) inputs++; } } if (inputs > 0) { // Compute a scale factor to renormalize (approximately) scale = 0; while (inputs > 1) { scale++; inputs = inputs >> 1; } out = MpBuf_getBuf(MpMisc.UcbPool, N, 0, MP_FMT_T12); if (NULL == out) { Zprintf( "MprBridge::doPF(line #%d): MpBuf_getBuf() returned NULL!\n", __LINE__, 0,0,0,0,0); return FALSE; } outstart = MpBuf_getSamples(out); memset((char *) outstart, 0, N * sizeof(Sample)); for (inIdx=1; inIdx < inBufsSize; inIdx++) { if (isPortActive(inIdx)) { output = outstart; //Mix only non-silent audio if((MpBuf_getSpeech(inBufs[inIdx]) != MP_SPEECH_COMFORT_NOISE) && (MpBuf_getSpeech(inBufs[inIdx]) != MP_SPEECH_SILENT) ) { input = MpBuf_getSamples(inBufs[inIdx]); n = min(MpBuf_getNumSamples(inBufs[inIdx]), samplesPerFrame); for (i=0; i<n; i++) *output++ += (*input++) >> scale; } } }
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; }
UtlBoolean MprMixer::doProcessFrame(MpBufPtr inBufs[], MpBufPtr outBufs[], int inBufsSize, int outBufsSize, UtlBoolean isEnabled, int samplesPerFrame, int samplesPerSecond) { int i; int in; int wgt; int n; int N = samplesPerFrame; MpBufPtr out; Sample* input; Sample* output; Sample* outstart; if (0 == outBufsSize) return FALSE; *outBufs = NULL; if ((0 == mScale) || (0 == inBufsSize)) { out = MpBuf_getFgSilence(); *outBufs = out; return TRUE; // scale factors are all zero, or // no input buffers, return silence } if (!isEnabled) { // Disabled, return first input out = *inBufs; *inBufs = NULL; if (NULL == out) { out = MpBuf_getFgSilence(); } *outBufs = out; return TRUE; } if (1 == mScale) { // must be only one weight != 0, and it is == 1 out = NULL; for (i=0; i < inBufsSize; i++) { if (0 != mWeights[i]) { out = inBufs[i]; inBufs[i] = NULL; i = inBufsSize; // all done, exit loop } } if (NULL == out) { out = MpBuf_getFgSilence(); } *outBufs = out; return TRUE; // even if we did not find it (mNWeights > inBufsSize) } out = MpBuf_getBuf(MpMisc.UcbPool, N, 0, MP_FMT_T12); assert(NULL != out); *outBufs = out; outstart = MpBuf_getSamples(out); memset((char *) outstart, 0, N * sizeof(Sample)); for (in=0; in < inBufsSize; in++) { wgt = mWeights[in]; if ((NULL != inBufs[in]) && (0 != wgt)) { output = outstart; input = MpBuf_getSamples(inBufs[in]); n = min(MpBuf_getNumSamples(inBufs[in]), samplesPerFrame); if (1 == wgt) { for (i=0; i<n; i++) *output++ += (*input++) / mScale; } else { for (i=0; i<n; i++) *output++ += (*input++ * wgt) / mScale; } } } return TRUE; }