游戏电视苹果数码历史美丽
投稿投诉
美丽时装
彩妆资讯
历史明星
乐活安卓
数码常识
驾车健康
苹果问答
网络发型
电视车载
室内电影
游戏科学
音乐整形

AudioUnit(一)

  最近一直在做iOS音频相关技术的项目,期间在官方及网上的资料文档也学习了很多,当然,iOS平台中音频相关技术还是有很多方面的,这里我先总体概述下,然后以IOAudioUnit为例对其概念,基本用法和思路进行讲解,可能不够全面,一些细节需要自行查找相关文档。后面我会对github上一个开源的音频引擎框架进行源码分析,来展现在更复杂的音频技术应用场景下可能的设计及实现方式。
  本文图片及大部分技术概念阐述均来自apple官网1、CoreAudio
  CoreAudio是iOS和MAC系统中的关于数字音频处理的基础设施,它是应用程序用来处理音频的一组软件框架,所有关于iOS音频开发的接口都是由CoreAudio来提供或者经过它提供的接口来进行封装的。Apple官方对CoreAudio的框架分层图示如下:
  coreaudiolayers。png2、LowLevel
  该主要在MAC上的音频APP实现中并且需要最大限度的实时性能的情况下使用,大部分音频APP不需要使用该层的服务。而且,在iOS上也提供了具备较高实时性能的高层API达到你的需求。例如OpenAL,在游戏中具备与IO直接调用的实时音频处理能力IOKit,与硬件驱动交互AudioHAL,音频硬件抽象层,使API调用与实际硬件相分离,保持独立CoreMIDI,为MIDI流和设备提供软件抽象工作层HostTimeServices,访问电脑硬件时钟3、MidLevel
  该层功能比较齐全,包括音频数据格式转换,音频文件读写,音频流解析,插件工作支持等AudioConvertServices负责音频数据格式的转换AudioFileServices负责音频数据的读写AudioUnitServices和AudioProcessingGraphServices支持均衡器和混音器等数字信号处理的插件AudioFileScreamServices负责流解析CoreAudioClockServices负责音频音频时钟同步4、HighLevel
  是一组从低层接口组合起来的高层应用,基本上我们很多关于音频开发的工作在这一层就可以完成AudioQueueServices提供录制、播放、暂停、循环、和同步音频它自动采用必要的编解码器处理压缩的音频格式AVAudioPlayer是专为IOS平台提供的基于ObjectiveC接口的音频播放类,可以支持iOS所支持的所有音频的播放ExtendedAudioFileServices由AudioFile与AudioConverter组合而成,提供压缩及无压缩音频文件的读写能力OpenAL是CoreAudio对OpenAL标准的实现,可以播放3D混音效果5、不同场景所需要的APIService只实现音频的播放,没有其他需求,AVAudioPlayer就可以满足需求。它的接口使用简单,不用关心其中的细节,通常只提供给它一个播放源的URL地址,并且调用其play、pause、stop等方法进行控制,observer其播放状态更新UI即可
  APP需要对音频进行流播放,就需要AudioFileStreamer加AudioQueue,将网络或者本地的流读取到内存,提交给AudioFileStreamer解析分离音频帧,分离出来的音频帧可以送给AudioQueue进行解码和播放可参考AudioStreamerFreeStreamerAFSoundManager
  APP需要需要对音频施加音效(均衡器、混响器),就是除了数据的读取和解析以外还需要用到AudioConverter或者Codec来把音频数据转换成PCM数据,再由AudioUnitAUGraph来进行音效处理和播放可参考DouAudioStreamerTheAmazingAudioEngineAudioKit6、AudioUnit
  iOS提供了混音、均衡、格式转换、实时IO录制、回放、离线渲染、语音对讲(VoIP)等音频处理插件,它们都属于不同的AudioUnit,支持动态载入和使用。AudioUnit可以单独创建使用,但更多的是被组合使用在AudioProcessingGraph容器中以达到多样的处理需要,例如下面的一种场景:
  APP持有的AudioProcessingGraph容器中包含两个EQUnit、一个MixerUnit、一个IOUnit,APP将磁盘或者网络中的两路流数据分别通过EQUnit进行均衡处理,然后在MixerUnit经过混音处理为一路,进入IOUnit将此路数据送往硬件去播放。在这整个流程中,APP随时可以调整设置AUGraph及其中每个Unit的工作状态及参数,动态性的接入或者移出指定的Unit,并且保证线程安全。
  C音视频学习资料免费获取方法:关注音视频开发T哥,点击链接即可免费获取2023年最新C音视频开发进阶独家免费学习大礼包!6。1AudioUnit类型:
  IO:RemoteIO、VoiceProcessingIO、GenericOutputMixing:3DMixer、MutichannelMixerEffect:iPodEqualizerFormatConversion:FormatConverter6。2AudioUnit构建方式
  创建AudioUnit有两种途径,以IOUnit为例,一种是直接调用unit接口创建,一种是通过AudioUnitGraph创建,下面是两种创建方式的基本流程和相关代码:6。3UnitAPI方式(RemoteIOUnit)createIOUnitBOOLresultNO;AudioComponentDescriptionoutputDescription{0};outputDescription。componentTypekAudioUnitTypeOutput;outputDescription。componentSubTypekAudioUnitSubTypeRemoteIO;outputDescription。componentManufacturerkAudioUnitManufacturerApple;outputDescription。componentFlags0;outputDescription。componentFlagsMask0;AudioComponentcompAudioComponentFindNext(NULL,outputDescription);resultCheckOSStatus(AudioComponentInstanceNew(comp,mVoipUnit),couldntcreateanewinstanceofRemoteIO);if(!result)returnresult;configIOEnablestatusUInt32flag1;resultCheckOSStatus(AudioUnitSetProperty(mVoipUnit,kAudioOutputUnitPropertyEnableIO,kAudioUnitScopeOutput,kOutputBus,flag,sizeof(flag)),couldnotenableoutputonRemoteIO);if(!result)returnresult;resultCheckOSStatus(AudioUnitSetProperty(mVoipUnit,kAudioOutputUnitPropertyEnableIO,kAudioUnitScopeInput,kInputBus,flag,sizeof(flag)),AudioUnitSetPropertyEnableIO);if(!result)returnresult;ConfigdefaultformatresultCheckOSStatus(AudioUnitSetProperty(mVoipUnit,kAudioUnitPropertyStreamFormat,kAudioUnitScopeOutput,kInputBus,inputAudioDescription,sizeof(inputAudioDescription)),couldntsettheinputclientformatonRemoteIO);if(!result)returnresult;resultCheckOSStatus(AudioUnitSetProperty(mVoipUnit,kAudioUnitPropertyStreamFormat,kAudioUnitScopeInput,kOutputBus,outputAudioDescription,sizeof(outputAudioDescription)),couldntsettheoutputclientformatonRemoteIO);if(!result)returnresult;SettheMaximumFramesPerSliceproperty。ThispropertyisusedtodescribetoanaudiounitthemaximumnumberofsamplesitwillbeaskedtoproduceonanysinglegivencalltoAudioUnitRenderUInt32maxFramesPerSlice4096;resultCheckOSStatus(AudioUnitSetProperty(mVoipUnit,kAudioUnitPropertyMaximumFramesPerSlice,kAudioUnitScopeGlobal,0,maxFramesPerSlice,sizeof(UInt32)),couldntsetmaxframespersliceonRemoteIO);if(!result)returnresult;SettherecordcallbackAURenderCallbackStructrecordCallback;recordCallback。inputProcrecordCallbackFunc;recordCallback。inputProcRefCon(bridgevoidNullable)(self);resultCheckOSStatus(AudioUnitSetProperty(mVoipUnit,kAudioOutputUnitPropertySetInputCallback,kAudioUnitScopeGlobal,kInputBus,recordCallback,sizeof(recordCallback)),couldntsetrecordcallbackonRemoteIO);if(!result)returnresult;SettheplaybackcallbackAURenderCallbackStructplaybackCallback;playbackCallback。inputProcplaybackCallbackFunc;playbackCallback。inputProcRefCon(bridgevoidNullable)(self);resultCheckOSStatus(AudioUnitSetProperty(mVoipUnit,kAudioUnitPropertySetRenderCallback,kAudioUnitScopeGlobal,kOutputBus,playbackCallback,sizeof(playbackCallback)),couldntsetplaybackcallbackonRemoteIO);if(!result)returnresult;setbufferallocateflag0;resultCheckOSStatus(AudioUnitSetProperty(mVoipUnit,kAudioUnitPropertyShouldAllocateBuffer,kAudioUnitScopeOutput,kInputBus,flag,sizeof(flag)),couldntsetpropertyforShouldAllocateBuffer);if(!result)returnresult;InitializetheoutputIOinstanceresultCheckOSStatus(AudioUnitInitialize(mVoipUnit),couldntinitializeVoiceProcessingIOinstance);if(!result)returnresult;returnYES;6。4AUGraph方式(MultiChannelMixerUnitRemoteIOUnit)createAUGraphBOOLresultNO;resultCheckOSStatus(NewAUGraph(processingGraph),couldntcreateanewinstanceofAUGraph);if(!result)returnresult;IOunitAudioComponentDescriptioniOUnitDescription;iOUnitDescription。componentTypekAudioUnitTypeOutput;iOUnitDescription。componentSubTypekAudioUnitSubTypeRemoteIO;iOUnitDescription。componentManufacturerkAudioUnitManufacturerApple;iOUnitDescription。componentFlags0;iOUnitDescription。componentFlagsMask0;MultichannelmixerunitAudioComponentDescriptionMixerUnitDescription;MixerUnitDescription。componentTypekAudioUnitTypeMixer;MixerUnitDescription。componentSubTypekAudioUnitSubTypeMultiChannelMixer;MixerUnitDescription。componentManufacturerkAudioUnitManufacturerApple;MixerUnitDescription。componentFlags0;MixerUnitDescription。componentFlagsMask0;AUNodeiONode;nodeforIOunitAUNodemixerNode;nodeforMultichannelMixerunitresultCheckOSStatus(AUGraphAddNode(processingGraph,iOUnitDescription,iONode),couldntaddanodeinstanceofkAudioUnitSubTypeRemoteIO);if(!result)returnresult;resultCheckOSStatus(AUGraphAddNode(processingGraph,MixerUnitDescription,mixerNode),couldntaddanodeinstanceofmixerunit);if(!result)returnresult;opentheAUGraphresultCheckOSStatus(AUGraphOpen(processingGraph),couldntgetinstanceofmixerunit);if(!result)returnresult;ObtainunitinstanceresultCheckOSStatus(AUGraphNodeInfo(processingGraph,mixerNode,NULL,mMixerUnit),couldntgetinstanceofmixerunit);if(!result)returnresult;resultCheckOSStatus(AUGraphNodeInfo(processingGraph,iONode,NULL,mVoipUnit),couldntgetanewinstanceofremoteiounit);if(!result)returnresult;UInt32busCount2;buscountformixerunitinputUInt32guitarBus0;mixerunitbus0willbestereoandwilltaketheguitarsoundUInt32beatsBus1;mixerunitbus1willbemonoandwilltakethebeatssoundresultCheckOSStatus(AudioUnitSetProperty(mMixerUnit,kAudioUnitPropertyElementCount,kAudioUnitScopeInput,0,busCount,sizeof(busCount)),couldnotsetmixerunitinputbuscount);if(!result)returnresult;UInt32maximumFramesPerSlice4096;resultCheckOSStatus(AudioUnitSetProperty(mMixerUnit,kAudioUnitPropertyMaximumFramesPerSlice,kAudioUnitScopeGlobal,0,maximumFramesPerSlice,sizeof(maximumFramesPerSlice)),couldnotsetmixerunitmaximumframeperslice);if(!result)returnresult;Attachtheinputrendercallbackandcontexttoeachinputbusfor(UInt16busNumber0;busNumberbusCount;busNumber){SetupthestruturethatcontainstheinputrendercallbackAURenderCallbackStructplaybackCallback;playbackCallback。inputProcplaybackCallbackFunc;playbackCallback。inputProcRefCon(bridgevoidNullable)(self);NSLog(Registeringtherendercallbackwithmixerunitinputbusu,busNumber);SetacallbackforthespecifiednodesspecifiedinputresultCheckOSStatus(AUGraphSetNodeInputCallback(processingGraph,mixerNode,busNumber,playbackCallback),couldntsetplaybackcallbackonmixerunit);if(!result)returnresult;}ConfigmixerunitinputdefaultformatresultCheckOSStatus(AudioUnitSetProperty(mMixerUnit,kAudioUnitPropertyStreamFormat,kAudioUnitScopeInput,guitarBus,outputAudioDescription,sizeof(outputAudioDescription)),couldntsettheinput0clientformatonmixerunit);if(!result)returnresult;resultCheckOSStatus(AudioUnitSetProperty(mMixerUnit,kAudioUnitPropertyStreamFormat,kAudioUnitScopeInput,beatsBus,outputAudioDescription,sizeof(outputAudioDescription)),couldntsettheinput1clientformatonmixerunit);if(!result)returnresult;Float64graphSampleRate44100。0;Hertz;resultCheckOSStatus(AudioUnitSetProperty(mMixerUnit,kAudioUnitPropertySampleRate,kAudioUnitScopeOutput,0,graphSampleRate,sizeof(graphSampleRate)),couldntsettheoutputclientformatonmixerunit);if(!result)returnresult;configvoidunitIOEnablestatusUInt32flag1;resultCheckOSStatus(AudioUnitSetProperty(mVoipUnit,kAudioOutputUnitPropertyEnableIO,kAudioUnitScopeOutput,kOutputBus,flag,sizeof(flag)),couldnotenableoutputonkAudioUnitSubTypeRemoteIO);if(!result)returnresult;resultCheckOSStatus(AudioUnitSetProperty(mVoipUnit,kAudioOutputUnitPropertyEnableIO,kAudioUnitScopeInput,kInputBus,flag,sizeof(flag)),couldnotenableinputonkAudioUnitSubTypeRemoteIO);if(!result)returnresult;configvoipunitdefaultformatresultCheckOSStatus(AudioUnitSetProperty(mVoipUnit,kAudioUnitPropertyStreamFormat,kAudioUnitScopeOutput,kInputBus,inputAudioDescription,sizeof(inputAudioDescription)),couldntsettheinputclientformatonkAudioUnitSubTypeRemoteIO);if(!result)returnresult;UInt32maxFramesPerSlice4096;resultCheckOSStatus(AudioUnitSetProperty(mVoipUnit,kAudioUnitPropertyMaximumFramesPerSlice,kAudioUnitScopeGlobal,0,maxFramesPerSlice,sizeof(UInt32)),couldntsetmaxframespersliceonkAudioUnitSubTypeRemoteIO);if(!result)returnresult;SettherecordcallbackAURenderCallbackStructrecordCallback;recordCallback。inputProcrecordCallbackFunc;recordCallback。inputProcRefCon(bridgevoidNullable)(self);resultCheckOSStatus(AudioUnitSetProperty(mVoipUnit,kAudioOutputUnitPropertySetInputCallback,kAudioUnitScopeGlobal,kInputBus,recordCallback,sizeof(recordCallback)),couldntsetrecordcallbackonkAudioUnitSubTypeRemoteIO);if(!result)returnresult;setbufferallocateflag0;resultCheckOSStatus(AudioUnitSetProperty(mVoipUnit,kAudioUnitPropertyShouldAllocateBuffer,kAudioUnitScopeOutput,kInputBus,flag,sizeof(flag)),couldntsetpropertyforShouldAllocateBuffer);if(!result)returnresult;InitializetheoutputIOinstanceresultCheckOSStatus(AUGraphConnectNodeInput(processingGraph,mixerNode,sourcenode0,sourcenodeoutputbusnumberiONode,destinationnode0desintationnodeinputbusnumber),couldntconnectionodetomixernode);if(!result)returnresult;resultCheckOSStatus(AUGraphInitialize(processingGraph),AUGraphInitializefailed);if(!result)returnresult;returnYES;6。5AudioUnit数据的输入输出方式
  Unit处理音频数据,都要经过一个输入和输出过程,设置输入输出的音频格式(可以相同或者不同),两个Unit对接即是将一个Unit的输入接到另一个Unit的输出,或者将一个Unit的输出接到另一个Unit的输入,需要注意的是在对接点要保证AudioFormat的一致性。以RemoteIOUnit为例,结构如下图所示:
  一个IOUnit包含两个实体对象,两个实体对象(Element0、Element1)相互独立,根据需求可通过kAudioOutputUnitPropertyEnableIO属性去开关它们。Element1与硬件输入连接,并且Element1的输入域(inputscope)对你不可见,你只能读取它的输出域的数据及设置其输出域的音频格式;Element0与硬件输出连接,并且Element0的输出域(ouputscope)对你不可见,你只能写入它的输入域的数据及设置其输入域的音频格式。
  如何将输入设备采集的数据抓出来,又如何将处理后的数据送到输出设备呢?通过AURenderCallbackStruct结构,将定义的两个回调静态方法地址设置到需要的Element01上,当Unit配置完毕并且运行后,Unit调度线程会按照当前设备状态及音频格式安排调度周期,循环往复的调用你提供的录制与播放回调方法,样例代码如下:forrecordcallback,readaudiodatafrombufferliststaticOSStatusrecordCallbackFunc(voidinRefCon,AudioUnitRenderActionFlagsioActionFlags,constAudioTimeStampinTimeStamp,UInt32inBusNumber,UInt32inNumberFrames,AudioBufferListioData){ASAudioEngineSingleUengine(bridgeASAudioEngineSingleU)inRefCon;OSStatuserrnoErr;if(engine。audioChainIsBeingReconstructedNO){autoreleasepool{AudioBufferListbufList〔enginegetBufferList:inNumberFrames〕;errAudioUnitRender(〔enginerecorderUnit〕,ioActionFlags,inTimeStamp,inBusNumber,inNumberFrames,bufList);if(err){HMLogDebug(LogModuleAudio,AudioUnitRendererrorcoded,err);}else{AudioBufferbufferbufList。mBuffers〔0〕;NSDatapcmBlock〔NSDatadataWithBytes:buffer。mDatalength:buffer。mDataByteSize〕;〔enginedidRecordData:pcmBlock〕;}}}returnerr;}forplaycallback,fillaudiodatatobufferliststaticOSStatusplaybackCallbackFunc(voidinRefCon,AudioUnitRenderActionFlagsioActionFlags,constAudioTimeStampinTimeStamp,UInt32inBusNumber,UInt32inNumberFrames,AudioBufferListioData){ASAudioEngineSingleUengine(bridgeASAudioEngineSingleU)inRefCon;OSStatuserrnoErr;if(engine。audioChainIsBeingReconstructedNO){for(inti0;iioDatamNumberBuffers;i){autoreleasepool{AudioBufferbufferioDatamBuffers〔i〕;NSDatapcmBlock〔enginegetPlayFrame:buffer。mDataByteSize〕;if(pcmBlockpcmBlock。length){UInt32size(UInt32)MIN(buffer。mDataByteSize,〔pcmBlocklength〕);memcpy(buffer。mData,〔pcmBlockbytes〕,size);buffer。mDataByteSizesize;HMLogDebug(LogModuleAudio,AudioUnitRenderpcmdatahasfilled);}else{buffer。mDataByteSize0;ioActionFlagskAudioUnitRenderActionOutputIsSilence;}}endpool}endfor}endifreturnerr;7、不同场景下AudioUnit构建样例7。1IO无渲染
  从输入设备采集过来的数据,先经过MutilChannelMixerUnit,再送到输出设备播放,该构建方式在于中间的Unit可对mic采集采集过来的数据进行声相调节以及音量的调节7。2IO有渲染
  该构建方式在输入与输出之间增加了rendercallback,可以在硬件采集过来的数据上做一些处理(例如,增益、调制、音效等)后再送到输出播放
  IOWithRenderCallback2x。png7。3仅输出并且带渲染
  适合音乐游戏及合成器类的APP,仅使用IOUnit的output端,在rendercallback中负责播放源的提取整理并准备送播,比较简单的构建方式
  输入端有两路音频流,都是通过rendercallback方式抓取数据,其中一路音频流直接给入到MixerUnit中,另一路先经过EQUnit处理后给入到MixerUnit中,8、Tips8。1多线程及内存管理
  尽可能的避免rendercallback方法内做加锁及处理耗时较高的操作,这样可以最大限度的提升实时性能,如果播放数据或者采集数据存在不同线程读写的情况,必需要加锁保护,推荐pthread相关lock方法性能比其它锁要高音频的输入输出一般都是一个持续的过程,在采集与播放的callback中,应尽量复用buffer及避免多次buffer拷贝,而不是每次回调都重新申请和释放,在适当的位置加上autoreleasepool避免长时间运行内存不断上涨8。2格式
  CoreAudioType中定义了AudioStreamBasicDescription结构,AudioUnit及其它很多音频API对格式的配置都需要用到它,根据需要将该结构的信息填充正确,下面是44。1K,stereo,16bit的填充例子audioDescription。mSampleRate44100;audioDescription。mChannelsPerFrame2;audioDescription。mBitsPerChannel16;audioDescription。mFramesPerPacket1;audioDescription。mFormatIDkAudioFormatLinearPCM;audioDescription。mFormatFlagskLinearPCMFormatFlagIsSignedIntegerkAudioFormatFlagIsPacked;audioDescription。mBytesPerFrame(audioDescription。mBitsPerChannel8)audioDescription。mChannelsPerFrame;audioDescription。mBytesPerPacketaudioDescription。mBytesPerFrame;
  苹果官方建议在整个AudioProcessingGraph或者Unit之间尽量以相同的音频格式流通,尽管AudioUnit的输入输出可以不同。另外在Unit之间输入输出连接点要保持一致。8。3音质
  在使用过程中,AudioUnit的format是可以动态改变的,但存在一种情况,Unit在销毁前最好恢复到默认创建时的format,否则在销毁后再重建Unit后,可能出现播放音质变差(音量变小,声音粗糙)的情况。在使用VoiceProcessingIOUnit过程,遇到在有些iphone上开启扬声器后,Unit从Mic采集过来的数据为空或者噪音的情况,从APPSTORE中下载了其它的VOIP类型的APP也同样存在该问题,后来将AudioUnitSubType改成RemoteIO类型后,问题消失,怀疑苹果在VoiceProcessingUnit上对回声消除功能的处理上有bug8。4AudioSession
  既然使用了音频特性,就会用到AudioSession,随着功能需求跟进,与它相关的问题也瞒多的,比如路由管理(听筒扬声器、线控耳机、蓝牙耳机),打断处理(interruption、iphonecall)等,这里以AudioUnit为主,就不对它进行详细描述了,需要注意的是音频的路由变更(用户挺拔耳机,或者代码调用强制切换)涉及到iOS硬件上输入和输出设备的改变,IO类型Unit的采集和播放线程在切换过程中会阻塞一定时间(200ms左右),如果是语音对讲类对实时性要求较高的应用场景要考虑丢包策略。在APP前台工作时,iPhone来电或者用户主动切换到其它音频类APP后,要及时处理音频的打断机制,在恰当的时机停止及恢复Unit的工作,由于iOS平台对资源的独占方式,iPhone在通话等操作时,APP中的Unit是无法初始化或者继续工作的。
  原文链接:iOSAudioUnit(涓)鎺橀噾

比亚迪新能源汽车怪相供不应求却口碑逐渐崩塌消费者的口碑是一个企业的生命,每一个企业都在积极追求消费者的好口碑。而比亚迪汽车公司却在产品供不应求的情况下出现消费者口碑的崩塌,属实奇葩。作为一名比亚迪汽车的老用户,我……独显芯片显神威双芯实力派通吃各大手游iQOONeo6手机评测随着手机市场的不断更新换代,越来越多的手机开始走入消费者的视野。然而要说一款手机中最重要的部分,那可能是非芯片莫属了。纵观今年的手机市场,骁龙芯片可以说是安卓阵营里的独一家,拥……对待国人不能太傻总看互联网,网上很有意思,有人苦口婆心,循循善诱地为大家讲道理、明是非,有人恶意搅混水、带节奏,有人仗义执言,有人极力护主,有人聪明,有人愚昧,有人偏执,有人无耻。要问我……男篮41分胜同曦,周琦转会现转机!篮协主席遭举报,山西补强遇头条创作挑战赛在昨晚与南京同曦的热身赛中,中国男篮采用了14人轮换,最终以41分的巨大优势战胜了拥有双外援的对手。张镇麟在比赛中9投8中,砍下全队最高的20分,曾凡博也有……央视2021年重阳节晚会久久乐重阳节目单新鲜出炉,名嘴张蕾搭封面新闻记者杜恩湖10月14日是重阳节。今天12时,封面新闻记者从央视获悉:央视为2021年重阳节打造了一台别具匠心尊老爱老的大型文艺晚会《久久乐重阳》。央视综艺名嘴张蕾……有茶友说,喝茶会伤胃,是真的吗?【尚茶时间108】有茶友说,喝茶会伤胃,是真的吗?1、很多人觉得喝茶伤胃,胃不好的人更不能喝茶,这其实是一种很深的误解。2、肠胃功能正常和肠胃功能稍弱的人,只……吃不烦的6道菜,家常,营养下饭,大人孩子喜欢好吃不过家常菜!分享6道家常食谱,味道好,做起来没啥难度,最关键的是有营养还下饭,不容易吃烦。第一道【薄五花炒包菜】虽然是很简单的食材,这方做法可香了,五花肉薄薄的……沙田阇西村成功创建省民主法治示范村(社区)近日,省委依法治省办、省委农办、省司法厅、省民政厅联合下发《关于确认2022年广东省民主法治示范村(社区)创建单位的通报》,沙田镇阇西村名列其中,获评2022年广东省民主法治示……曹操亚瑟喜上加喜,蒙恬迎来首款传说,芈月传说升级,710给曜王者一路走来,也是带给了玩家们不同凡响的游戏日常,同时也使王者成为了当下十分热门的手游,正因如此,王者现如今也是频繁的上线新皮肤着,总体来说,也是官方为了更好地维持游戏的秩序。……人死后去了什么地方,人死后仍会有意识,大脑会继续运行?有这样的一句话,人终究有一死,无论你是贫穷富贵,都无法摆脱这个结局,的确也是这样的。人的生命与地球其他生命一样,有生就有死,这样的变化从未改变过。死亡意味着生命终止,停止生存,……老品牌创出新活力来源:【中国路桥新闻网】本报讯(全媒体记者项薇通讯员李胤晓)路桥商贸底蕴深厚,市场经济得风雨历练,锤炼出市场繁荣、民资丰厚、民心思进极具地方特色的路桥经济。在路桥,……金价即将大跌!11月8日各大金店黄金价格多少钱一克?11月8日,欧市早盘,美元指数维持强劲走势,现货黄金维持跌势,金价现报1669美元盎司左右,黄金上涨动力不足。今日国内各大金店金价平稳,目前,金价最高的是老凤祥与周六福,……
羊了个羊用户心理致胜《羊了个羊》,突然火了,因为游戏的第二关超级难,登上了各大热搜。来源微博热搜一款消除类的游戏会火,而且这几天火得一塌糊涂,看似偶然,但偶然间也存在一些必然。我……威少公开发声!主动认错!承担上赛季糟糕的表现被交易了一整个休赛期,被吐槽了一整个赛季,沉默许久的威少终于发声了。既没有为自己辩解,也没有怒怼粉丝、媒体,反倒是主动揽责,承担错误。他说:我知道我会犯错误,会有糟……中老年人最怕失眠,经常吃这3菜,安神静心,一觉到天亮大家好,我是桃子姐!俗话说:睡眠才是最好的补药,睡眠的好坏,直接影响我们第二天的精神状态,睡眠好则神清气爽,睡眠不好整个人就萎靡不振,脾气还会变得暴躁易怒。年轻的时候可能……科学高血压治疗远离治疗四误区!高血压发生以后,积极做好高血压的治疗工作很关键。高血压是怎么一回事,生活中相信大家都清楚,高血压是一种常见病,患上高血压后,患者由于血压攀升,这很容易给患者健康带来伤害。因为,……塞尔维亚女排公布总决赛14人名单,二姐回归,波斯猫继续放大假2022世界女排联赛总决赛即将于7月13日17日在土耳其安卡拉展开争斗!各队相继公布了参赛的14人大名单,塞尔维亚排协公布了村姑的14人大名单。主攻5人:米哈伊洛维奇、布……蒙自市青少年活动中心小记者团打卡碧色寨景区来源:【云南日报】为进一步激发孩子们对家乡历史文化的学习兴趣,增强摄影和写作水平,2月4日,蒙自市青少年活动中心小记者站的孩子们(以下简称:小记者团)走进碧色寨景区,开展……2023年福建锂电池产业分布情况宁德厦门成锂电产业重点集聚区中商情报网讯:锂电产业是新能源的基础产业,大力发展锂电产业是国家实现能源变革、实现双碳战略目标的重要举措。我国锂电产业市场需求持续旺盛,近几年来,福建加速布局锂电产业。福……鄱阳湖大米坚守健康赛道,玩转线上线下新营销2022年的粮油领域,一些企业开辟新业务,寻求新的利润增长点,也有外来者看好粮油行业发展,跨界入局卖粮生意,去年运动品牌贵人鸟子公司收购粮油企业黑龙江和美泰富农业发展股份有限公……林志玲首谈离婚,自曝患抑郁结婚才3年,她怎么成这样了?大家好,我是窈窕妈妈。消失两年的林志玲终于露面了。产子10月后,她匆忙回到台湾推广新书,作为事业重启的序曲。台上的她,披肩长发,一袭白色连衣裙,尽显温柔。……面临退市风波的ST日海股价下跌超50,三年巨亏近18亿《港湾商业观察》廖紫雯日海智能科技股份有限公司(以下简称:ST日海,002313。SZ)2009年于深交所上市,属于国家高新技术企业,是物联网龙头企业之一。2016……你知道儿童戏剧是如何丰富孩子想象力的吗?戏剧被认为是儿童想象力的源泉。相信不少家长已经知道儿童戏剧能够丰富孩子的想象力了,所以开始重视培养孩子对儿童戏剧的戏剧,尽可能地创造机会让孩子参加儿童戏剧活动。但是……春兰大捷,中国仅仅收获5冠,韩收获7冠!这一次,李轩豪将称雄春兰杯,将再次迎来中韩大战,只不过这一次决赛的两位大将均是首次打入决赛阵容,中国李轩豪九段和韩卞相壹九段。两位大将棋逢对手,等级分均位居中韩第2人,无论谁夺冠一切皆有可能,根据……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网