- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试使用XAudio2音频系统异步播放循环声音。它起作用,但是当DLL被卸载时(这里的代码在另一个程序加载的DLL内部)中,我在父应用程序中遇到了访问冲突异常。
我注意到在将母带声音添加到混音中之前,我没有收到任何错误,但是我不知道自己可能会做错什么。
代码如下:
在soundengine.h中
#include <Windows.h>
#include <xaudio2.h>
#include <fstream>
#define SAFE_DELETE(p) if(p) {delete p; p = NULL;}
#define SAFE_DELETE_ARRAY(p) if(p) {delete[] p; p = NULL;}
#define DXTRACE_ERR(str,hr) DXTrace(__FILE__,(DWORD)__LINE__,hr,str, FALSE)
using namespace std;
#define XA2SE_PLAY_LOOP 1
#define XA2SE_PLAY_STD 0
#define XA2SE_ERROR_NOTPLAYING -1
#define XA2SE_ERROR_COULD_NOT_OPEN_FILE -2
#define XA2SE_ERROR_NOT_WAVE_FILE -3
#define XA2SE_ERROR_COULD_NOT_SEEK -4
#define XA2SE_ERROR_COULD_NOT_DESCEND -5
#define XA2SE_ERROR_COULD_NOT_RESET -6
#define XA2SE_ERROR_RIFF_ERROR -7
#define XA2SE_ERROR_SIZE_ERROR -8
#define XA2SE_ERROR_COULD_NOT_READ -9
#define XA2SE_ERROR_UNEXPECTED_NULL_VALUE -10
#define XA2SE_ERROR_COULD_NOT_ASCEND -11
#define XA2SE_ERROR_COULD_NOT_GET_INFO -12
#define XA2SE_ERROR_COULD_NOT_ADVANCE -13
#define XA2SE_ERROR_COULD_NOT_READEND -14
#define XA2SE_ERROR_COULD_NOT_SET_INFO -15
#define XA2SE_ERROR_COULD_NOT_CREATE_VOICE -16
#define XA2SE_COULD_NOT_SUBMIT_BUFFER -17
#define WAVEFILE_READ 0x001
class XA2SoundEngine {
public:
IXAudio2MasteringVoice* mv;
IXAudio2SourceVoice* sv;
IXAudio2* pXA2;
XA2SoundEngine();
~XA2SoundEngine();
BOOL Play(LPWSTR file, int mode);
};
class WaveFile {
public:
WAVEFORMATEX* m_pwfx; // Pointer to WAVEFORMATEX structure
HMMIO m_hmmio; // MM I/O handle for the WAVE
MMCKINFO m_ck; // Multimedia RIFF chunk
MMCKINFO m_ckRiff; // Use in opening a WAVE file
DWORD m_dwSize; // The size of the wave file
MMIOINFO m_mmioinfoOut;
BYTE* m_pbData;
BYTE* m_pbDataCur;
ULONG m_ulDataSize;
CHAR* m_pResourceBuffer;
protected:
HRESULT ReadMMIO();
HRESULT WriteMMIO( WAVEFORMATEX* pwfxDest );
public:
WaveFile();
~WaveFile();
HRESULT Open( LPWSTR strFileName);
HRESULT Close();
HRESULT Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead );
HRESULT Write( UINT nSizeToWrite, BYTE* pbData, UINT* pnSizeWrote );
DWORD GetSize();
HRESULT ResetFile();
WAVEFORMATEX* GetFormat() {
return m_pwfx;
};
};
extern XA2SoundEngine* soundengine;
#include "soundengine.h"
struct async_play_params {
LPWSTR file;
int mode;
};
DWORD _stdcall async_play_routine(void* param);
XA2SoundEngine::XA2SoundEngine() {
HRESULT hr;
CoInitializeEx(NULL,COINIT_MULTITHREADED);
pXA2 = NULL;
sv = NULL;
if(FAILED(hr = XAudio2Create(&pXA2))) {
MessageBoxW(NULL,L"The TFDi 737 Extreme Sound system failed to initialize the XAudio2 engine.\r\n\r\nError: FAILED(hr = XAudio2Create(&pXA2, flags))",L"TFDi 737XS Sound Error",MB_OK + MB_ICONERROR);
return;
}
if(FAILED(hr = pXA2->CreateMasteringVoice(&mv))) {
MessageBoxW(NULL,L"The TFDi 737 Extreme Sound system failed to initialize the XAudio2 mastering voice.\r\n\r\nError: FAILED(hr = pXA2->CreateMasteringVoice(&mv))",L"TFDi 737XS Sound Error",MB_OK + MB_ICONERROR);
return;
}
}
XA2SoundEngine::~XA2SoundEngine() {
if(sv)
sv->DestroyVoice();
if(mv)
mv->DestroyVoice();
if(pXA2)
pXA2->Release();
CoUninitialize();
}
BOOL XA2SoundEngine::Play(LPWSTR file, int mode) {
HRESULT hr;
WaveFile wf;
if(FAILED(hr = wf.Open(file)))
return XA2SE_ERROR_COULD_NOT_OPEN_FILE;
WAVEFORMATEX* pwfx = wf.GetFormat();
DWORD wavesize = wf.GetSize();
BYTE* wavedata = new BYTE[wavesize];
if(FAILED(hr = wf.Read(wavedata, wavesize, &wavesize)))
return XA2SE_ERROR_COULD_NOT_READ;
if(soundengine->sv != NULL) {
soundengine->sv->FlushSourceBuffers();
soundengine->sv->DestroyVoice();
}
if(FAILED(hr = soundengine->pXA2->CreateSourceVoice(&soundengine->sv,pwfx))) {
SAFE_DELETE(wavedata);
return XA2SE_ERROR_COULD_NOT_CREATE_VOICE;
}
XAUDIO2_BUFFER buffer = {0};
buffer.pAudioData = wavedata;
buffer.Flags = XAUDIO2_END_OF_STREAM;
buffer.AudioBytes = wavesize;
buffer.LoopBegin = 0;
double nos = (double)wavesize / ((pwfx->wBitsPerSample * pwfx->nChannels) / pwfx->nSamplesPerSec);
buffer.LoopLength = (unsigned int)nos;
buffer.LoopLength = 0;
buffer.LoopCount = (mode == XA2SE_PLAY_LOOP ? XAUDIO2_LOOP_INFINITE : 0);
if(FAILED(hr = soundengine->sv->SubmitSourceBuffer(&buffer))) {
SAFE_DELETE_ARRAY(wavedata);
return XA2SE_COULD_NOT_SUBMIT_BUFFER;
}
hr = soundengine->sv->Start(0);
//SAFE_DELETE_ARRAY(wavedata);
return TRUE;
}
WaveFile::WaveFile() {
m_pwfx = NULL;
m_hmmio = NULL;
m_pResourceBuffer = NULL;
m_dwSize = 0;
}
WaveFile::~WaveFile() {
Close();
SAFE_DELETE_ARRAY(m_pwfx);
}
HRESULT WaveFile::Open( LPWSTR strFileName)
{
HRESULT hr;
if( strFileName == NULL )
return E_INVALIDARG;
SAFE_DELETE_ARRAY(m_pwfx);
m_hmmio = mmioOpenW( strFileName, NULL, MMIO_ALLOCBUF | MMIO_READ );
if( NULL == m_hmmio ) {
return XA2SE_ERROR_COULD_NOT_OPEN_FILE;
}
if(FAILED(hr = ReadMMIO())) {
// ReadMMIO will fail if its an not a wave file
mmioClose( m_hmmio, 0 );
return XA2SE_ERROR_NOT_WAVE_FILE;
}
if( FAILED( hr = ResetFile() ) )
return XA2SE_ERROR_COULD_NOT_RESET;
// After the reset, the size of the wav file is m_ck.cksize so store it now
m_dwSize = m_ck.cksize;
return hr;
}
HRESULT WaveFile::ReadMMIO()
{
MMCKINFO ckIn; // chunk info. for general use.
PCMWAVEFORMAT pcmWaveFormat; // Temp PCM structure to load in.
memset( &ckIn, 0, sizeof(ckIn) );
m_pwfx = NULL;
if((0 != mmioDescend(m_hmmio,&m_ckRiff,NULL,0)))
return XA2SE_ERROR_COULD_NOT_DESCEND;
// Check to make sure this is a valid wave file
if((m_ckRiff.ckid != FOURCC_RIFF) || (m_ckRiff.fccType != mmioFOURCC('W','A','V','E')))
return XA2SE_ERROR_RIFF_ERROR;
// Search the input file for for the 'fmt ' chunk.
ckIn.ckid = mmioFOURCC( 'f', 'm', 't', ' ' );
if( 0 != mmioDescend( m_hmmio, &ckIn, &m_ckRiff, MMIO_FINDCHUNK ) )
return XA2SE_ERROR_COULD_NOT_DESCEND;
// Expect the 'fmt' chunk to be at least as large as <PCMWAVEFORMAT>;
// if there are extra parameters at the end, we'll ignore them
if( ckIn.cksize < ( LONG )sizeof( PCMWAVEFORMAT ) )
return XA2SE_ERROR_SIZE_ERROR;
// Read the 'fmt ' chunk into <pcmWaveFormat>.
if( mmioRead( m_hmmio, ( HPSTR )&pcmWaveFormat,
sizeof( pcmWaveFormat ) ) != sizeof( pcmWaveFormat ) )
return XA2SE_ERROR_COULD_NOT_READ;
// Allocate the waveformatex, but if its not pcm format, read the next
// word, and thats how many extra bytes to allocate.
if( pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM )
{
m_pwfx = ( WAVEFORMATEX* )new CHAR[ sizeof( WAVEFORMATEX ) ];
if( NULL == m_pwfx )
return XA2SE_ERROR_UNEXPECTED_NULL_VALUE;
// Copy the bytes from the pcm structure to the waveformatex structure
memcpy( m_pwfx, &pcmWaveFormat, sizeof( pcmWaveFormat ) );
m_pwfx->cbSize = 0;
}
else
{
// Read in length of extra bytes.
WORD cbExtraBytes = 0L;
if( mmioRead( m_hmmio, ( CHAR* )&cbExtraBytes, sizeof( WORD ) ) != sizeof( WORD ) )
return XA2SE_ERROR_COULD_NOT_READ;
m_pwfx = ( WAVEFORMATEX* )new CHAR[ sizeof( WAVEFORMATEX ) + cbExtraBytes ];
if( NULL == m_pwfx )
return XA2SE_ERROR_UNEXPECTED_NULL_VALUE;
// Copy the bytes from the pcm structure to the waveformatex structure
memcpy( m_pwfx, &pcmWaveFormat, sizeof( pcmWaveFormat ) );
m_pwfx->cbSize = cbExtraBytes;
// Now, read those extra bytes into the structure, if cbExtraAlloc != 0.
if( mmioRead( m_hmmio, ( CHAR* )( ( ( BYTE* )&( m_pwfx->cbSize ) ) + sizeof( WORD ) ),
cbExtraBytes ) != cbExtraBytes )
{
SAFE_DELETE( m_pwfx );
return XA2SE_ERROR_COULD_NOT_READ;
}
}
// Ascend the input file out of the 'fmt ' chunk.
if( 0 != mmioAscend( m_hmmio, &ckIn, 0 ) )
{
SAFE_DELETE( m_pwfx );
return XA2SE_ERROR_COULD_NOT_ASCEND;
}
return S_OK;
}
DWORD WaveFile::GetSize() {
return m_dwSize;
}
HRESULT WaveFile::ResetFile() {
if( m_hmmio == NULL )
return CO_E_NOTINITIALIZED;
// Seek to the data
if( -1 == mmioSeek( m_hmmio, m_ckRiff.dwDataOffset + sizeof( FOURCC ),
SEEK_SET ) )
return XA2SE_ERROR_COULD_NOT_SEEK;
// Search the input file for the 'data' chunk.
m_ck.ckid = mmioFOURCC( 'd', 'a', 't', 'a' );
if( 0 != mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) )
return XA2SE_ERROR_COULD_NOT_DESCEND;
return S_OK;
}
HRESULT WaveFile::Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead ) {
MMIOINFO mmioinfoIn; // current status of m_hmmio
if( m_hmmio == NULL )
return CO_E_NOTINITIALIZED;
if( pBuffer == NULL || pdwSizeRead == NULL )
return E_INVALIDARG;
*pdwSizeRead = 0;
if( 0 != mmioGetInfo( m_hmmio, &mmioinfoIn, 0 ) )
return XA2SE_ERROR_COULD_NOT_GET_INFO;
UINT cbDataIn = dwSizeToRead;
if( cbDataIn > m_ck.cksize )
cbDataIn = m_ck.cksize;
m_ck.cksize -= cbDataIn;
for( DWORD cT = 0; cT < cbDataIn; cT++ )
{
// Copy the bytes from the io to the buffer.
if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead )
{
if( 0 != mmioAdvance( m_hmmio, &mmioinfoIn, MMIO_READ ) )
return XA2SE_ERROR_COULD_NOT_ADVANCE;
if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead )
return XA2SE_ERROR_COULD_NOT_READEND;
}
// Actual copy.
*( ( BYTE* )pBuffer + cT ) = *( ( BYTE* )mmioinfoIn.pchNext );
mmioinfoIn.pchNext++;
}
if( 0 != mmioSetInfo( m_hmmio, &mmioinfoIn, 0 ) )
return XA2SE_ERROR_COULD_NOT_SET_INFO;
*pdwSizeRead = cbDataIn;
return S_OK;
}
HRESULT WaveFile::Close() {
if ( m_hmmio != NULL ) {
mmioClose( m_hmmio, 0 );
m_hmmio = NULL;
}
SAFE_DELETE_ARRAY( m_pResourceBuffer );
return S_OK;
}
最佳答案
我碰巧在某些方面使用XAudio,并且检查了我的代码。奇怪的是,我有一条评论说不要在AudioDevice析构函数本身中使用CoUninitialize();
,我还记得原因:
您正在使用CoInitializeEx( NULL, COINIT_MULTITHREADED );
初始化COM。这意味着除了您的应用程序之外,还有其他线程(特别是其他XAudio线程)正在运行。当您在XA2SoundEngine的析构函数中联合CoUninitialize()时,该线程可能尚未退出或未完成其资源的清理。从本质上讲,您是在要求COM进行一些可能还没有准备好执行的杀死操作(这是我最好的猜测,因为我自己一直在获取访问冲突)。
我解决它的方法只是没有CoUninitialize()
。微软在较新版本的XAudio2中意识到,不告诉您正在使用的线程何时产生或垂死是多么愚蠢的事情,因此XAudio2(我相信在Windows 8上为2.8)为您完成了CoInitializeEx
和CoUninitialize
的工作。如果您在那个环境中,那么您不应该首先调用这些方法。
如果这恰好在DLL中,则可以在DLL自身附加时安全地调用CoUninitialize和CoInitializeEx。它将运行而没有错误:
BOOL APIENTRY DllMain ( HANDLE hModule, DWORD dwReason, LPVOID lpReserved ) {
switch (dwReason) {
case DLL_PROCESS_ATTACH:
CoInitializeEx(NULL, COINIT_MULTITHREADED);
break;
case DLL_THREAD_ATTACH:
CoInitializeEx(NULL, COINIT_MULTITHREADED);
break;
case DLL_THREAD_DETACH:
CoUninitialize();
break;
case DLL_PROCESS_DETACH:
CoUninitialize();
break;
default:
// Wat...
break;
}
return TRUE;
}
关于c++ - 卸载时XAudio2访问冲突异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16049677/
我的工作是将每条记录写入 Hadoop 映射中的 DynamoDB。 我无法使用具有 httpclient-4.2.5.jar 和 httpcore-4.2.5.jar 的 Hadoop 2.6 运行
我在 JavaScript 中嵌套了循环开关,例如: for (var i = 0; i < checkBoxIds.length; i++) { if ($('#' + checkB
我有一个文件夹被重命名的分支。现在我正在尝试合并从主干到这个分支的更改,但是在主干中修改的文件仍然在原始文件夹名称下,因此 svn 引发了树冲突。我该如何解决这个问题? 该文件夹已使用 svn ren
我在使用 jquery 暴露插件和 Masked 输入插件时遇到了问题。问题是它们都占用 $.mask 函数,从而导致冲突。但我非常需要这两个插件一起工作。我会将其中一个中的 $.mask 重命名为.
我正在尝试为我所有的 INPUT 元素做一个简单的 :focus 效果,就像这样: INPUT:focus { border-color: orange; } 这很好用,直到我将这段 CSS 添加到样
我是 javascript 的新手。 在 wordpress 上工作,我在自定义 js 中为我的主题输入了以下函数: document.getElementsByName("empty_cart")[
为什么有些 javascript 会与其他的发生冲突?我的意思是我一直在为图片库使用 javascript 代码,然后尝试在 jquery 中获取文本水印。为什么在使用 jquery 之后,画廊完全消
是否可以根据已知的输入值创建 MD5 碰撞? 所以例如我有输入字符串 abc与 MD5 900150983cd24fb0d6963f7d28e17f72 . 现在我想将字节添加到字符串 def获得相同
我在我的项目中使用原型(prototype): NodeParser.prototype.getChildren = function(parentContainer) { return fl
根据我对 merge 冲突的理解,当两个人更改了同一文件和/或修改了该文件中的同一行时,就会发生 merge 冲突。所以当我做一个 git pull origin master 我期望 merge 冲
iPad 上 Mobile Safari 中的 HTML5 模板。带 iScroll 的 Div 工作正常。 if/else 语句中还包含一个 jQuery 函数。该函数测试用户是否在 iScroll
我一直在尝试使 2 个脚本(1 个 mootol 和 1 个 jquery)在同一页面上工作,但没有成功。我一直在研究许多论坛等,但我仍然无法使这两个脚本同时工作。 这就是它在我的标题中的样子: /w
我想克隆带标题的问号。一切正常,但是当我将鼠标悬停在新问号上时,第一个问号上会出现工具提示。有什么想法吗? 我正在使用 jQuery 和醉酒的工具提示。 Demo here click here
好吧,我已经在一个 friend 的网站上工作了一段时间了。我的编码技能......值得怀疑,而且我遇到了很多问题。 目前我网站上的 jQuery 停止工作了,我找不到原因,并且我已尽一切努力让它工作
我想使用一个文件来保存所有#define 和常量:示例 #ifndef CONSTANTS_H_ #define CONSTANTS_H_ #include //OVERALL DEFS
我在我的表单中的所有 HTML 下都有一些验证码,这似乎阻止了我的复选框验证码的工作,一旦我在我的 HTML 下的代码周围添加/* */(使其不活动),我就得出了这个结论) 复选框验证代码开始正常工作
我是新手。我的页面上有两个 javascript/jquery。如果我使用第一个脚本,第二个脚本将不起作用。如果我删除第一个脚本,第二个脚本就可以正常工作。我不知道如何解决这个问题。我知道有一个“无冲
我是 Bison 新手,在处理 Shift/Reduce 冲突时遇到了麻烦... 我正在为C语言编写语法规则:ID是标识变量的标记,我编写此规则是为了确保即使将标识符写在括号中,也可以考虑它。 id
我目前正在使用 LibGdx 开发我的第一个 Android 游戏项目。这是一款 2D 迷宫游戏,您可以使用触摸输入从其中一个入口到其中一个导出“画出”一条线。世界本身是一个 TiledMap,目前仅
我正在尝试通过 javascript 完成表单验证,并在 #form# 标记中放置一个要执行的 .py 文件操作。但问题是,当我提交数据后,它不会重定向到 .py 操作。所以我摆脱了 preventd
我是一名优秀的程序员,十分优秀!