void MpodAndroid::audioCallback(int event, void* user, void *info) { //LOGV("MpodAndroid::audioCallback(event=%d)\n", event); RTL_BLOCK("MpodAndroid::audioCallback"); bool lSignal = false; if (event != MpAndroidAudioTrack::EVENT_MORE_DATA) { LOGV("MpodAndroid::audioCallback(event=%d)\n", event); return; } MpAndroidAudioTrack::Buffer *buffer = static_cast<MpAndroidAudioTrack::Buffer *>(info); MpodAndroid *pDriver = static_cast<MpodAndroid *>(user); // Start accessing non-atomic member variables AutoMutex autoLock(pDriver->mLock); int samplesToCopy = sipx_min(buffer->frameCount, pDriver->mSamplesPerFrame-pDriver->mSampleBufferIndex); #ifdef ENABLE_FRAME_TIME_LOGGING LOGV("MpodAndroid::audioCallback() buffer=%p samples=%d size=%d toCopy=%d\n", buffer->i16, buffer->frameCount, buffer->size, samplesToCopy); #endif RTL_EVENT("MpodAndroid::audioCallback_bufsize", samplesToCopy); // Copy data to buffer memcpy(buffer->i16, pDriver->mpSampleBuffer+pDriver->mSampleBufferIndex, samplesToCopy*sizeof(short)); buffer->frameCount = samplesToCopy; buffer->size = samplesToCopy*sizeof(short); pDriver->mSampleBufferIndex += samplesToCopy; #ifdef ENABLE_FILE_LOGGING fwrite(buffer->i16, 1, buffer->frameCount*sizeof(short), sgOutFile); #endif // ENABLE_FILE_LOGGING if (pDriver->mSampleBufferIndex >= pDriver->mSamplesPerFrame) { RTL_BLOCK("MpodAndroid::audioCallback_tick"); if(pDriver->mSampleBufferIndex > pDriver->mSamplesPerFrame) { LOGE("MpodAndroid::audioCallback() sample index (%d) > samples/frame (%d)\n", (int)pDriver->mSampleBufferIndex, (int)pDriver->mSamplesPerFrame); } // Return index to the beginning pDriver->mSampleBufferIndex = 0; // Fire callback. It will call our pushFrame() in turn. #ifdef ENABLE_FRAME_TIME_LOGGING LOGV("MpodAndroid::audioCallback() signal ticker, time %"PRIi64"ns\n", systemTime(SYSTEM_TIME_REALTIME)); #endif pDriver->mpTickerNotification->signal(pDriver->mSamplesPerFrame); // Update frame time. pDriver->mCurFrameTime += pDriver->mSamplesPerFrame; } // Step forward state switch (pDriver->mState) { case DRIVER_STARTING: pDriver->mState = DRIVER_PLAYING; lSignal = true; break; case DRIVER_STOPPING: // pDriver->mState = DRIVER_STOPPED; // break; case DRIVER_STOPPED: LOGV("MpodAndroid::audioCallback() stopping Track\n"); pDriver->mpAudioTrack->stop(); LOGV("MpodAndroid::audioCallback() stopped Track\n"); buffer->size = 0; pDriver->mState = DRIVER_IDLE; lSignal = true; break; default: break; } if (lSignal) { LOGV("MpodAndroid::audioCallback signalling\n"); pDriver->mWaitCbkCond.signal(); LOGV("MpodAndroid::audioCallback signalled\n"); } }
void MpOss::soundIoThread() { UtlBoolean bStReader; UtlBoolean bStWriter; UtlBoolean bShutdown; OsStatus status; MpAudioSample* isamples; const MpAudioSample* osamples; int i; UtlBoolean bWakeUp = TRUE; assert(mModeChanged == TRUE); for (;;i++) { // To reduce latency we use flag handling instead of semaphore locking while (mModeChanged) { bStReader = mStReader; bStWriter = mStWriter; bShutdown = mStShutdown; // Set we have caught signal mModeChanged = FALSE; if (!bStWriter && !bStReader && !bShutdown) { RTL_EVENT("MpOss::io_thread", 10); ioctl(mfdDevice, SNDCTL_DSP_SYNC, NULL); RTL_EVENT("MpOss::io_thread", 11); ossSetTrigger(false); ossReset(); sem_post(&mSignalSem); RTL_EVENT("MpOss::io_thread", 12); // Wait for any IO sem_wait(&mSleepSem); if (mStShutdown) { return; } bWakeUp = TRUE; } else if (bShutdown) { RTL_EVENT("MpOss::io_thread", 0); // OSS driver killing ossSetTrigger(false); ossReset(); return; } else { // Signal we have caught modification flag sem_post(&mSignalSem); RTL_EVENT("MpOss::io_thread", 15); int frameSize = ((mStereoOps) ? 2 : 1) * mUsedSamplesPerFrame * 2; if (bStWriter || bStReader) { assert (frameSize > 0 && frameSize < SOUND_MAXBUFFER); } if (bWakeUp) { unsigned precharge; i = 0; RTL_EVENT("MpOss::io_thread", -1); ossSetTrigger(true); RTL_EVENT("MpOss::io_thread", 16); if (mbWriteCap) { // Plays out silence to set requested buffer deep precharge = OSS_LATENCY_LENGTH * mUsedSamplesPerSec / 1000; for (unsigned k = 0; k < precharge; k += mUsedSamplesPerFrame) { unsigned sz = precharge - k; if (sz > mUsedSamplesPerFrame) sz = mUsedSamplesPerFrame; //Use small data request unless OSS may be confused if (mbReadCap) { doInputRs(gTrashBuffer, mUsedSamplesPerFrame >> 3); RTL_EVENT("MpOss::io_thread", 18); } doOutputRs(gSilenceBuffer, sz); RTL_EVENT("MpOss::io_thread", 17); } } RTL_EVENT("MpOss::io_thread", 19); if ((mbWriteCap) && (mbReadCap)) { //Compensates output shift due previous data requests doOutputRs(gSilenceBuffer, (mUsedSamplesPerFrame >> 2)); } bWakeUp = FALSE; RTL_EVENT("MpOss::io_thread", 16); } } } // Produce heart beat for MpMediaLib if ((mWriter) && (!mWriter->mNotificationThreadEn)) { RTL_EVENT("MpOss::io_thread", 4); mWriter->signalForNextFrame(); } if (mbReadCap) { RTL_EVENT("MpOss::io_thread", 2); isamples = (bStReader) ? mReader->mAudioFrame : gTrashBuffer; status = doInputRs(isamples, mUsedSamplesPerFrame); if ((status == OS_SUCCESS) && (bStReader)) { RTL_EVENT("MpOss::io_thread", 3); mReader->pushFrame(); } } if (mbWriteCap) { osamples = (bStWriter) ? mWriter->mAudioFrame : gSilenceBuffer; RTL_EVENT("MpOss::io_thread", 1); status = doOutputRs(osamples, mUsedSamplesPerFrame); } }
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; }
void testTones() { RTL_START(1600000); CPPUNIT_ASSERT(mpMediaFactory); SdpCodecList* sdpCodecList = new SdpCodecList(); CPPUNIT_ASSERT(sdpCodecList); UtlSList utlCodecList; sdpCodecList->getCodecs(utlCodecList); UtlString localRtpInterfaceAddress("127.0.0.1"); UtlString locale; int tosOptions = 0; UtlString stunServerAddress; int stunOptions = 0; int stunKeepAlivePeriodSecs = 25; UtlString turnServerAddress; int turnPort = 0 ; UtlString turnUser; UtlString turnPassword; int turnKeepAlivePeriodSecs = 25; bool enableIce = false ; CpMediaInterface* mediaInterface = mpMediaFactory->createMediaInterface(NULL, sdpCodecList, NULL, // public mapped RTP IP address localRtpInterfaceAddress, locale, tosOptions, stunServerAddress, stunOptions, stunKeepAlivePeriodSecs, turnServerAddress, turnPort, turnUser, turnPassword, turnKeepAlivePeriodSecs, enableIce); // Record the entire "call" - all connections. mediaInterface->recordAudio("testTones_call_recording.wav"); mediaInterface->giveFocus() ; RTL_EVENT("Tone set", 0); printf("first tone set\n"); RTL_EVENT("Tone set", 1); mediaInterface->startTone(6, true, false) ;OsTask::delay(500) ; RTL_EVENT("Tone set", 2); mediaInterface->startTone(8, true, false) ;OsTask::delay(500) ; RTL_EVENT("Tone set", 3); mediaInterface->startTone(4, true, false) ;OsTask::delay(500) ; RTL_EVENT("Tone set", 0); printf("second tone set\n"); OsTask::delay(500) ; RTL_EVENT("Tone set", 1); mediaInterface->startTone(6, true, false) ;OsTask::delay(500) ; RTL_EVENT("Tone set", 2); mediaInterface->startTone(8, true, false) ;OsTask::delay(500) ; RTL_EVENT("Tone set", 3); mediaInterface->startTone(4, true, false) ;OsTask::delay(500) ; RTL_EVENT("Tone set", 0); printf("third tone set\n"); OsTask::delay(500) ; RTL_EVENT("Tone set", 1); mediaInterface->startTone(9, true, false) ;OsTask::delay(500) ; mediaInterface->startTone(5, true, false) ;OsTask::delay(500) ; mediaInterface->startTone(5, true, false) ;OsTask::delay(500) ; mediaInterface->startTone(4, true, false) ;OsTask::delay(500) ; RTL_EVENT("Tone set", 0); printf("fourth tone set\n"); OsTask::delay(500) ; RTL_EVENT("Tone set", 1); mediaInterface->startTone(9, true, false) ;OsTask::delay(500) ; mediaInterface->startTone(5, true, false) ;OsTask::delay(500) ; mediaInterface->startTone(5, true, false) ;OsTask::delay(500) ; mediaInterface->startTone(4, true, false) ;OsTask::delay(500) ; RTL_EVENT("Tone set", 0); printf("tone set done\n"); OsTask::delay(1000) ; // Stop recording the "call" -- all connections. mediaInterface->stopRecording(); RTL_WRITE("testTones.rtl"); RTL_STOP; // delete interface mediaInterface->release(); OsTask::delay(500) ; delete sdpCodecList ; };
void testTwoTones() { RTL_START(2400000); // This test creates three flowgraphs. It streams RTP with tones // from the 2nd and 3rd to be received and mixed in the first flowgraph // So we test RTP and we test that we can generate 2 different tones in // to different flowgraphs to ensure that the ToneGen has no global // interactions or dependencies. CPPUNIT_ASSERT(mpMediaFactory); SdpCodecList* pSdpCodecList = new SdpCodecList(); CPPUNIT_ASSERT(pSdpCodecList); UtlSList utlCodecList; pSdpCodecList->getCodecs(utlCodecList); UtlString localRtpInterfaceAddress("127.0.0.1"); OsSocket::getHostIp(&localRtpInterfaceAddress); UtlString locale; int tosOptions = 0; UtlString stunServerAddress; int stunOptions = 0; int stunKeepAlivePeriodSecs = 25; UtlString turnServerAddress; int turnPort = 0 ; UtlString turnUser; UtlString turnPassword; int turnKeepAlivePeriodSecs = 25; bool enableIce = false ; // Create a flowgraph (sink) to receive and mix 2 sources CpMediaInterface* mixedInterface = mpMediaFactory->createMediaInterface(NULL, pSdpCodecList, NULL, // public mapped RTP IP address localRtpInterfaceAddress, locale, tosOptions, stunServerAddress, stunOptions, stunKeepAlivePeriodSecs, turnServerAddress, turnPort, turnUser, turnPassword, turnKeepAlivePeriodSecs, enableIce); // Create connections for mixed(sink) flowgraph int mixedConnection1Id = -1; CPPUNIT_ASSERT(mixedInterface->createConnection(mixedConnection1Id, NULL) == OS_SUCCESS); CPPUNIT_ASSERT(mixedConnection1Id > 0); int mixedConnection2Id = -1; CPPUNIT_ASSERT(mixedInterface->createConnection(mixedConnection2Id, NULL) == OS_SUCCESS); CPPUNIT_ASSERT(mixedConnection2Id > 0); // Get the address of the connections so we can send RTP to them // capabilities of first connection on mixed(sink) flowgraph const int maxAddresses = 1; UtlString rtpHostAddresses1[maxAddresses]; int rtpAudioPorts1[maxAddresses]; int rtcpAudioPorts1[maxAddresses]; int rtpVideoPorts1[maxAddresses]; int rtcpVideoPorts1[maxAddresses]; RTP_TRANSPORT transportTypes1[maxAddresses]; int numActualAddresses1; SdpCodecList supportedCodecs1; SdpSrtpParameters srtpParameters1; int videoBandwidth1; int videoFramerate1; CPPUNIT_ASSERT_EQUAL( mixedInterface->getCapabilitiesEx(mixedConnection1Id, maxAddresses, rtpHostAddresses1, rtpAudioPorts1, rtcpAudioPorts1, rtpVideoPorts1, rtcpVideoPorts1, transportTypes1, numActualAddresses1, supportedCodecs1, srtpParameters1, videoBandwidth1, videoFramerate1), OS_SUCCESS); // capabilities of second connection on mixed(sink) flowgraph UtlString rtpHostAddresses2[maxAddresses]; int rtpAudioPorts2[maxAddresses]; int rtcpAudioPorts2[maxAddresses]; int rtpVideoPorts2[maxAddresses]; int rtcpVideoPorts2[maxAddresses]; RTP_TRANSPORT transportTypes2[maxAddresses]; int numActualAddresses2; SdpCodecList supportedCodecs2; SdpSrtpParameters srtpParameters2; int videoBandwidth2; int videoFramerate2; CPPUNIT_ASSERT_EQUAL( mixedInterface->getCapabilitiesEx(mixedConnection2Id, maxAddresses, rtpHostAddresses2, rtpAudioPorts2, rtcpAudioPorts2, rtpVideoPorts2, rtcpVideoPorts2, transportTypes2, numActualAddresses2, supportedCodecs2, srtpParameters2, videoBandwidth2, videoFramerate2), OS_SUCCESS); // Prep the sink connections to receive RTP UtlSList codec1List; supportedCodecs1.getCodecs(codec1List); CPPUNIT_ASSERT_EQUAL( mixedInterface->startRtpReceive(mixedConnection1Id, codec1List), OS_SUCCESS); // Want to hear what is on the mixed flowgraph mixedInterface->giveFocus(); UtlSList codec2List; supportedCodecs2.getCodecs(codec2List); CPPUNIT_ASSERT_EQUAL( mixedInterface->startRtpReceive(mixedConnection2Id, codec2List), OS_SUCCESS); // Second flowgraph to be one of two sources CpMediaInterface* source1Interface = mpMediaFactory->createMediaInterface(NULL, pSdpCodecList, NULL, // public mapped RTP IP address localRtpInterfaceAddress, locale, tosOptions, stunServerAddress, stunOptions, stunKeepAlivePeriodSecs, turnServerAddress, turnPort, turnUser, turnPassword, turnKeepAlivePeriodSecs, enableIce); // Create connection for source 1 flowgraph int source1ConnectionId = -1; CPPUNIT_ASSERT(source1Interface->createConnection(source1ConnectionId, NULL) == OS_SUCCESS); CPPUNIT_ASSERT(source1ConnectionId > 0); // Set the destination for sending RTP from source 1 to connection 1 on // the mix flowgraph printf("rtpHostAddresses1: \"%s\"\nrtpAudioPorts1: %d\nrtcpAudioPorts1: %d\nrtpVideoPorts1: %d\nrtcpVideoPorts1: %d\n", rtpHostAddresses1->data(), *rtpAudioPorts1, *rtcpAudioPorts1, *rtpVideoPorts1, *rtcpVideoPorts1); CPPUNIT_ASSERT_EQUAL( source1Interface->setConnectionDestination(source1ConnectionId, rtpHostAddresses1->data(), *rtpAudioPorts1, *rtcpAudioPorts1, *rtpVideoPorts1, *rtcpVideoPorts1), OS_SUCCESS); // Start sending RTP from source 1 to the mix flowgraph CPPUNIT_ASSERT_EQUAL( source1Interface->startRtpSend(source1ConnectionId, codec1List), OS_SUCCESS); // Second flowgraph to be one of two sources CpMediaInterface* source2Interface = mpMediaFactory->createMediaInterface(NULL, pSdpCodecList, NULL, // public mapped RTP IP address localRtpInterfaceAddress, locale, tosOptions, stunServerAddress, stunOptions, stunKeepAlivePeriodSecs, turnServerAddress, turnPort, turnUser, turnPassword, turnKeepAlivePeriodSecs, enableIce); // Create connection for source 2 flowgraph int source2ConnectionId = -1; CPPUNIT_ASSERT(source2Interface->createConnection(source2ConnectionId, NULL) == OS_SUCCESS); CPPUNIT_ASSERT(source2ConnectionId > 0); // Set the destination for sending RTP from source 2 to connection 2 on // the mix flowgraph CPPUNIT_ASSERT_EQUAL( source2Interface->setConnectionDestination(source2ConnectionId, *rtpHostAddresses2, *rtpAudioPorts2, *rtcpAudioPorts2, *rtpVideoPorts2, *rtcpVideoPorts2), OS_SUCCESS); RTL_EVENT("Tone count", 0); // Record the entire "call" - all connections. mixedInterface->recordAudio("testTwoTones_call_recording.wav"); // Start sending RTP from source 2 to the mix flowgraph CPPUNIT_ASSERT_EQUAL( source2Interface->startRtpSend(source2ConnectionId, codec2List), OS_SUCCESS); RTL_EVENT("Tone count", 1); printf("generate tones in source 1\n"); source1Interface->startTone(1, true, true); OsTask::delay(1000); RTL_EVENT("Tone count", 2); printf("generate tones in source 2 as well\n"); source2Interface->startTone(2, true, true); OsTask::delay(1000); RTL_EVENT("Tone count", 1); printf("stop tones in source 1\n"); OsTask::delay(1000); RTL_EVENT("Tone count", 0); OsTask::delay(1000); printf("two tones done\n"); // Stop recording the "call" -- all connections. mixedInterface->stopRecording(); // Delete connections mixedInterface->deleteConnection(mixedConnection1Id); mixedInterface->deleteConnection(mixedConnection2Id); source1Interface->deleteConnection(source1ConnectionId); source2Interface->deleteConnection(source2ConnectionId); // delete interfaces mixedInterface->release(); source1Interface->release(); source2Interface->release(); OsTask::delay(500) ; RTL_WRITE("testTwoTones.rtl"); RTL_STOP; delete pSdpCodecList ; };
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; }