6790|15

1

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

waveOutClose的疑惑 [复制链接]

为了解决playSound函数装载大文件速度慢和不支持MP3的播放,我自己写一个模拟PlaySound的函数来播放音频文件。

我使用了常规的双缓冲,用一个callback函数不停的装载数据,播放很流畅,但是如果在播放过程中停止播放在waveOutClose的时候出现33的错误(任然有buffer没有清空),尝试了几次都不行,请大家帮我看看是什么问题,谢谢!!

void CALLBACK waveOutProcCallback( HWAVEOUT hwo2, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 )
{
        HRESULT mr;
        LPWAVEHDR pWaveHeader = NULL;

//系统自动识别是哪一个WAVEHDR播放完毕
        pWaveHeader = (LPWAVEHDR)dwParam1;
        switch(uMsg)
        {
        case WOM_CLOSE:
                break;

        case WOM_OPEN:
                break;

        case WOM_DONE:

//播放完后须调用此函数
                waveOutUnprepareHeader( hwo2, pWaveHeader, sizeof(WAVEHDR) );

                EnterCriticalSection(&g_csReadyQueue);
                if(g_qReadyQueue.empty())
                {
                        LeaveCriticalSection(&g_csReadyQueue);
                }
                else
                {
                        g_pPlayBuf = g_qReadyQueue.front();
                        g_qReadyQueue.pop();

                        LeaveCriticalSection(&g_csReadyQueue);

//装填新的buffer
                        pWaveHeader->lpData = (char *)g_pPlayBuf;

//把使用过的buffer放回Unready Queue
                        EnterCriticalSection(&g_csUnreadyQueue);
                        g_qUnreadyQueue.push(g_pPlayBuf);
                        LeaveCriticalSection(&g_csUnreadyQueue);

                        mr = waveOutPrepareHeader(hwo2, pWaveHeader, sizeof(WAVEHDR));
                        mr = waveOutWrite(hwo2, pWaveHeader, sizeof(WAVEHDR));
                }
                break;

        default:
                break;
        }
}


DWORD WINAPI PlayThread(LPVOID lpParam)
{
        DWORD dwWait;
        HRESULT mr;

//分配两个结构体双缓冲
        WAVEHDR hdr1;
    WAVEHDR hdr2;

        int count = 0;
       
        RETAILMSG(1, (TEXT("PlayThread Begin!\r\n")));
       
//打开设备,使用回调函数处理双缓冲播放
        mr =  waveOutOpen(&hwo, WAVE_MAPPER, g_pwfx, (DWORD)waveOutProcCallback, NULL, CALLBACK_FUNCTION );
        MRCHECK1(mr, waveOutOpen, ERROR_OPEN);

        while(!g_bStopThread)
        {
            //只执行一次,初始化开始两个buffer
            if(0 == count)
                {
                        //从一个Unready队列中提取buffer赋值给WAVEHDR hdr1,WAVEHDR hdr2
                        EnterCriticalSection(&g_csReadyQueue);
                        if(g_qReadyQueue.empty())
                        {
                                LeaveCriticalSection(&g_csReadyQueue);
                                continue;
                        }

                        g_pPlayBuf = g_qReadyQueue.front();
                        g_qReadyQueue.pop();
                        LeaveCriticalSection(&g_csReadyQueue);
               
                        memset(&hdr1, 0, sizeof(hdr1));
                        hdr1.dwBufferLength = BUF_SIZE;  //BUF_SIZE = 0x8000
                        1.lpData = (char *) g_pPlayBuf;
                        hdr1.dwFlags = 0;
                        hdr1.dwLoops = 0;

                        EnterCriticalSection(&g_csUnreadyQueue);
                        g_qUnreadyQueue.push(g_pPlayBuf);
                        LeaveCriticalSection(&g_csUnreadyQueue);

                        EnterCriticalSection(&g_csReadyQueue);
                        if(g_qReadyQueue.empty())
                        {
                                LeaveCriticalSection(&g_csReadyQueue);
                                continue;
                        }

                        g_pPlayBuf = g_qReadyQueue.front();
                        g_qReadyQueue.pop();
                       
                        LeaveCriticalSection(&g_csReadyQueue);

                        memset(&hdr2, 0, sizeof(hdr2));
                        hdr2.dwBufferLength = BUF_SIZE;
                        hdr2.lpData = (char *) g_pPlayBuf;
                        hdr2.dwFlags = 0;
                        hdr2.dwLoops = 0;

                        EnterCriticalSection(&g_csUnreadyQueue);
                        g_qUnreadyQueue.push(g_pPlayBuf);
                        LeaveCriticalSection(&g_csUnreadyQueue);

                        mr = waveOutPrepareHeader(hwo, &hdr1, sizeof(hdr1));
                        MRCHECK1(mr, waveOutPrepareHeader,ERROR_PLAY);

                        mr = waveOutPrepareHeader(hwo, &hdr2, sizeof(hdr2));
                        MRCHECK1(mr, waveOutPrepareHeader, ERROR_PLAY);

                        mr = waveOutWrite(hwo, &hdr1, sizeof(hdr1));
                        MRCHECK1(mr, waveOutWrite, ERROR_PLAY);

                        mr = waveOutWrite(hwo, &hdr2, sizeof(hdr2));
                        MRCHECK1(mr, waveOutWrite, ERROR_PLAY);
                        count++;
                }
        }
        RETAILMSG(1, (TEXT("PlayThread End!\r\n")));
         
ERROR_PLAY:
        mr = waveOutReset(hwo);
        MRCHECK1(mr, waveOutReset, ERROR_OPEN);

        //Sleep(800);

        free(hdr1.lpData);
        waveOutPrepareHeader(hwo, &hdr1, sizeof(hdr1));
        MRCHECK1(mr, waveOutPrepareHeader, ERROR_OPEN);

        free(hdr2.lpData);
        waveOutPrepareHeader(hwo, &hdr2, sizeof(hdr2));
        MRCHECK1(mr, waveOutPrepareHeader, ERROR_OPEN);

    mr = waveOutClose(hwo);
    MRCHECK1(mr, waveOutClose, ERROR_OPEN);

ERROR_OPEN:
    delete [] g_pPlayBuf;
    delete [] g_pwfx;

ERROR_READ:
    return 0;
}

