在DSound播放文件的同时,我们维系了一个变量来递增显示当前播放的时间,下面讲其中几个比较重要的函数
这里一般情况下都会是p<curPos,那么offsetbuf,就是描述一个buf的偏移量,不断的累加,
cycleDif是一个描述偏移次数的东东,这个函数下来,改变得有三个offsetBuf、
cycleDif和
curPos,这个curPos描述的相对与当前Buf的位置。那理论上,我们播放一个bufSize的时候就要调用这个函数一次在什么地方时候时候调用。
我们可以看到这个函数在,音乐播放的While循环里面调用过,这样我们就想通了。
好,这个修改的只是Buf的位置,如何转换成时间呢?
其中
UNITS为10^7,
(curPos+offsetBuf)/bufFormat.Format.nAvgBytesPerSec这个返回的是秒为单位,乘以
UNITS之后,精度变为10^-7s了,前面好像说过IRef实现的函数可以为空,这句话不完全正确,函数为空只是针对于那些需要同步的函数如GetAdviceTime这类函数,但是里面的一个最基本的GetTime还是要做的,因为Graph要知道当前的播放进度就是通过这个函数,这个函数必须的实现,为了实现这个函数,我们首先写了这个函数:
这都是时间相关的函数,可以参考一下。
下面有两个相对的函数;
返回的分别是空闲和已读的字节数。
- HRESULT CScopeFilter::getCurPos()
- {
- if(!buffer) return DSERR_UNINITIALIZED;
- clockLock.Lock();
- DWORD p;
- HRESULT hr= buffer->GetCurrentPosition(&p,0);
- if(hr==DS_OK){
- static DWORD pp,cnt; ///实际情况在播放的时候不可能p==pp
- if(p==pp){
- if(playing && ++cnt>9){
- stop();
- play();
- cnt=0;
- }
- }else{
- cnt=0;
- pp=p;
- }
- if(p<curPos){
- //因为在播放音乐的时候是一个一个Buff来播放的,获得Buff的位置p,那么证明我们的curPos
- //存储的只是上一帧的位置,需要加上这一帧的大小
- offsetBuf+=bufSize;
- //并且我们的buff个数也要加一
- cycleDif++;
- }
- //注意这里的CurPos永远都是相对于Buff
- //buff在一个接一个播放的,因而curPos都在变
- //但是相对于文件来说,我们播放了多长时间了,就要参考GetPrivateTime函数
- //看他们之间的关系
- curPos=p;
- }
- clockLock.Unlock();
- return hr;
- }
我们可以看到这个函数在,音乐播放的While循环里面调用过,这样我们就想通了。
好,这个修改的只是Buf的位置,如何转换成时间呢?
- REFERENCE_TIME CScopeFilter::GetPrivateTime()
- {
- HRESULT hr= getCurPos();
- if(hr==DS_OK){
- clockLock.Lock();
- REFERENCE_TIME result= UNITS*(curPos+offsetBuf)/bufFormat.Format.nAvgBytesPerSec;
- clockLock.Unlock();
- return result;
- }
- return 0;
- }
- REFERENCE_TIME CScopeFilter::getWriteTime()
- {
- clockLock.Lock();
- REFERENCE_TIME result= UNITS*(offsetBuf+(writePos+(1-cycleDif)*bufSize))/bufFormat.Format.nAvgBytesPerSec;
- clockLock.Unlock();
- return result;
- }
- STDMETHODIMP CScopeFilter::GetTime(REFERENCE_TIME *pTime)
- {
- CheckPointer(pTime,E_POINTER);
- *pTime= GetPrivateTime();
- if(*pTime<beginTime) *pTime=beginTime;
- return S_OK;
- }
- int CScopeFilter::msToB(int ms)
- {
- return MulDiv(ms, bufFormat.Format.nSamplesPerSec, 1000)*bufFormat.Format.nBlockAlign;
- }
下面有两个相对的函数;
- int CScopeFilter::getFree()
- {
- clockLock.Lock();
- int result= int(curPos-writePos)+cycleDif*bufSize;
- clockLock.Unlock();
- return result;
- }
- int CScopeFilter::getFilled()
- {
- clockLock.Lock();
- int result= int(writePos-curPos)+(1-cycleDif)*bufSize;
- clockLock.Unlock();
- return result;
- }