SLboolean AudioRecorder::Stop(void) { // in case already recording, stop recording and clear buffer queue SLuint32 curState; SLresult result = (*recItf_)->GetRecordState(recItf_, &curState); SLASSERT(result); if( curState == SL_RECORDSTATE_STOPPED) { return SL_BOOLEAN_TRUE; } result = (*recItf_)->SetRecordState(recItf_, SL_RECORDSTATE_STOPPED); SLASSERT(result); result = (*recBufQueueItf_)->Clear(recBufQueueItf_); SLASSERT(result); sample_buf *buf = NULL; while(devShadowQueue_->front(&buf)) { devShadowQueue_->pop(); freeQueue_->push(buf); } #ifdef ENABLE_LOG recLog_->flush(); #endif return SL_BOOLEAN_TRUE; }
SLboolean AudioRecorder::Start(void) { if(!freeQueue_ || !recQueue_ || !devShadowQueue_) { LOGE("====NULL poiter to Start(%p, %p, %p)", freeQueue_, recQueue_, devShadowQueue_); return SL_BOOLEAN_FALSE; } audioBufCount = 0; SLresult result; // in case already recording, stop recording and clear buffer queue result = (*recItf_)->SetRecordState(recItf_, SL_RECORDSTATE_STOPPED); SLASSERT(result); result = (*recBufQueueItf_)->Clear(recBufQueueItf_); SLASSERT(result); for(int i =0; i < RECORD_DEVICE_KICKSTART_BUF_COUNT; i++ ) { sample_buf *buf = NULL; if(!freeQueue_->front(&buf)) { LOGE("=====OutOfFreeBuffers @ startingRecording @ (%d)", i); break; } freeQueue_->pop(); assert(buf->buf_ && buf->cap_ && !buf->size_); result = (*recBufQueueItf_)->Enqueue(recBufQueueItf_, buf->buf_, buf->cap_); SLASSERT(result); devShadowQueue_->push(buf); } result = (*recItf_)->SetRecordState(recItf_, SL_RECORDSTATE_RECORDING); SLASSERT(result); return (result == SL_RESULT_SUCCESS? SL_BOOLEAN_TRUE:SL_BOOLEAN_FALSE); }
void createSLEngine(jint sampleRate, jint framesPerBuf) { SLresult result; memset(&engine, 0, sizeof(engine)); engine.fastPathSampleRate_ = static_cast<SLmilliHertz>(sampleRate) * 1000; engine.fastPathFramesPerBuf_ = static_cast<uint32_t>(framesPerBuf); engine.sampleChannels_ = AUDIO_SAMPLE_CHANNELS; engine.bitsPerSample_ = SL_PCMSAMPLEFORMAT_FIXED_16; result = slCreateEngine(&engine.slEngineObj_, 0, NULL, 0, NULL, NULL); SLASSERT(result); result = (*engine.slEngineObj_)->Realize(engine.slEngineObj_, SL_BOOLEAN_FALSE); SLASSERT(result); result = (*engine.slEngineObj_)->GetInterface(engine.slEngineObj_, SL_IID_ENGINE, &engine.slEngineItf_); SLASSERT(result); /* compute the RECOMMENDED fast audio buffer size: * the lower latency required * *) the smaller the buffer should be (adjust it here) AND * *) the less buffering should be before starting player AFTER * receiving the recordered buffer * Adjust the bufSize here to fit your bill [before it busts] */ uint32_t bufSize = engine.fastPathFramesPerBuf_ * engine.sampleChannels_ * engine.bitsPerSample_; bufSize = (bufSize + 7) >> 3; // bits --> byte engine.buf_ = new uint8_t [BUF_COUNT * bufSize]; engine.bufSize_ = bufSize; assert(engine.buf_); }
AudioRecorder::AudioRecorder(SampleFormat *sampleFormat, SLEngineItf slEngine) : freeQueue_(nullptr), devShadowQueue_(nullptr), recQueue_(nullptr), callback_(nullptr) { SLresult result; sampleInfo_ = *sampleFormat; SLAndroidDataFormat_PCM_EX format_pcm; ConvertToSLSampleFormat(&format_pcm, &sampleInfo_); // configure audio source SLDataLocator_IODevice loc_dev = {SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT, SL_DEFAULTDEVICEID_AUDIOINPUT, NULL }; SLDataSource audioSrc = {&loc_dev, NULL }; // configure audio sink SLDataLocator_AndroidSimpleBufferQueue loc_bq = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, DEVICE_SHADOW_BUFFER_QUEUE_LEN }; SLDataSink audioSnk = {&loc_bq, &format_pcm}; // create audio recorder // (requires the RECORD_AUDIO permission) const SLInterfaceID id[1] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE}; const SLboolean req[1] = {SL_BOOLEAN_TRUE}; result = (*slEngine)->CreateAudioRecorder(slEngine, &recObjectItf_, &audioSrc, &audioSnk, 1, id, req); SLASSERT(result); result = (*recObjectItf_)->Realize(recObjectItf_, SL_BOOLEAN_FALSE); SLASSERT(result); result = (*recObjectItf_)->GetInterface(recObjectItf_, SL_IID_RECORD, &recItf_); SLASSERT(result); result = (*recObjectItf_)->GetInterface(recObjectItf_, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &recBufQueueItf_); SLASSERT(result); result = (*recBufQueueItf_)->RegisterCallback(recBufQueueItf_, bqRecorderCallback, this); SLASSERT(result); devShadowQueue_ = new AudioQueue(DEVICE_SHADOW_BUFFER_QUEUE_LEN); assert(devShadowQueue_); #ifdef ENABLE_LOG std::string name = "rec"; recLog_ = new AndroidLog(name); #endif }
void AudioRecorder::ProcessSLCallback(SLAndroidSimpleBufferQueueItf bq) { #ifdef ENABLE_LOG recLog_->logTime(); #endif assert(bq == recBufQueueItf_); sample_buf *dataBuf = NULL; devShadowQueue_->front(&dataBuf); devShadowQueue_->pop(); dataBuf->size_ = dataBuf->cap_; //device only calls us when it is really full recQueue_->push(dataBuf); sample_buf* freeBuf; while (freeQueue_->front(&freeBuf) && devShadowQueue_->push(freeBuf)) { freeQueue_->pop(); SLresult result = (*bq)->Enqueue(bq, freeBuf->buf_, freeBuf->cap_); SLASSERT(result); } /* * PLAY_KICKSTART_BUFFER_COUNT: # of buffers cached in the queue before * STARTING player. it is defined in audio_common.h. Whatever buffered * here is the part of the audio LATENCY! adjust to fit your bill [ until * it busts ] */ if(++audioBufCount == PLAY_KICKSTART_BUFFER_COUNT && callback_) { callback_(ctx_, ENGINE_SERVICE_MSG_KICKSTART_PLAYER, NULL); } // should leave the device to sleep to save power if no buffers if (devShadowQueue_->size() == 0) { (*recItf_)->SetRecordState(recItf_, SL_RECORDSTATE_STOPPED); } }
bool UDPPacketReceiver::processRecv(bool expectingPacket) { Address srcAddr; UDPPacket* pChannelReceiveWindow = CREATE_POOL_OBJECT(UDPPacket); int len = pChannelReceiveWindow->recvFromEndPoint(*m_pEndPoint, &srcAddr); if(len <= 0) { RELEASE_POOL_OBJECT(UDPPacket, pChannelReceiveWindow); PacketReceiver::RecvState rstate = this->checkSocketErrors(len, expectingPacket); return rstate == PacketReceiver::RECV_STATE_CONTINUE; } Channel* pSrcChannel = m_pNetworkInterface->findChannel(srcAddr); if(pSrcChannel == NULL) { EndPoint* pNewEndPoint = CREATE_POOL_OBJECT(EndPoint); pNewEndPoint->addr(srcAddr.m_port, srcAddr.m_ip); pSrcChannel = CREATE_POOL_OBJECT(Channel, m_pNetworkInterface, pNewEndPoint, nullptr, PROTOCOL_UDP); if (!pSrcChannel) { pSrcChannel->destroy(); RELEASE_POOL_OBJECT(Channel, pSrcChannel); RELEASE_POOL_OBJECT(UDPPacket, pChannelReceiveWindow); return false; } if(!m_pNetworkInterface->registerChannel(pSrcChannel)) { RELEASE_POOL_OBJECT(UDPPacket, pChannelReceiveWindow); pSrcChannel->destroy(); RELEASE_POOL_OBJECT(Channel, pSrcChannel); return false; } } SLASSERT(pSrcChannel != NULL, "wtf"); if(pSrcChannel->isCondemn()) { RELEASE_POOL_OBJECT(UDPPacket, pChannelReceiveWindow); m_pNetworkInterface->deregisterChannel(pSrcChannel); pSrcChannel->destroy(); RELEASE_POOL_OBJECT(Channel, pSrcChannel); return false; } Reason ret = this->processPacket(pSrcChannel, pChannelReceiveWindow); if(ret != REASON_SUCCESS) { } return true; }
bool CSLListener::start(const char* pszIP, uint16 wPort, bool bReUseAddr /* = true */) { SLASSERT(m_pNetworkInterface, "wtf"); if (m_pNetworkInterface == nullptr || m_pListenerReceiver == nullptr || m_dwRecvBufSize <= 0 || m_dwSendBufSize <= 0){ return false; } return m_pNetworkInterface->createListeningSocket(pszIP, wPort, &m_pListenEndPoint, m_pListenerReceiver, m_dwRecvBufSize, m_dwSendBufSize); }
bool TCPPacketSender::processSend(Channel* pChannel) { bool noticed = pChannel == NULL; //如果由poller通知的,我們需要通過地址找到channel if(noticed) { pChannel = getChannel(); } SLASSERT(pChannel != NULL, "wtf"); if(pChannel->isCondemn()) { return false; } if(!pChannel->isConnected()){ return false; } Channel::Bundles& bundles = pChannel->bundles(); Reason reason = REASON_SUCCESS; Channel::Bundles::iterator iter = bundles.begin(); for (; iter != bundles.end(); ++iter) { Bundle::Packets& packets = (*iter)->packets(); Bundle::Packets::iterator iter1 = packets.begin(); for (; iter1 != packets.end(); ++iter1) { reason = processPacket(pChannel, (*iter1)); if(reason != REASON_SUCCESS) break; else { RECLAIM_PACKET((*iter)->isTCPPacket(), (*iter1)); } } if(reason == REASON_SUCCESS) { packets.clear(); RELEASE_POOL_OBJECT(Bundle, *iter); } else { packets.erase(packets.begin(), iter1); bundles.erase(bundles.begin(), iter); if(reason == REASON_RESOURCE_UNAVAILABLE) { } else { onGetError(pChannel); } return false; } } bundles.clear(); if(noticed) pChannel->onSendCompleted(); return true; }