最新回复

最近在做音视频处理,也出现了这个问题,谢谢lesho,shiyang_x  详情 回复 发表于 2009-12-22 11:54
点赞 关注

回复
举报

4

帖子

0

TA的资源

一粒金砂(中级)

沙发
 
各位windows编程达人呢?给点意见赛,100分,说点啥我都是给分的哎
 
 

回复

2

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
向你学习,呵呵……这一块还不是很懂,正在学习中……
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

4
 
我也是第一次做这个,代码肯定有缺陷,希望高人指点一二
 
 
 

回复

4

帖子

0

TA的资源

一粒金砂(初级)

5
 
代码有点乱,没调整好!其实很简单,就是一个播放的线程,一个回调函数处理一个WAVEHDR结构体播放完毕的消息。

如果播放中间中止,g_bStopThread变为TRUE;跳出循环,收拾内存,关闭设备。就是在mr = waveOutClose(hwo); 的时候出错,如果加上Sleep(800);就没问题,不过会出现后缀音(不能立刻停止)。
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

6
 
关注中,遇到了类似的问题!快些解决呀!
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

7
 
看了一代码,应该是两个线程没有做好同步工作.waveOutReset过程中应该可以调到waveOutProcCallback WOM_DONE中,所以在WOM_DONE的处理过程中你应该判断是否是已经RESET了,如果RESET,就不要再往里写数据了,之后又把数据delete,sleep(800)后播放出杂音应该就是这的问题了,估计这个也应该是CLOSE失败的原因。

 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

8
 
我不是高手。。但是做过关于音频的应用和驱动。。粗略的看了下。。我觉得首先是先填满两个buffer.然后就开始waveoutwrite一个。因为一开始第一个buffer write完后就可以进入你的那个回调再所有的过程都集中在回调里面。
还有就是你的hwo2是什么意思。。不是就一个hwo吗?

我想你试试在最后close之前再reset一次看看。。。reset是清空缓存。。。。

网上有个叫filter的小程序。。很是经典。。。如果是想专门弄好这一块就可以下下来看看。。。


 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

9
 
感谢unsway123:

1. 如果填满两个buffer,然后就开始waveoutwrite一个,就算进入回调还是只能是一个buffer装载数据,write数据啊,第二个始终在那里没有播放吧。所以另外一个waveoutwrite也要执行。

2. hwo就是hwo2,因为回调函数自己可以判断出hwo,hwo和hwo2只是变量命名而已。

3. 我在close之前reset了,没用,代码如下:

waveOutReset(hwo);
//Sleep(800);
waveOutPrepareHeader(hwo, &hdr1, sizeof(hdr1));
waveOutPrepareHeader(hwo, &hdr2, sizeof(hdr2));
waveOutClose(hwo);
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

10
 
Sleep(800)之后就可以了。
那可能是说,音频缓冲区里的数据没有被播放完,
清空缓冲区之后才能正常关闭?

reset能清空缓冲区吗?
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

11
 
引用 7 楼 rzsheng 的回复:
Sleep(800)之后就可以了。
那可能是说,音频缓冲区里的数据没有被播放完,
清空缓冲区之后才能正常关闭?

reset能清空缓冲区吗?


这就是我想问的,如果按照代码判断,reset和unprepare两个函数都不能真正清空buffer,所以close的时候出错,延迟800毫秒貌似可以全部放完了,但是会有一点尾音,就是结尾不干净的那种声音。
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

12
 
引用 10 楼 shiyang_x 的回复:
看了一代码,应该是两个线程没有做好同步工作.waveOutReset过程中应该可以调到waveOutProcCallback WOM_DONE中,所以在WOM_DONE的处理过程中你应该判断是否是已经RESET了,如果RESET,就不要再往里写数据了,之后又把数据delete,sleep(800)后播放出杂音应该就是这的问题了,估计这个也应该是CLOSE失败的原因。


看完很有启发,我试试看,顺道问一下,怎么判断是否已经reset了?光根据返回值好像不好判断吧。。。
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

13
 
问题解决了!!果然如shiyang_x兄所言!!拜谢!!
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

14
 
学习一下!
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

15
 
感谢大家,我也遇到这个问题。
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

16
 
最近在做音视频处理,也出现了这个问题,谢谢lesho,shiyang_x
 
 
 

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

随便看看
查找数据手册?

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