status_t AudioALSALoopbackController::open(const audio_devices_t output_devices, const audio_devices_t input_device) { ALOGD("+%s(), output_devices = 0x%x, input_device = 0x%x", __FUNCTION__, output_devices, input_device); AudioAutoTimeoutLock _l(mLock); AudioAutoTimeoutLock _l2(*AudioALSADriverUtility::getInstance()->getStreamSramDramLock()); // DL loopback setting memset(&mConfig, 0, sizeof(mConfig)); mConfig.channels = 2; mConfig.rate = 48000; mConfig.period_size = 1024; mConfig.period_count = 2; mConfig.format = PCM_FORMAT_S16_LE; mConfig.start_threshold = 0; mConfig.stop_threshold = 0; mConfig.silence_threshold = 0; ALOGD("+%s(), mConfig.rate=%d", __FUNCTION__,mConfig.rate); ASSERT(mPcmUL == NULL && mPcmDL == NULL); mPcmUL = pcm_open(0, 4, PCM_IN, &mConfig); mPcmDL = pcm_open(0, 4, PCM_OUT, &mConfig); ASSERT(mPcmUL != NULL && mPcmDL != NULL); ALOGV("%s(), mPcmUL = %p, mPcmDL = %p", __FUNCTION__, mPcmUL, mPcmDL); pcm_start(mPcmUL); pcm_start(mPcmDL); mHardwareResourceManager->startInputDevice(input_device); mHardwareResourceManager->startOutputDevice(output_devices, mConfig.rate); ALOGD("-%s()", __FUNCTION__); return NO_ERROR; }
status_t AudioALSACaptureDataProviderBase::openPcmDriver(const unsigned int device) { ALOGD("+%s(), pcm device = %d", __FUNCTION__, device); ASSERT(mPcm == NULL); mPcm = pcm_open(kAudioSoundCardIndex, device, PCM_IN, &mConfig); if (mPcm == NULL) { ALOGE("%s(), mPcm == NULL!!", __FUNCTION__); } else if (pcm_is_ready(mPcm) == false) { ALOGE("%s(), pcm_is_ready(%p) == false due to %s, close pcm.", __FUNCTION__, mPcm, pcm_get_error(mPcm)); pcm_close(mPcm); mPcm = NULL; } else { pcm_start(mPcm); } ALOGD("-%s(), mPcm = %p", __FUNCTION__, mPcm); ASSERT(mPcm != NULL); return NO_ERROR; }
status_t AudioALSACaptureDataProviderBTSCO::open() { ALOGD("%s()", __FUNCTION__); ASSERT(mClientLock.tryLock() != 0); // lock by base class attach AudioAutoTimeoutLock _l(mEnableLock); ASSERT(mEnable == false); // config attribute (will used in client SRC/Enh/... later) // TODO(Harvey): query this mStreamAttributeSource.audio_format = AUDIO_FORMAT_PCM_16_BIT; mStreamAttributeSource.audio_channel_mask = AUDIO_CHANNEL_IN_MONO; mStreamAttributeSource.num_channels = android_audio_legacy::AudioSystem::popCount(mStreamAttributeSource.audio_channel_mask); mStreamAttributeSource.sample_rate = mWCNChipController->GetBTCurrentSamplingRateNumber(); // pcm config mConfig.channels = mStreamAttributeSource.num_channels; mConfig.rate = mStreamAttributeSource.sample_rate; // Buffer size: 2048(period_size) * 1(ch) * 2(byte) * 4(period_count) = 16 kb mConfig.period_size = 2048; mConfig.period_count = 4; mConfig.format = PCM_FORMAT_S16_LE; mConfig.start_threshold = 0; mConfig.stop_threshold = 0; mConfig.silence_threshold = 0; ALOGD("%s(), audio_format = %d, audio_channel_mask=%x, num_channels=%d, sample_rate=%d", __FUNCTION__, mStreamAttributeSource.audio_format, mStreamAttributeSource.audio_channel_mask, mStreamAttributeSource.num_channels, mStreamAttributeSource.sample_rate); ALOGD("%s(), format = %d, channels=%d, rate=%d", __FUNCTION__, mConfig.format, mConfig.channels, mConfig.rate); OpenPCMDump(LOG_TAG); // enable pcm ASSERT(mPcm == NULL); mPcm = pcm_open(0, 12, PCM_IN | PCM_MONOTONIC, &mConfig); ASSERT(mPcm != NULL && pcm_is_ready(mPcm) == true); ALOGV("%s(), mPcm = %p", __FUNCTION__, mPcm); pcm_start(mPcm); // create reading thread mEnable = true; int ret = pthread_create(&hReadThread, NULL, AudioALSACaptureDataProviderBTSCO::readThread, (void *)this); if (ret != 0) { ALOGE("%s() create thread fail!!", __FUNCTION__); return UNKNOWN_ERROR; } return NO_ERROR; }
bool SpeechANCController::StartPCMIn(char mTypePCM, uint32_t device, pcm_config mConfig) { ALOGD("+%s(), pcm device = %d", __FUNCTION__, device); pcm *mPcm; //ASSERT(mPcm == NULL); mPcm = pcm_open(kAudioSoundCardIndex, device, PCM_IN, &mConfig); if (mPcm == NULL) { ALOGE("%s(), mPcm == NULL!!", __FUNCTION__); } else if (pcm_is_ready(mPcm) == false) { ALOGE("%s(), pcm_is_ready(%p) == false due to %s, close pcm.", __FUNCTION__, mPcm, pcm_get_error(mPcm)); pcm_close(mPcm); mPcm = NULL; } else { pcm_start(mPcm); } ALOGD("-%s(), mPcm = %p", __FUNCTION__, mPcm); ASSERT(mPcm != NULL); switch (mTypePCM) { case 0: mPcmIn_MOD = mPcm ; break; case 1: mPcmIn_IO2 = mPcm; break; case 2: mPcmIn_ADC2 = mPcm; break; } return true; }
status_t AudioALSACaptureDataProviderTDM::open() { ALOGD("%s()", __FUNCTION__); ASSERT(mClientLock.tryLock() != 0); // lock by base class attach AudioAutoTimeoutLock _l(mEnableLock); AudioAutoTimeoutLock _l2(*AudioALSADriverUtility::getInstance()->getStreamSramDramLock()); ASSERT(mEnable == false); // config attribute (will used in client SRC/Enh/... later) // TODO(Harvey): query this mStreamAttributeSource.audio_format = AUDIO_FORMAT_PCM_16_BIT; mStreamAttributeSource.audio_channel_mask = AUDIO_CHANNEL_IN_STEREO; mStreamAttributeSource.num_channels = android_audio_legacy::AudioSystem::popCount(mStreamAttributeSource.audio_channel_mask); mStreamAttributeSource.sample_rate = 44100; OpenPCMDump(LOG_TAG); // enable pcm ASSERT(mPcm == NULL); mPcm = pcm_open(0, 13, PCM_IN, &mConfig); // mPcm = pcm_open(0, 1, PCM_IN, &mConfig); ASSERT(mPcm != NULL && pcm_is_ready(mPcm) == true); ALOGV("%s(), mPcm = %p", __FUNCTION__, mPcm); pcm_start(mPcm); // create reading thread mEnable = true; int ret = pthread_create(&hReadThread, NULL, AudioALSACaptureDataProviderTDM::readThread, (void *)this); if (ret != 0) { ALOGE("%s() create thread fail!!", __FUNCTION__); return UNKNOWN_ERROR; } return NO_ERROR; }
void AudioALSAPlaybackHandlerNormal::OpenHpImpeDancePcm(void) { ALOGD("OpenHpImpeDancePcm"); // Don't lock Sram/Dram lock here, it would be locked by caller function int pcmindex = AudioALSADeviceParser::getInstance()->GetPcmIndexByString(keypcmHpimpedancePlayback); int cardindex = AudioALSADeviceParser::getInstance()->GetCardIndexByString(keypcmHpimpedancePlayback); struct pcm_params *params; params = pcm_params_get(cardindex, pcmindex, PCM_OUT); if (params == NULL) { ALOGD("Device does not exist.\n"); } int buffer_size = pcm_params_get_max(params, PCM_PARAM_BUFFER_BYTES); ALOGD("buffer_size = %d", buffer_size); pcm_params_free(params); // HW pcm config mHpImpedanceConfig.channels = 2; mHpImpedanceConfig.rate = mStreamAttributeSource->sample_rate; mHpImpedanceConfig.period_count = 2; mHpImpedanceConfig.period_size = (buffer_size / (mHpImpedanceConfig.channels * mHpImpedanceConfig.period_count)) / 2; mHpImpedanceConfig.format = PCM_FORMAT_S16_LE; mHpImpedanceConfig.start_threshold = 0; mHpImpedanceConfig.stop_threshold = 0; mHpImpedanceConfig.silence_threshold = 0; ALOGD("%s(), mHpImpedanceConfig: channels = %d, rate = %d, period_size = %d, period_count = %d, format = %d", __FUNCTION__, mHpImpedanceConfig.channels, mHpImpedanceConfig.rate, mHpImpedanceConfig.period_size, mHpImpedanceConfig.period_count, mHpImpedanceConfig.format); // open pcm driver mHpImpeDancePcm = pcm_open(cardindex, pcmindex, PCM_OUT, &mHpImpedanceConfig); if (mHpImpeDancePcm == NULL) { ALOGE("%s(), mPcm == NULL!!", __FUNCTION__); } ALOGD("-%s(), mPcm = %p", __FUNCTION__, mHpImpeDancePcm); ASSERT(mHpImpeDancePcm != NULL); pcm_start(mHpImpeDancePcm); }
status_t AudioALSAFMController::setFmDirectConnection(const bool enable, const bool bforce) { ALOGD("+%s(), enable = %d, bforce = %d", __FUNCTION__, enable, bforce); // Check Current Status if (mIsFmDirectConnectionMode == enable && bforce == false) { ALOGW("-%s(), enable = %d, bforce = %d", __FUNCTION__, enable, bforce); return INVALID_OPERATION; } // Apply if (enable == true) { mConfig.channels = 2; mConfig.rate = getFmDownlinkSamplingRate(); mConfig.period_size = 3072; mConfig.period_count = 2; mConfig.format = PCM_FORMAT_S16_LE; mConfig.start_threshold = 0; mConfig.stop_threshold = 0; mConfig.silence_threshold = 0; if (mPcm == NULL) { // Get pcm open Info int card_index = -1; int pcm_index = -1; if (WCNChipController::GetInstance()->IsFMMergeInterfaceSupported() == true) { card_index = AudioALSADeviceParser::getInstance()->GetCardIndexByString(keypcmMRGrxPlayback); pcm_index = AudioALSADeviceParser::getInstance()->GetPcmIndexByString(keypcmMRGrxPlayback); } else { card_index = AudioALSADeviceParser::getInstance()->GetCardIndexByString(keypcmFMI2SPlayback); pcm_index = AudioALSADeviceParser::getInstance()->GetPcmIndexByString(keypcmFMI2SPlayback); } ALOGD("%s(), card_index = %d, pcm_index = %d", __FUNCTION__, card_index, pcm_index); mPcm = pcm_open(card_index, pcm_index , PCM_OUT, &mConfig); ALOGD("%s(), pcm_open mPcm = %p", __FUNCTION__, mPcm); } if (mPcm == NULL || pcm_is_ready(mPcm) == false) { ALOGE("%s(), Unable to open mPcm device %u (%s)", __FUNCTION__, 6 , pcm_get_error(mPcm)); } pcm_start(mPcm); } else { if (mPcm != NULL) { pcm_stop(mPcm); pcm_close(mPcm); mPcm = NULL; } } // Update Direct Mode Status mIsFmDirectConnectionMode = enable; // Update (HW_GAIN2) Volume for Direct Mode Only if (mIsFmDirectConnectionMode == true) { setFmVolume(mFmVolume); } ALOGD("-%s(), enable = %d, bforce = %d", __FUNCTION__, enable, bforce); return NO_ERROR; }
static int stream_transfer(struct stream_transfer *stream_transfer) { struct dev_stream *stream_sender; struct dev_stream *stream_receiver; short* Srcptr; short* Drcptr; int size_transfer = 0; int ret =0; int exit_flag =0; int i=0; stream_sender = stream_transfer->stream_sender; stream_receiver = stream_transfer->stream_receiver; size_transfer = stream_sender->buf_size; #ifdef START_ZERO_BUFFER /* 消除开头杂音 */ memset(stream_sender->buf, 0, stream_sender->buf_size); pcm_write(stream_receiver->dev, stream_sender->buf, stream_sender->buf_size); #endif ret =pcm_wait(stream_sender->dev, 0); ret =pcm_wait(stream_receiver->dev, 0); pcm_stop(stream_receiver->dev); pcm_start(stream_receiver->dev); /* 消除开头pa音 */ memset(stream_sender->buf, 0, stream_sender->buf_size); pcm_write(stream_receiver->dev, stream_sender->buf, stream_sender->buf_size); while( 1 ){ if ( (!stream_transfer->voice_thread_run_flag)){ break; } #if 0 if (SNDRV_PCM_STATE_XRUN == get_pcm_state(stream_sender->dev) ){ //ALOGD("read SNDRV_PCM_STATE_XRUN "); if(ioctl(stream_sender->dev->fd, SNDRV_PCM_IOCTL_PREPARE)){ ALOGE("in read, fail to prepare SNDRV_PCM_STATE_XRUN "); } //usleep(3 * 1000); ret =pcm_wait(stream_sender->dev, 0); //ALOGD("pcm_read, pcm_wait ret=%d", ret); //ALOGD("read after prepare state:%d ",get_pcm_state(stream_sender->dev)); } #endif ret = pcm_read(stream_sender->dev, stream_sender->buf, size_transfer); if (ret != 0) { //exit_flag = 1; ALOGE("err: read codec err:%s, ret=%d", strerror(errno), ret); //break; } if ( (!stream_transfer->voice_thread_run_flag)){ break; } #if 0 if (SNDRV_PCM_STATE_XRUN == get_pcm_state(stream_receiver->dev) ){ //ALOGD("write SNDRV_PCM_STATE_XRUN "); pcm_stop(stream_receiver->dev); usleep(3 * 1000); //ALOGD("write after stop state:%d ",get_pcm_state(stream_receiver->dev)); pcm_start(stream_receiver->dev); ret =pcm_wait(stream_receiver->dev, 0); //ALOGD("pcm_write, pcm_wait ret=%d", ret); //usleep(3 * 1000); //ALOGD("write after prepare state:%d ",get_pcm_state(stream_receiver->dev)); } #endif ret = pcm_write(stream_receiver->dev, stream_sender->buf, size_transfer); if (ret != 0) { //exit_flag = 1; ALOGE("err: write pcm err:%s, ret=%d", strerror(errno), ret); } if ( (!stream_transfer->voice_thread_run_flag)){ break; } if (stream_transfer->record_flag == 1){ //是上行,还是下行. if (stream_transfer->voice_direction == UPSTREAM){ Srcptr = (short*)(stream_sender->buf); Drcptr = (short*)(record_data.record_buf + (record_data.lenwriteup%record_data.record_lenth)); if(record_data.lenwriteup >= record_data.lenwritedown) { memcpy(Drcptr,Srcptr,size_transfer); } else { int i; for(i=0;i<size_transfer/2;i++,Drcptr++) { *Drcptr = (*Drcptr + *Srcptr++)/2; } record_data.lenwrite += size_transfer; } record_data.lenwriteup += size_transfer; //ALOGD("stream is upload"); } else { Srcptr = (short*)(stream_sender->buf); Drcptr = (short*)(record_data.record_buf + (record_data.lenwritedown%record_data.record_lenth)); if(record_data.lenwritedown >= record_data.lenwriteup) { memcpy(Drcptr,Srcptr,size_transfer); } else { for(i=0;i<size_transfer/2;i++,Drcptr++) { *Drcptr = ((int)*Drcptr + (int)(*Srcptr++))/2; } record_data.lenwrite += size_transfer; } record_data.lenwritedown += size_transfer; } sem_post(&g_sem_record); } if ( (!stream_transfer->voice_thread_run_flag)){ break; } } return 0; }
status_t AudioALSACaptureDataProviderEchoRefExt::open() { ALOGD("%s()", __FUNCTION__); ASSERT(mClientLock.tryLock() != 0); // lock by base class attach AudioAutoTimeoutLock _l(mEnableLock); AudioAutoTimeoutLock _l2(*AudioALSADriverUtility::getInstance()->getStreamSramDramLock()); ASSERT(mEnable == false); AudioALSASampleRateController *pAudioALSASampleRateController = AudioALSASampleRateController::getInstance(); pAudioALSASampleRateController->setScenarioStatus(PLAYBACK_SCENARIO_ECHO_REF_EXT); // config attribute (will used in client SRC/Enh/... later) // TODO(Sam): query the mConfig? mStreamAttributeSource.audio_format = AUDIO_FORMAT_PCM_16_BIT; mStreamAttributeSource.audio_channel_mask = AUDIO_CHANNEL_IN_STEREO; mStreamAttributeSource.num_channels = android_audio_legacy::AudioSystem::popCount(mStreamAttributeSource.audio_channel_mask); mStreamAttributeSource.sample_rate = AudioALSASampleRateController::getInstance()->getPrimaryStreamOutSampleRate(); mConfig.channels = mStreamAttributeSource.num_channels; mConfig.rate = mStreamAttributeSource.sample_rate; // Buffer size: 2048(period_size) * 2(ch) * 2(byte) * 8(period_count) = 64 kb mConfig.period_size = 2048; mConfig.period_count = 8; mConfig.format = PCM_FORMAT_S16_LE; mConfig.start_threshold = 0; mConfig.stop_threshold = 0; mConfig.silence_threshold = 0; #if 0 //latency time, set as DataProvider buffer size mStreamAttributeSource.latency = (kReadBufferSize * 1000) / (mStreamAttributeSource.num_channels * mStreamAttributeSource.sample_rate * (mStreamAttributeSource.audio_format == AUDIO_FORMAT_PCM_8_BIT ? 1 : //8 1byte/frame (mStreamAttributeSource.audio_format == AUDIO_FORMAT_PCM_32_BIT ? 4 : //24bit 3bytes/frame 2))); //default 2bytes/sample #else //latency time, set as hardware buffer size mStreamAttributeSource.latency = (mConfig.period_size * mConfig.period_count * 1000) / mConfig.rate; #endif ALOGD("%s(), audio_format = %d, audio_channel_mask=%x, num_channels=%d, sample_rate=%d, latency=%dms", __FUNCTION__, mStreamAttributeSource.audio_format, mStreamAttributeSource.audio_channel_mask, mStreamAttributeSource.num_channels, mStreamAttributeSource.sample_rate, mStreamAttributeSource.latency); ALOGD("%s(), format = %d, channels=%d, rate=%d", __FUNCTION__, mConfig.format, mConfig.channels, mConfig.rate); #ifdef NXP_SMARTPA_SUPPORT MTK_Tfa98xx_EchoReferenceConfigure(1); #endif OpenPCMDump(LOG_TAG); // enable pcm ASSERT(mPcm == NULL); mPcm = pcm_open(0, 16, PCM_IN | PCM_MONOTONIC, &mConfig); ASSERT(mPcm != NULL && pcm_is_ready(mPcm) == true); pcm_start(mPcm); // create reading thread mEnable = true; int ret = pthread_create(&hReadThread, NULL, AudioALSACaptureDataProviderEchoRefExt::readThread, (void *)this); if (ret != 0) { ALOGE("%s() create thread fail!!", __FUNCTION__); return UNKNOWN_ERROR; } return NO_ERROR; }
int main(int ac, char** av) { pcm_desc_t desc; pcm_handle_t ipcm; pcm_handle_t opcm; mod_handle_t mod; int err; cmdline_t cmd; size_t i; err = -1; if (get_cmdline(&cmd, ac - 1, av + 1)) goto on_error_0; pcm_init_desc(&desc); desc.flags |= PCM_FLAG_IN; if (cmd.flags & CMDLINE_FLAG(IPCM)) desc.name = cmd.ipcm; if (pcm_open(&ipcm, &desc)) goto on_error_0; pcm_init_desc(&desc); desc.flags |= PCM_FLAG_OUT; if (cmd.flags & CMDLINE_FLAG(OPCM)) desc.name = cmd.opcm; if (pcm_open(&opcm, &desc)) goto on_error_1; if (mod_open(&mod, 512)) goto on_error_2; if (pcm_start(&ipcm)) goto on_error_3; if (pcm_start(&opcm)) goto on_error_3; signal(SIGINT, on_sigint); for (i = 0; is_sigint == 0; i += 1) { size_t nsampl; size_t navail; size_t off; /* read ipcm */ err = snd_pcm_wait(ipcm.pcm, -1); if (is_sigint) break ; if (err < 0) goto on_ipcm_xrun; navail = (size_t)snd_pcm_avail_update(ipcm.pcm); if (ipcm.wpos >= ipcm.rpos) nsampl = ipcm.nsampl - ipcm.wpos; else nsampl = ipcm.rpos - ipcm.wpos; if (nsampl > navail) nsampl = navail; off = ipcm.wpos * ipcm.scale; err = snd_pcm_readi(ipcm.pcm, ipcm.buf + off, nsampl); if (err < 0) goto on_ipcm_xrun; ipcm.wpos += (size_t)err; if (ipcm.wpos == ipcm.nsampl) ipcm.wpos = 0; /* apply modifier */ redo_mod: if (ipcm.wpos >= ipcm.rpos) nsampl = ipcm.wpos - ipcm.rpos; else nsampl = ipcm.nsampl - ipcm.rpos + ipcm.wpos; if (cmd.flags & CMDLINE_FLAG(FILT)) { const size_t n = mod_apply (&mod, ipcm.buf, ipcm.nsampl, ipcm.rpos, nsampl); nsampl = n; } if (nsampl == 0) continue ; if ((ipcm.rpos + nsampl) > ipcm.nsampl) { const size_t n = ipcm.nsampl - ipcm.rpos; off = ipcm.rpos * ipcm.scale; err = snd_pcm_writei(opcm.pcm, ipcm.buf + off, n); if (err < 0) goto on_opcm_xrun; nsampl -= n; ipcm.rpos = 0; } off = ipcm.rpos * ipcm.scale; err = snd_pcm_writei(opcm.pcm, ipcm.buf + off, nsampl); if (err < 0) goto on_opcm_xrun; ipcm.rpos += nsampl; if (ipcm.rpos == ipcm.nsampl) ipcm.rpos = 0; goto redo_mod; continue ; on_ipcm_xrun: if (pcm_recover_xrun(&ipcm, err)) PERROR_GOTO("", on_error_2); continue ; on_opcm_xrun: if (pcm_recover_xrun(&opcm, err)) PERROR_GOTO("", on_error_2); continue ; } err = 0; on_error_3: mod_close(&mod); on_error_2: pcm_close(&opcm); on_error_1: pcm_close(&ipcm); on_error_0: return err; }