int LoopBack(int on) { MpBufferMsg* pMsg; int save = MpMisc.doLoopBack; MpMisc.doLoopBack = on; while (0 < MpMisc.pLoopBackQ->numMsgs()) { if (OS_SUCCESS == MpMisc.pLoopBackQ->receive((OsMsg*&) pMsg, OsTime::NO_WAIT_TIME)) { pMsg->releaseMsg(); } } return save; }
void testEnabledWithData() { MprToSpkr* pToSpkr = NULL; OsMsgQ* pSpkQ = NULL; OsMsgQ* pEchoQ = NULL; MpBufferMsg* pSpkMsg = NULL; MpBufferMsg* pEchoMsg = NULL; MpBufPtr pBuf; OsStatus res; // Create message queues to get data from MprToSpkr pSpkQ = new OsMsgQ(MSG_Q_LEN); CPPUNIT_ASSERT(pSpkQ != NULL); pEchoQ = new OsMsgQ(MSG_Q_LEN); CPPUNIT_ASSERT(pEchoQ != NULL); pToSpkr = new MprToSpkr("MprToSpkr", pSpkQ, pEchoQ); CPPUNIT_ASSERT(pToSpkr != NULL); setupFramework(pToSpkr); // pToSpkr enabled, there are buffers on the input 0, message queue // is not full. CPPUNIT_ASSERT(mpSourceResource->enable()); CPPUNIT_ASSERT(pToSpkr->enable()); res = mpFlowGraph->processNextFrame(); CPPUNIT_ASSERT(res == OS_SUCCESS); // Get messages from the queues (wait for 1 second) res = pSpkQ->receive((OsMsg*&)pSpkMsg, OsTime(1000)); CPPUNIT_ASSERT(res == OS_SUCCESS); res = pEchoQ->receive((OsMsg*&)pEchoMsg, OsTime(1000)); CPPUNIT_ASSERT(res == OS_SUCCESS); // Store output buffer for convenience pBuf = mpSourceResource->mLastDoProcessArgs.outBufs[0]; // Buffer is sent to queues and to output CPPUNIT_ASSERT( (mpSinkResource->mLastDoProcessArgs.inBufs[0] == pBuf) && (pSpkMsg->getBuffer().isValid()) && (pEchoMsg->getBuffer() == pBuf) ); // Free received message and stored buffer pSpkMsg->releaseMsg(); pEchoMsg->releaseMsg(); pBuf.release(); // Stop flowgraph haltFramework(); // Free message queue delete pSpkQ; delete pEchoQ; }
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; }
static WAVEHDR* outPrePrep(int n, DWORD bufLen) { #ifdef RTL_ENABLED RTL_EVENT("SpeakerThreadWnt.outPrePrep", 1); #endif WAVEHDR* pWH; int doAlloc = (hOutHdr[n] == NULL); MpBufferMsg* msg; MpBufferMsg* pFlush; MpAudioBufPtr ob; static int oPP = 0; static int flushes = 0; static int skip = 0; assert((n > -1) && (n < N_OUT_BUFFERS)); #ifdef DEBUG_WINDOZE /* [ */ if (1) { static int spkQLen[1024]; int in = oPP % 1024; int i, j; spkQLen[in] = MpMisc.pSpkQ->numMsgs(); if (in == 1023) { osPrintf("\n\n Speaker Queue lengths [%d,%d]:\n ", oPP, frameCount); for (i=0; i<1024; i+=32) { for (j=i; j<(i+32); j++) { osPrintf("%3d", spkQLen[j]); } osPrintf("\n "); } osPrintf("\n\n"); } } #endif /* DEBUG_WINDOZE ] */ oPP++; #ifdef DEBUG_WINDOZE /* [ */ if (0 && (0 == (oPP % 1000))) { osPrintf("outPrePrep(): %d playbacks, %d flushes\n", oPP, flushes); } #endif /* DEBUG_WINDOZE ] */ while (MpMisc.pSpkQ && MpMisc.pSpkQ->numMsgs() > MprToSpkr::MAX_SPKR_BUFFERS) { OsStatus res; flushes++; res = MpMisc.pSpkQ->receive((OsMsg*&) pFlush, OsTime::NO_WAIT_TIME); if (OS_SUCCESS == res) { pFlush->releaseMsg(); } else { osPrintf("DmaTask: queue was full, now empty (4)!" " (res=%d)\n", res); } if (flushes > 100) { osPrintf("outPrePrep(): %d playbacks, %d flushes\n", oPP, flushes); flushes = 0; } } if (MpMisc.pSpkQ) { if ( (skip == 0) && (MpMisc.pSpkQ->numMsgs() < MprToSpkr::MIN_SPKR_BUFFERS)) { skip = MprToSpkr::SKIP_SPKR_BUFFERS; assert(MprToSpkr::MAX_SPKR_BUFFERS >= skip); #ifdef DEBUG_WINDOZE /* [ */ osPrintf("Skip(%d,%d)\n", skip, oPP); #endif /* DEBUG_WINDOZE ] */ } if (MpMisc.pSpkQ->numMsgs() >= skip) { skip = 0; if (MpMisc.pSpkQ->receive((OsMsg*&)msg, OsTime::NO_WAIT_TIME) == OS_SUCCESS) { ob = (MpAudioBufPtr)(msg->getBuffer()); msg->releaseMsg(); } // osPrintf("pSpkQ message received\n"); } else { // osPrintf("pSpkQ message skipped\n"); } } if (!ob.isValid()) { ob = MpMisc.mpFgSilence; } if (doAlloc) { hOutHdr[n] = GlobalAlloc(GPTR, sizeof(WAVEHDR)); assert(NULL != hOutHdr[n]); hOutBuf[n] = GlobalAlloc(GPTR, bufLen); assert(NULL != hOutBuf[n]); } pOutHdr[n] = pWH = (WAVEHDR*) GlobalLock(hOutHdr[n]); assert(NULL != pOutHdr[n]); pWH->lpData = (char*) GlobalLock(hOutBuf[n]); pWH->dwBufferLength = bufLen; pWH->dwUser = n; pWH->dwBytesRecorded = 0; pWH->dwFlags = 0; pWH->dwLoops = 0; pWH->lpNext = 0; pWH->reserved = 0; memcpy(pWH->lpData, ob->getSamplesPtr(), bufLen); #ifdef RTL_ENABLED RTL_EVENT("SpeakerThreadWnt.outPrePrep", 0); #endif return pWH; }
UtlBoolean MprFromMic::doProcessFrame(MpBufPtr inBufs[], MpBufPtr outBufs[], int inBufsSize, int outBufsSize, UtlBoolean isEnabled, int samplesPerFrame, int samplesPerSecond) { MpAudioBufPtr out; MpBufferMsg* pMsg; // We need one output buffer if (outBufsSize != 1) return FALSE; // Don't waste the time if output is not connected if (!isOutputConnected(0)) return TRUE; // One more frame processed mNumFrames++; #ifdef RTL_ENABLED RTL_EVENT("FromMic queue", mpMicQ->numMsgs()); #endif if (isEnabled) { // If the microphone queue (holds unprocessed mic data) has more then // the max_mic_buffers threshold, drain the queue until in range) while (mpMicQ && mpMicQ->numMsgs() > MpMisc.max_mic_buffers) { if (mpMicQ->receive((OsMsg*&)pMsg, OsTime::NO_WAIT_TIME) == OS_SUCCESS) { pMsg->releaseMsg(); osPrintf( "mpMicQ drained. %d msgs in queue now\n" , mpMicQ->numMsgs()); } } if (mpMicQ && mpMicQ->numMsgs() > 0) { if (mpMicQ->receive((OsMsg*&)pMsg, OsTime::NO_WAIT_TIME) == OS_SUCCESS) { // osPrintf( "mpMicQ->receive() succeed, %d msgs in queue\n" // , mpMicQ->numMsgs()); out = pMsg->getBuffer(); pMsg->releaseMsg(); } } else { // osPrintf("MprFromMic: No data available (total frames=%d)\n", // mNumFrames); } #ifdef INSERT_SAWTOOTH /* [ */ if (!out.isValid()) { out = MpMisc.RawAudioPool->getBuffer(); if (!out.isValid()) return FALSE; out->setSamplesNumber(MpMisc.frameSamples); } MpBuf_insertSawTooth(out); out->setSpeechType(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 (!out.isValid()) { out = MpMisc.RawAudioPool->getBuffer(); if (!out.isValid()) return FALSE; out->setSamplesNumber(MpMisc.frameSamples); } if (out.isValid()) { int n = 0; MpAudioSample* s = NULL; s = out->getSamplesWritePtr(); n = out->getSamplesNumber(); s_fnMicDataHook(n, (short*)s) ; out->setSpeechType(MP_SPEECH_UNKNOWN); } } if (out.isValid()) { switch(out->getSpeechType()) { case MP_SPEECH_TONE: break; case MP_SPEECH_MUTED: out->setSpeechType(MP_SPEECH_SILENT); break; default: { MpAudioSample* shpTmpFrame; MpAudioBufPtr tpBuf; MpAudioSample *shpSamples; int n = out->getSamplesNumber(); shpSamples = out->getSamplesWritePtr(); tpBuf = MpMisc.RawAudioPool->getBuffer(); if (!out.isValid()) return FALSE; tpBuf->setSamplesNumber(n); assert(tpBuf.isValid()); shpTmpFrame = tpBuf->getSamplesWritePtr(); highpass_filter800(shpSamples, shpTmpFrame, n); out->setSpeechType(speech_detected(shpTmpFrame,n)); } break; } } } else { out = inBufs[0]; } outBufs[0] = out; return TRUE; }
static WAVEHDR* outPrePrep(int n, DWORD bufLen) { WAVEHDR* pWH; int doAlloc = (hOutHdr[n] == NULL); MpBufferMsg* msg; MpBufferMsg* pFlush; MpBufPtr ob; static int oPP = 0; static MpBufPtr prev = NULL; // prev is for future concealment use static int concealed = 0; static int flushes = 0; static int skip = 0; assert((n > -1) && (n < N_OUT_BUFFERS)); #ifdef DEBUG_WINDOZE /* [ */ if (1) { static int spkQLen[1024]; int in = oPP % 1024; int i, j; spkQLen[in] = MpMisc.pSpkQ->numMsgs(); if (in == 1023) { osPrintf("\n\n Speaker Queue lengths [%d,%d]:\n ", oPP, frameCount); for (i=0; i<1024; i+=32) { for (j=i; j<(i+32); j++) { osPrintf("%3d", spkQLen[j]); } osPrintf("\n "); } osPrintf("\n\n"); } } #endif /* DEBUG_WINDOZE ] */ oPP++; #ifdef DEBUG_WINDOZE /* [ */ if (0 && (0 == (oPP % 1000))) { osPrintf("outPrePrep(): %d playbacks, %d flushes\n", oPP, flushes); } #endif /* DEBUG_WINDOZE ] */ while (MpMisc.pSpkQ && MprToSpkr::MAX_SPKR_BUFFERS < MpMisc.pSpkQ->numMsgs()) { OsStatus res; flushes++; res = MpMisc.pSpkQ->receive((OsMsg*&) pFlush, OsTime::NO_WAIT); if (OS_SUCCESS == res) { MpBuf_delRef(pFlush->getTag()); pFlush->releaseMsg(); } else { osPrintf("DmaTask: queue was full, now empty (4)!" " (res=%d)\n", res); } if (flushes > 100) { osPrintf("outPrePrep(): %d playbacks, %d flushes\n", oPP, flushes); flushes = 0; } } if (MpMisc.pSpkQ && (skip == 0) && (MprToSpkr::MIN_SPKR_BUFFERS > MpMisc.pSpkQ->numMsgs())) { skip = MprToSpkr::SKIP_SPKR_BUFFERS; assert(MprToSpkr::MAX_SPKR_BUFFERS >= skip); #ifdef DEBUG_WINDOZE /* [ */ osPrintf("Skip(%d,%d)\n", skip, oPP); #endif /* DEBUG_WINDOZE ] */ } ob = NULL; if (0 == skip) { if (MpMisc.pSpkQ && OS_SUCCESS == MpMisc.pSpkQ->receive((OsMsg*&)msg, OsTime::NO_WAIT)) { ob = msg->getTag(); msg->releaseMsg(); } } else { if (MpMisc.pSpkQ && MpMisc.pSpkQ->numMsgs() >= skip) skip = 0; } if (NULL == ob) { ob = conceal(prev, concealed); concealed++; } else { concealed = 0; } if (doAlloc) { hOutHdr[n] = GlobalAlloc(GPTR, sizeof(WAVEHDR)); assert(NULL != hOutHdr[n]); hOutBuf[n] = GlobalAlloc(GPTR, bufLen); assert(NULL != hOutBuf[n]); } pOutHdr[n] = pWH = (WAVEHDR*) GlobalLock(hOutHdr[n]); assert(NULL != pOutHdr[n]); pWH->lpData = (char*) GlobalLock(hOutBuf[n]); pWH->dwBufferLength = bufLen; pWH->dwUser = n; pWH->dwBytesRecorded = 0; pWH->dwFlags = 0; pWH->dwLoops = 0; pWH->lpNext = 0; pWH->reserved = 0; memcpy(pWH->lpData, MpBuf_getSamples(ob), bufLen); MpBuf_delRef(prev); prev = ob; return pWH; }