4929|15

80

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

音频驱动某函数代码看不太懂,救助。 [复制链接]

PBYTE OutputStreamContextM16::Render2(PBYTE pBuffer, PBYTE pBufferEnd, PBYTE pBufferLast)
{
    LONG CurrT = m_CurrT;
    LONG DeltaT = m_DeltaT;
    LONG CurrSamp0 = m_CurrSamp[0];
    LONG PrevSamp0 = m_PrevSamp[0];
    PBYTE pCurrData = m_lpCurrData;
    PBYTE pCurrDataEnd = m_lpCurrDataEnd;
    LONG fxpGain = m_fxpGain;
    LONG OutSamp0;

    while (pBuffer < pBufferEnd)
    {
        while (CurrT >= 0x100)
        {
            if (pCurrData>=pCurrDataEnd)
            {
                goto Exit;
            }

            CurrT -= 0x100;

            PrevSamp0 = CurrSamp0;

            PPCM_SAMPLE pSampleSrc = (PPCM_SAMPLE)pCurrData;
            CurrSamp0 = (LONG)pSampleSrc->m16.sample;
            pCurrData+=2;
        }

        OutSamp0 = PrevSamp0 + (((CurrSamp0 - PrevSamp0) * CurrT) >> 8);
        OutSamp0 = (OutSamp0 * fxpGain) >> VOLSHIFT;
        CurrT += DeltaT;
        // DEBUGMSG(1, (TEXT("PrevSamp0=0x%x, CurrSamp0=0x%x, CurrT=0x%x, OutSamp0=0x%x\r\n"), PrevSamp0,CurrSamp0,CurrT,OutSamp0));

#if (OUTCHANNELS==2)
        LONG OutSamp1;
        OutSamp1=OutSamp0;
        if (pBuffer < pBufferLast)
        {
            OutSamp0 += ((HWSAMPLE *)pBuffer)[0];
            OutSamp1 += ((HWSAMPLE *)pBuffer)[1];
#if USE_MIX_SATURATE
            // Handle saturation
            if (OutSamp0>AUDIO_SAMPLE_MAX)
            {
                OutSamp0=AUDIO_SAMPLE_MAX;
            }
            else if (OutSamp0             {
                OutSamp0=AUDIO_SAMPLE_MIN;
            }
            if (OutSamp1>AUDIO_SAMPLE_MAX)
            {
                OutSamp1=AUDIO_SAMPLE_MAX;
            }
            else if (OutSamp1             {
                OutSamp1=AUDIO_SAMPLE_MIN;
            }
#endif
        }
        ((HWSAMPLE *)pBuffer)[0] = (HWSAMPLE)OutSamp0;
        ((HWSAMPLE *)pBuffer)[1] = (HWSAMPLE)OutSamp1;
        pBuffer += 2*sizeof(HWSAMPLE);
#else
        if (pBuffer < pBufferLast)
        {
            OutSamp0 += ((HWSAMPLE *)pBuffer)[0];
#if USE_MIX_SATURATE
            // Handle saturation
            if (OutSamp0>AUDIO_SAMPLE_MAX)
            {
                OutSamp0=AUDIO_SAMPLE_MAX;
            }
            else if (OutSamp0             {
                OutSamp0=AUDIO_SAMPLE_MIN;
            }
#endif
        }
        ((HWSAMPLE *)pBuffer)[0] = (HWSAMPLE)OutSamp0;
        pBuffer += sizeof(HWSAMPLE);
#endif
    }

    Exit:
    m_dwByteCount += (pCurrData - m_lpCurrData);
    m_lpCurrData = pCurrData;
    m_CurrT = CurrT;
    m_PrevSamp[0] = PrevSamp0;
    m_CurrSamp[0] = CurrSamp0;
    return pBuffer;
}

这个函数对pBuffer缓冲区的数据进行处理了一下。pBuffer里面本来就是WAV格式,为什么还要计算?其中m_fxpGain是个音量值,把音量和pBuffer组合运算,怎么就起到控制声音的效果了?。
m_CurrT,m_DeltaT,CurrSamp0,PrevSamp0 ,OutSamp0 这几个参数分别是干嘛用的?组合运算以后 pBuffer里面的数据起到了什么变化?
DWORD OutputStreamContext::SetRate(DWORD dwMultiplier)
{
    m_dwMultiplier = dwMultiplier;

    UINT64 Delta = (m_WaveFormat.nSamplesPerSec * m_dwMultiplier) >> 16;
    Delta = (Delta * INVSAMPLERATE) >> 24;  // Convert to 24.8 format
    m_DeltaT = (DWORD)Delta;
    return MMSYSERR_NOERROR;
}
上面函数中针对m_DeltaT的运算是什么意思?
看来好长时间,没能明白!
附上100分,恳请大家指点!

最新回复

受教了  详情 回复 发表于 2009-11-5 13:47
点赞 关注

回复
举报

92

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
while (CurrT >= 0x100)
        {
            if (pCurrData>=pCurrDataEnd)
            {
                goto Exit;
            }

            CurrT -= 0x100;

            PrevSamp0 = CurrSamp0;

            PPCM_SAMPLE pSampleSrc = (PPCM_SAMPLE)pCurrData;
            CurrSamp0 = (LONG)pSampleSrc->m16.sample;
            pCurrData+=2;
        }

        OutSamp0 = PrevSamp0 + (((CurrSamp0 - PrevSamp0) * CurrT) >> 8);
        OutSamp0 = (OutSamp0 * fxpGain) >> VOLSHIFT;
        CurrT += DeltaT
主要是这段运算,不太理解!
 
 

回复

77

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
循环中,以下几句话都是什么意思?
CurrT -= 0x100; CurrT += DeltaT;
        OutSamp0 = PrevSamp0 + (((CurrSamp0 - PrevSamp0) * CurrT) >> 8);
        OutSamp0 = (OutSamp0 * fxpGain) >> VOLSHIFT;
 
 
 

回复

78

帖子

0

TA的资源

一粒金砂(初级)

4
 
这个程序我曾经也研究过。。。也没有摸索出个所以然来基本上卡住的地方跟你一样。。。不过从做音频看来他并不需要修改。。这是一个混音的算法。。。就说当你有很多个流在一起放的时候这个函数会有很大的作用。。。

希望有人出来解释解释
 
 
 

回复

62

帖子

0

TA的资源

一粒金砂(初级)

5
 
fxpGain应该是通过线性缩小音频波形幅值来控制声音的,这样就不用直接控制运放增益了。混音原理不太明白,他怎么会和以前的采样点PrevSamp0有关系呢?
 
 
 

回复

69

帖子

0

TA的资源

一粒金砂(初级)

6
 
可能我说错了。。你的这段代码跟混音没有关系。。呵呵呵。。我就是这段以前不明白

OutSamp0 = PrevSamp0 + (((CurrSamp0 - PrevSamp0) * CurrT) >> 8);
OutSamp0 = (OutSamp0 * fxpGain) >> VOLSHIFT;
CurrT += DeltaT;

他看起来似乎是用了两个16位的原始sample来拼出了一个用于播放的sample
 
 
 

回复

76

帖子

0

TA的资源

一粒金砂(初级)

7
 
你的这个currT是多少呢
 
 
 

回复

66

帖子

0

TA的资源

一粒金砂(初级)

8
 
高手们都不进,看来是被鄙视了!
 
 
 

回复

73

帖子

0

TA的资源

一粒金砂(初级)

9
 
不懂,转到专题开发去试试。
 
 
 

回复

77

帖子

0

TA的资源

一粒金砂(初级)

10
 
音频包括(音量Gain)和内容(歌曲),这个函数就是把系统音量,比如:99999999这个值打包歌曲内容发送到音频设备去播放,这些算法是不要修改的
 
 
 

回复

71

帖子

0

TA的资源

一粒金砂(初级)

11
 
呵呵,友情UP,这个真的不懂
 
 
 

回复

64

帖子

0

TA的资源

一粒金砂(初级)

12
 
引用 6 楼 unsway123 的回复:
你的这个currT是多少呢

currT初始化是0X200。但是会变的啊!
 
 
 

回复

74

帖子

0

TA的资源

一粒金砂(初级)

13
 
呵呵。。你的m_currT会变吗?贴下代码。。我的BSP中直接就赋值0x200;
 
 
 

回复

83

帖子

0

TA的资源

一粒金砂(初级)

14
 
这是混音和重采样算法

Driver把不同采样率的声音混合到同一采样率,然后在硬件上播放

假设OutputStream的采样率是1,硬件播放的采样率是1/DeltaT

*-----*-----*-----*-----*  OutputStream采样点S
0     1     2     3     4
*---*---*---*---*---*---*  硬件采样点H (d=DeltaT)
0   d  2d  3d  4d  5d  6d

这个CurrT是OutputStream和硬件采样点之间定比分点(CurrT实际应该是0-1直接的小数,程序中用0-256表示)

外层while表示遍历每个硬件采样点H,每计算完一个采样点CurrT递增DeltaT,
内层while根据CurrT的值选择用于插值的两个S点,并把CurrT修正在0-1之间,表示硬件采样点在这两个S点间的定比分点
然后用线性插值,把硬件采样点计算出来

为什么CurrT开始等于2的原因就是在初始的时候让程序能够找到H(0)的两个插值点S(0),S(1)
 
 
 

回复

65

帖子

0

TA的资源

一粒金砂(初级)

15
 
    非常感谢,楼上。
    我理解了。主要是应用层的WAV文件,采样率是不一致的,11.025k,16k,22.05k,32k,44.1k都有可能 。而驱动当中,其实对IIS进行操作的采样率是已经恒定的(我BSP上是44.1k).这样一来如果播放11.025k的WAV文件,如果不调整,必然会导致播放速度太快,就像快进一样。所以必须加快采样率,才能使声音正常。
    上面的算法刚好就起到了这个效果。如果播放11.025k的文件,通过另外插入三个值,相当于原本播放一个点的时间用来播放4个点,这样采样就和44.1k相同了。(为了不使声音失真,采用线性插值算法)   
     
 
 
 

回复

92

帖子

0

TA的资源

一粒金砂(初级)

16
 
受教了
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表