4597|19

67

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

wince声道切换! [复制链接]

    我使用DX做了一个mp3播放器。
使用waveoutsetvolume()设置左右声道的音量,设置成功之后,我连续播放同一个声音,
居然自己跳到另外一个声道去播放了!

就是说我没有做任何动作,他自己把声道切换到另外一边去播放了!

这样一来,我在左声道播放的声音就有可能出现自动跳到右声道播放的可能,很不稳定!

请问有没有什么解决方法,谢谢!

最新回复

mark  学习了  详情 回复 发表于 2010-1-28 10:43
点赞 关注

回复
举报

81

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
前几天有个贴在讨论这个,你可以搜搜看看。
 
 

回复

86

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
ls的,
好像也是lz问的。
 
 
 

回复

68

帖子

0

TA的资源

一粒金砂(初级)

4
 
要是能搜索到答案我就不用再问了啊

这个问题困扰了我很多天了啊
我不段的修改驱动,都没有能实现啊,都不稳定!
 
 
 

回复

69

帖子

0

TA的资源

一粒金砂(初级)

5
 
查找驱动程序中的音频流到DMA传输哪里, 我的驱动是在流上下文 句柄实例 那里面准备要播放的缓冲区,然后调用设备去添加缓冲区,然后再调用流里面的发送到DMA通道, 最后调用硬件设备的DMA中断去处理。

一般你的自动切换左右声道,你要仔细调试你的驱动是否哪里有问题:
1、缓冲区准备是否正确, 缓冲区数据传输是否正确
2、DMA通道传输是否正确
3、DMA结束控制是否正确,也就是你的缓冲区在传输过程中动态的长度处理是怎么样的?
4、语音流结束控制如何,哪里调用了停止,也就是3中的问题 ,


如果这些都搞好了, 你的驱动也许就不会有问题了。

好运
 
 
 

回复

79

帖子

0

TA的资源

一粒金砂(初级)

6
 
我检查了驱动,一步一步的跟了下去,看了一下

在一个语音流开始的字节,这个时候LRCLK,也就是左右声道时钟,决定了此次播放的左右声道!
并不是每次开始传输的时候,LRCLK都是相同的电平!

这让我有点头疼了,怎么才能实现稳定的左右声道播放呢!
 
 
 

回复

64

帖子

0

TA的资源

一粒金砂(初级)

7
 
1、底层驱动:中在你打开设备前,你会调用系统音频设备查询,将返回你是否支持双声道  这点, 我想你肯定支持了
2、PDD中PDD_WaveOpen 中会检查你的声道:
//
    // Allow PCM, mono or stereo, 8 or 16 bit at 11k or 22k Hz
    //
    if ((lpFormat->wFormatTag != WAVE_FORMAT_PCM) ||
        (lpFormat->nChannels  != 1 && lpFormat->nChannels != 2) ||
        (lpFormat->nSamplesPerSec < 4000 || lpFormat->nSamplesPerSec > 48000) ||
        (lpFormat->wBitsPerSample != 16 && lpFormat->wBitsPerSample != 8) )
    {
        mmRet = WAVERR_BADFORMAT;
        goto EXIT;
    }

这就是说没有播放前,这里要求你的声道数据必须要对,左右声道数据不同, 且分为16位的高8Bit和低8 Bit

3.CreateStream时就根据你打开设备的情况创建了流缓冲区
StreamContext *OutputDeviceContext::CreateStream(LPWAVEOPENDESC lpWOD)
{
    LPWAVEFORMATEX lpFormat=lpWOD->lpFormat;
   
    if (lpFormat->nChannels==1)
    {
        if (lpFormat->wBitsPerSample==8)
        {
            return new OutputStreamContextM8;
        }
        else
        {
            return new OutputStreamContextM16;
        }
    }
    else
    {
        if (lpFormat->wBitsPerSample==8)
        {
            return new OutputStreamContextS8;
        }
        else
        {
            return new OutputStreamContextS16;
        }
    }
}
 
 
 

回复

90

帖子

0

TA的资源

一粒金砂(初级)

8
 
最终在数据准备哪里调到了系统相关的:Render2中(你的可能不同注意)在这里准备了数据
PBYTE OutputStreamContextS16::Render2(PBYTE pBuffer, PBYTE pBufferEnd, PBYTE pBufferLast)
{
   LONG CurrT = m_CurrT;
    LONG DeltaT = m_DeltaT;
    LONG CurrSamp0 = m_CurrSamp[0];
    LONG CurrSamp1 = m_CurrSamp[1];
    LONG PrevSamp0 = m_PrevSamp[0];
    LONG PrevSamp1 = m_PrevSamp[1];
    PBYTE pCurrData = m_lpCurrData;
    PBYTE pCurrDataEnd = m_lpCurrDataEnd;
    LONG fxpGain = m_fxpGain;
    LONG OutSamp0;
    LONG OutSamp1;

。。。。
          PrevSamp0 = CurrSamp0;
            PrevSamp1 = CurrSamp1;

            PPCM_SAMPLE pSampleSrc = (PPCM_SAMPLE)pCurrData;
            CurrSamp0 = (LONG)pSampleSrc->s16.sample_left;
            CurrSamp1 = (LONG)pSampleSrc->s16.sample_right;
            pCurrData+=4;

。。。。。
#if(HIGH_OUTPUT_QULITY==1)
        OutSamp0 = PrevSamp0 + (((CurrSamp0 - PrevSamp0) * CurrT) >> 8);
        OutSamp1 = PrevSamp1 + (((CurrSamp1 - PrevSamp1) * CurrT) >> 8);
#else
        OutSamp0 = CurrSamp0;
        OutSamp1 = CurrSamp1;
#endif
        OutSamp0 = (OutSamp0 * fxpGain) >> VOLSHIFT;
        OutSamp1 = (OutSamp1 * 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));

.....

最终:
        ((HWSAMPLE *)pBuffer)[0] = (HWSAMPLE)OutSamp0;
        ((HWSAMPLE *)pBuffer)[1] = (HWSAMPLE)OutSamp1;

        pBuffer += 2*sizeof(HWSAMPLE);
    }

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

返回了数据。  

再就是:送DMA了
void OutputDeviceContext::StreamReadyToRender(StreamContext *pStreamContext)
{
    g_pHWContext->StartOutputDMA();
    return;
}
AC97会根据你对AC97 芯片的设置将数据送往不同的声道DAC  然后到不同的channel


不知道你用的是什么方式,居然还有左右声道的CLK  我一直没有注意这个, 我用aC97


 
 
 

回复

82

帖子

0

TA的资源

一粒金砂(初级)

9
 
谢谢slyzhang 细心的回答

最开始我就已经检查了您所说的这些问题,并且现在这些问题已经解决,左右声道的音量可以分别控制!

但是,是不稳定的,也就是说播放一段时间过后,左右声道的音量就对调了
这难道不是LRCLK的原因。
我设置为单声道播放时,用示波器测了一下,偶尔是在LRCLK高电平时有数据,偶尔是在LRCLK低电平时有数据!这样,就造成了左右声道对调了!
并且,在一个语音播放完成时,LRCLK为什么电平,他就会停留在什么电平,下次播放时接着使用这个停留住的电平开始!

您所说的我知道是怎么做的,这样能实现左右声道,并且能够实现左右声道的音量调节!

但连续播放几次之后就出现互换的情况了!
 
 
 

回复

64

帖子

0

TA的资源

一粒金砂(初级)

10
 
那只能仔细检查每个环节了,其他人估计给你不了更精确的答案了。 我不知道DX是否存在问题, 不妨自己组织一段数据测试看看
 
 
 

回复

71

帖子

0

TA的资源

一粒金砂(初级)

11
 
播放中没有问题,下次播放出问题,明显是在两次播放之间有驱动操作,其中肯定涉及了通道切换的配置。
连续播放其实也是两次播放,只不过是自动判断并开始。
查驱动,打trace,看看播放完成后,上层到底发什么IOControl代码下来,调用驱动的什么函数,看看这个函数里面的代码到底做了什么不希望做的事(切换通道)。
 
 
 

回复

55

帖子

0

TA的资源

一粒金砂(初级)

12
 
引用 10 楼 shuiyan 的回复:
播放中没有问题,下次播放出问题,明显是在两次播放之间有驱动操作,其中肯定涉及了通道切换的配置。
连续播放其实也是两次播放,只不过是自动判断并开始。
查驱动,打trace,看看播放完成后,上层到底发什么IOControl代码下来,调用驱动的什么函数,看看这个函数里面的代码到底做了什么不希望做的事(切换通道)。


我跟踪调试下去看了一下,没有发现播放完成没有发生通道切换的IOControl。

请问有人实现了2410,1341的稳定的声道切换的吗
 
 
 

回复

74

帖子

0

TA的资源

一粒金砂(初级)

13
 
不一定直接就是“通道切换”的控制。

而是结束后和再次开始时,应用层传下来的控制动作,所对应的函数里重新配置了寄存器,用的是直接赋值,而不是“或”操作,导致之前的配置丢失。

我们在Phone上的音频发生过好几次这样的现象,因为打电话时的音频通道更复杂。
 
 
 

回复

71

帖子

0

TA的资源

一粒金砂(初级)

14
 
我看了驱动里面
iis总线,DMA传输
每次开始传送的时候都配置了几个IIS寄存器,传输完毕关闭了相应的寄存器
这样也会有问题吗
 
 
 

回复

76

帖子

0

TA的资源

一粒金砂(初级)

15
 
Mark!
 
 
 

回复

61

帖子

0

TA的资源

一粒金砂(初级)

16
 
那就在结束时,在开始时,将这些寄存器都通过trace打出来,细致的对比,尤其是涉及到左右声道配置的寄存器。
应该就是在这些操作里面,修改的时候忽略了之前的寄存器值,导致设置的左右声道值丢失。
 
 
 

回复

74

帖子

0

TA的资源

一粒金砂(初级)

17
 
mark`
 
 
 

回复

72

帖子

0

TA的资源

一粒金砂(初级)

18
 
说了这么久也没有去试验一下,因为最近工作真的太忙了,
我们现在使用继电器实现两个喇叭之间的切换

2410的IIS能够实现稳定的左右声道切换吗,我没看见2410的IIS有设置左右声道的,只有一个选择高电平为左还是低电平为左的,但是我的代码里面都没有设置过这个寄存器,用的是默认设置!

并且我用示波器看了一下,LRCK的的高低会停留在上次播放结束时停留的地方!

是不是每次传输的时候都能保证他传输第一个字节是在某一个电平,我是说LRCK,是不是每次发送一个音频的第一个字的时候,LRCK都是高或者低
 
 
 

回复

64

帖子

0

TA的资源

一粒金砂(初级)

19
 
Mark!
 
 
 

回复

70

帖子

0

TA的资源

一粒金砂(初级)

20
 
mark  学习了
 
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

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

 
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
快速回复 返回顶部 返回列表