如何用Directshow访问存储在内存中的资源?

作者&投稿:空康 (若有异议请与网页底部的电邮联系)
c# directshow如何立刻释放资源~

那这个对象总应该有close之类的方法吧
.net只能清理托管内存,对非托管的还真没有什么好办法


可以在代码里手动回收垃圾
比如:
direct变量 = null;
GC.Collect();

这个可能要看一些驱动的相关知识才能解决,建议你用directshow的相关知识。还有一些API的函数。相信会对你有些帮助。

Introduction (序)
这一章我们学习怎样用DX来播放声音和音乐。我们将会使用DirectX Audio来播放WAV和MIDI文件,使用DirectShow来播放MP3文件。此章我们仍然有一个简单的程序作例子,它会播放MP3的背景音乐,当用户用鼠标点击某个数字时它会播放一些音效。

DirectX Audio and DirectShow (DirectX Audio和 DirectShow)
我们已经学习过Direct3D和DirectInput了,现在,我要介绍另外两个DirectX组件:DirectX Audio和DirectShow。我们用DirectX Audio来播放WAV和MIDI文件;用DirectShow来播放媒体流,例如AVI和MP3。在此教程中,我们只学习一下用DirectShow播放MP3的方法。

Wav, Midi and Mp3 - When should I use what?
(WAV,MIDI和MP3——什么时候该用什么?)
那末,什么时候用什么格式好呢?嗯,这基本上取决于你的个人爱好。下面是这些格式的简介,过后我会说一下我的选择:

Wav files (WAV文件)
WAV是一种未经压缩的数字音频,CD音质,但是体积非常庞大。

Midi files (MIDI文件)
MIDI文件并没有保存音频记录,它实际上更像是一套演奏指令,所以,它的体积是非常小的。MIDI的音质完全取决于演奏设备(如我们的声卡),它在高端的设备上能表现出色,而在低端设备上则表现较差。

Mp3 files (MP3文件)
同WAV文件一样,MP3也是一种数字音频格式。不同的是,MP3文件是经过压缩的,而且是有损压缩,这意味着它的体积将大大地减小,而音质上将会有一些失真(实际上接近CD音质,基本听不出失真)。而且,MP3是一种媒体流,这意味着在播放它的时候不会将它整个的读入,取而代之的是分期的做部分读入。

My preference (我的选择)
你大概会选择MP3或MIDI来作背景音乐,特别是当你希望用户能从网上下载你的程序时。MP3和MIDI格式文件的体积都比较小,它们适合做长时间的背景音乐播放。而当需要播放简短的声效时,例如爆炸声等,我更趋向于使用WAV文件,品质能稍好一些。如果文件的体积不是问题的话,实际上我们可以使用WAV文件来播放所有的声音和音乐。

Include and Library files (头文件与库文件)
我们的项目需要增加以下的头文件和库文件:

o dmusici.h
o dsound.h
o dshow.h
o dsound.lib
o strmiids.lib

Setting up DirectX Audio (设置DirectX Audio)
要使用Direct Audio我们需要创建两个对象:演奏对象(Performance Object,有些资料翻译为执行对象)和加载器(Loader)。演奏对象是Direct Audio中的最高级对象,用于处理从源到合成器的数据流。加载器用于把文件(WAV或MIDI)加载到声音段以待播放。这两个对象在整个应用程序中我们每样只需要一个,所以,我们已经把它们创建为CGame的成员变量了。下面是它们的定义:

IDirectMusicPerformance8* m_pDirectAudioPerformance;
IDirectMusicLoader8* m_pDirectAudioLoader;

由于Direct Audio是一个纯COM,所以我们需要初始化COM。其实很简单,我们只需要在CGame的构造函数中调用CoInitialize函数即可:

CoInitialize(NULL);

初始化COM后,我们就可以创建上述的那两个DirectX Audio对象了。为此,我们给CGame做了一个新的函数InitialiseDirectAudio,它将会在Initialise函数中被调用。代码如下:

bool CGame::InitialiseDirectAudio(HWND hWnd)
{
LogInfo("<br>Initialise DirectAudio:");

//Create the DirectAudio performance object
if(CoCreateInstance(CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC,
IID_IDirectMusicPerformance8,
(void**) &m_pDirectAudioPerformance) != S_OK)
{
LogError("<li>Failed to create the DirectAudio perfomance object.");
return false;
}
else
{
LogInfo("<li>DirectAudio perfomance object created OK.");
}

//Create the DirectAudio loader object
if(CoCreateInstance(CLSID_DirectMusicLoader, NULL, CLSCTX_INPROC,
IID_IDirectMusicLoader8,
(void**) &m_pDirectAudioLoader) != S_OK)
{
LogError("<li>Failed to create the DirectAudio loader object.");
return false;
}
else
{
LogInfo("<li>DirectAudio loader object created OK.");
}

//Initialise the performance object
if(FAILED(m_pDirectAudioPerformance->InitAudio(NULL, NULL, hWnd,
DMUS_APATH_SHARED_STEREOPLUSREVERB,
64, DMUS_AUDIOF_ALL, NULL)))
{
LogError("<li>Failed to initialise the DirectAudio perfomance object.");
return false;
}
else
{
LogInfo("<li>Initialised the DirectAudio perfomance object OK.");
}

//Get the our applications "sounds" directory.
CHAR strSoundPath[MAX_PATH];
GetCurrentDirectory(MAX_PATH, strSoundPath);
strcat(strSoundPath, "\\Sounds");

//Convert the path to unicode.
WCHAR wstrSoundPath[MAX_PATH];
MultiByteToWideChar(CP_ACP, 0, strSoundPath, -1, wstrSoundPath, MAX_PATH);

//Set the search directory.
if(FAILED(m_pDirectAudioLoader->SetSearchDirectory(GUID_DirectMusicAllTypes,
wstrSoundPath, FALSE)))
{
LogError("<li>Failed to set the search directory '%s'.", strSoundPath);
return false;
}
else
{
LogInfo("<li>Search directory '%s' set OK.", strSoundPath);
}

return true;
}

我们用CoCreateInstance函数创建了演奏对象和加载器,然后调用了InitAudio模块来初始化演奏对象。上面代码中给InitAudio的参数是很典型的,所以你可以沿用它(查看一下SDK中的关于InitAudio函数以及它的参数的内容以获得更多的了解)。最后,我们设置了搜索目录。搜索目录应该被设置为存放声音文件的目录,以便加载器可以正确的加载声音文件。在本例中,搜索目录被设置为“Sounds”文件夹,它应该在本例的项目文件夹当中。

A new class - CSound (一个新的类——CSound)
我们已经为使用DirectX Audio作了必要的准备工作,现在,我们就可以加载、播放声音和音乐了。为此,我们做了一个新的类CSound,下面是它的代码,稍后我会解释它是怎样工作的:

CSound::CSound()
{
m_pDirectAudioPerformance = NULL;
m_pDirectAudioLoader = NULL;
m_pSegment = NULL;
m_pGraph = NULL;
m_pMediaControl = NULL;
m_pMediaPosition = NULL;
m_enumFormat = Unknown;

LogInfo("<li>Sound created OK");
}

void CSound::InitialiseForWavMidi(IDirectMusicPerformance8* pDirectAudioPerformance, IDirectMusicLoader8* pDirectAudioLoader)
{
m_pDirectAudioPerformance = pDirectAudioPerformance;
m_pDirectAudioLoader = pDirectAudioLoader;

m_enumFormat = WavMidi;
}

void CSound::InitialiseForMP3()
{
CoCreateInstance(CLSID_FilterGraph, NULL,
CLSCTX_INPROC, IID_IGraphBuilder, (void**)&m_pGraph);

m_pGraph->QueryInterface(IID_IMediaControl, (void**)&m_pMediaControl);

m_pGraph->QueryInterface(IID_IMediaPosition, (void**)&m_pMediaPosition);

m_enumFormat = MP3;
}

CSound::~CSound()
{
Stop();

SafeRelease(m_pSegment);
SafeRelease(m_pGraph);
SafeRelease(m_pMediaControl);
SafeRelease(m_pMediaPosition);

LogInfo("<li>Sound destroyed OK");
}

bool CSound::LoadSound(const char* szSoundFileName)
{
WCHAR wstrSoundPath[MAX_PATH];
CHAR strSoundPath[MAX_PATH];

switch(m_enumFormat)
{
case MP3:
//Get the our applications "sounds" directory.
GetCurrentDirectory(MAX_PATH, strSoundPath);
strcat(strSoundPath, "\\Sounds\\");
strcat(strSoundPath, szSoundFileName);

//Convert the path to unicode.
MultiByteToWideChar(CP_ACP, 0, strSoundPath, -1,
wstrSoundPath, MAX_PATH);

m_pGraph->RenderFile(wstrSoundPath, NULL);
break;
case WavMidi:
//Convert the filename to unicode.
MultiByteToWideChar(CP_ACP, 0, szSoundFileName, -1,
wstrSoundPath, MAX_PATH);

//Load a sound
m_pDirectAudioLoader->LoadObjectFromFile(CLSID_DirectMusicSegment,
IID_IDirectMusicSegment8,
wstrSoundPath,
(void**) &m_pSegment);

m_pSegment->Download(m_pDirectAudioPerformance);
break;
default:
return false;
}

return true;
}

bool CSound::Play(DWORD dwNumOfRepeats)
{

switch(m_enumFormat)
{
case MP3:
//Make sure that we are at the start of the stream
m_pMediaPosition->put_CurrentPosition(0);

//Play mp3
m_pMediaControl->Run();
break;
case WavMidi:
//Set the number of times the sound repeats
m_pSegment->SetRepeats(dwNumOfRepeats); //To loop the sound forever, pass
//in DMUS_SEG_REPEAT_INFINITE

//Play the loaded sound
m_pDirectAudioPerformance->PlaySegmentEx(m_pSegment, NULL, NULL, 0, 0,
NULL, NULL, NULL);
break;
default:
return false;
}

return true;
}

bool CSound::Stop()
{
switch(m_enumFormat)
{
case MP3:
m_pMediaControl->Stop();
break;
case WavMidi:
//Stop the loaded sound
m_pDirectAudioPerformance->StopEx(m_pSegment, 0, 0);
break;
default:
return false;
}

return true;
}

bool CSound::IsPlaying()
{
switch(m_enumFormat)
{
case MP3:
REFTIME refPosition;
REFTIME refDuration;

m_pMediaPosition->get_CurrentPosition(&refPosition);
m_pMediaPosition->get_Duration(&refDuration);

if(refPosition < refDuration)
{
return true;
}
else
{
return false;
}
break;
case WavMidi:
if(m_pDirectAudioPerformance->IsPlaying(m_pSegment, NULL) == S_OK)
{
return true;
}
else
{
return false;
}
break;
default:
return false;
}
}

那末,怎样用CSound来播放音乐呢?这很简单。首先,创建一个CSound对象,然后根据你想播放的声音类型来调用InitialiseForWavMidi或是InitialiseForMP3,二者选其一。接着,调用LoadSound读取声音文件。最后,调用Play模块来播放声音即可。很简单,不是吗?嗯,还有两个模块:Stop模块用来停止播放;IsPlaying模块用来检测声音是否正在播放。下面介绍了各个模块是怎样工作的:

InitialiseForWavMidi
InitialiseForWavMidi模块用于初始化CSound对象以待播放WAV或MIDI文件。它的两个输入参数是我们在CGame中创建好的演奏对象和加载器的接口指针,然后这两个指针会被保存为它的成员变量以备用。我们会把CSound的格式设置为WavMidi。

InitialiseForMP3
InitialiseForMP3模块用于初始化CSound对象以待播放MP3文件,它没有输入参数。InitialiseForMP3调用CoCreateInstance函数创建了一个DirectShow过滤器图管理器对象。我们能使用CoCreateInstance是因为我们在CGame的构造函数中已经调用过CoInitialize函数了。有了过滤器图管理器对象之后,我们调用它的模块QueryInterface来创建另外两个对象:一个媒体控制对象和一个媒体定位对象。这三个对象的指针将会被保存为CSound对象的成员变量。同理,我们把CSound的格式设置为MP3;

LoadSound
初始化好CSound对象后,我们就可以调用LoadSound来读取声音文件了。LoadSound只有一个参数,就是声音文件的文件名。这里不是一个路径而是一个文件名是因为所有的声音文件都应该在我们的项目的“Sounds”目录中。

如果这个CSound对象的格式为MP3,我们首先会构造出一个完整的文件路径,然后把它转换为Unicode字符集的字符串。接着,我们只需要调用过滤器图管理器对象的RenderFile模块并构造一个用于播放指定文件的过滤器图即可。

如果这个CSound对象的格式为WavMidi,我们首先会把文件名转换成Unicode字符集的字符串。接着我们会调用LoadObjectFromFile,它会载入文件并返回一个段(segment)指针。最后,我们调用段的Download模块下载波段到演奏对象里。

现在我们已经准备好来播放声音了。

Play
当文件载入后,我们就能播放它了。Play模块唯一的可选参数(默认为0)就是重复播放次数,只在播放WAV或MIDI时有效。

如果这个CSound对象的格式为MP3,我们首先会调用媒体定位对象的put_CurrentPosition模块来确认一下我们是否在媒体流的开始处。然后,我们调用媒体控制对象的Run模块来播放MP3。

如果这个CSound对象的格式为WavMidi,我们首先会设置重复次数。然后我们调用PlaySegmentEx来播放已经载入的段。如果你想让声音永远重复,输入DMUS_SEG_REPEAT_INFINITE恒量。

Stop
这能简单地停止正在播放的声音。如果是MP3,就调用媒体控制对象的Stop模块。如果是WAV或MIDI,就调用演奏对象的StopEx模块并输入要停止的段。

IsPlaying
最后,IsPlaying模块用于检测当前是否正在播放。是就返回true,不是则返回false。如果是MP3,我们会根据当前的媒体流定位与整个媒体流的长度做对比,以得知我们是否正在播放(看是否在流的终点)。如果是WAV,我们就调用演奏对象的IsPlaying模块并输入要检测的段以测试。

Cleaning up (清理)
在Csound的析构函数中我们会停止声音的播放并释放对象。在CGame中有一个新的函数CleanUpDirectAudio代码如下:

void CGame::CleanUpDirectAudio()
{
//Stop all sounds.
m_pDirectAudioPerformance->Stop(NULL, NULL, 0, 0);

//CleanUp
m_pDirectAudioPerformance->CloseDown();

SafeRelease(m_pDirectAudioLoader);
SafeRelease(m_pDirectAudioPerformance);

LogInfo("<li>CleanUpDirectAudio finished.");
}

Here we first stop all sounds from playing (just in case), then we close down the performance object before releasing it and the loader object. Also, in the CGame deconstructor we need to call CoUninitialize to close down the COM library (shown below).
这里我们首先停止所有声音的播放,然后关闭演奏对象,释放演奏对象和加载器。而且,在CGame的析构函数中我们会调用CoUninitialize来关掉COM:

CoUninitialize();

那末现在我们能在程序中播放音乐和声音了。当程序开始时,MP3的背景音乐就会开始播放。移动鼠标并点击不同的数字我们对听到不同的声音。这里的背景MP3只是一个小片断的循环,愿意的话你可以替换成你喜欢的音乐。(译者:我把我的MP3都放了一遍爽)

Summary (摘要)
In this tutorial we learnt how to play sounds and music using two new DirectX components, DirectX Audio and DirectShow. In the next tutorial we will use all of the skills we have seen so far to create our first game: 3D Pong. This game will be simple, but will have all of the key features that you would expect from any game.


direct翻译成中文
direct的意思:adv.直接;径直;亲自 v.指导;指示;管理;监督 adj.直接的;亲自的;亲身的;笔直的 direct的发音:美 [daɪˈrekt] 英 [daɪ'rekt]第三人称单数:directs 现在分词:directing 过去式:directed 例句:1.Relative to the direct advertising, sports sponsorship...

我的tc512用directs诊断工具检测是512mb是什么意思
开始打开点运行输入dxdiag点确认出来directs诊断工具点显示就出来显卡的数据和内存了

direct是什么意思
adj.直接的; 直的; 直系的; 率直的;adv.直接地; 径直地; 直截了当地; 正好;vt.(用建议、指示、有益的情报等) 指导; 导演(戏剧或电影) 指示方向; 把…对准(某方向或某人)[例句]The most direct route to the town centre 到市中心最直接的路线 [其他]第三人称单数:directs 现在分词:...

direct的名词
第三人称单数:directs 现在分词:directing 过去式:directed 过去分词:directed direction:英[dəˈrekʃn];美[dəˈrekʃn] n.方向;方位;趋势;动向;方面;目的;用法说明;管理;(电影导演的)指点,指示 复数:directions direct基本用法 1、direct的基本意思是“指示方向”“指引”,表示向正确的路线行走,或...

direct是什么意思
adj.直接的; 直的; 直系的; 率直的;adv.直接地; 径直地; 直截了当地; 正好;vt.(用建议、指示、有益的情报等)指导; 导演(戏剧或电影); 指示方向; 把…对准(某方向或某人);vt.& vi.指导,导演,管理;vi.引路; 当向导; 领唱; 领奏;第三人称单数:directs过去分词:directed现在进行时...

anker direct 这个direct是什么意思
adv.直接地; 径直地; 直截了当地; 正好;vt.(用建议、指示、有益的情报等) 指导; 导演(戏剧或电影); 指示方向; 把…对准(某方向或某人);[例句]They'd come on a direct flight from Athens.他们是搭乘从雅典直飞这里的航班过来的。[其他]第三人称单数:directs 现在分词:directing 过去...

direct是及物动词还是不及物动词
"Excuse me, can you direct me to the station?""对不起,你能不能告诉我去火车站怎么走?"She directed her steps towards the end of the garden.她向花园的尽头走去。指导;指挥;管理;支配 It is universally accepted that one's thinking directs one's actions."思想指导行动,这是普遍...

我的tc512用directs诊断工具检测是512mb是用了物理内存了吗
TC是Turbo Cache技术简称能让显卡使用闲置的系统内存作为显存,一般划分情况是不能手动干预的,根据驱动说明,大概每512内存就划分128显存(是在显卡板带显存以外增加),这样可以通过减少板带显存而减低生产成本,而且划分了的系统内存在不需要使用时是可以释放,即划分过程是双向可逆的 512M不是你实际的显存 而是...

用directto把注意力、精力贯注在…上造句?
词典释义 讲解1:08 adj.直接的;亲自的;亲身的;笔直的;径直的;最近的;直射的 v.把…对准(某方向或某人);管理;监督;指导;导演(戏剧或电影);指挥(管弦乐队)adv.直接;径直;亲自 高考 \/ CET4 \/ 考研 \/ BEC 变形 动词 第三人称单数:directs 现在分词:directing 过去分词:directed 过去式:directed ...

方便的单词怎么写
adj.直接的; 直的; 直系的; 率直的;adv.直接地; 径直地; 直截了当地; 正好;vt.(用建议、指示、有益的情报等)指导; 导演(戏剧或电影); 指示方向; 把…对准(某方向或某人);vt.& vi.指导,导演,管理;vi.引路; 当向导; 领唱; 领奏;第三人称单数:directs过去分词:directed现在进行时...

北碚区13854726590: Directx诊断工具
佟依清芬: 运行里面输入 DXDIAG 在Windows中,与游戏以及多媒体直接相关的就是DirectX,通过系统自带的DirectX诊断工具就可以对游戏和多媒体出现的显示、声音不正常等问题进行诊断,让它们运行得更顺畅. 一、认识DirectX DirectX是Windows操...

北碚区13854726590: directx sdk update是什么 -
佟依清芬: 是directx sdk的更新(升级) Microsoft DirectX SDK 是DirectX编程的软件.包含了开发尖端多媒体应用软件不可或缺的开发工具,以及runtime、headers及程序库、范例执行文件、文件、DirectX工具、并且同时支援C++ 以及 Visual Basic开发软件.http://baike.baidu.com/view/3501927.html

北碚区13854726590: VOD视频点播系统的VOD -
佟依清芬: VOD是Video On Demand的缩写,即视频点播的意思.顾名思义,它是一种可以按用户需要点播节目的交互式视频系统,或者更广义一点讲,它可以为用户提供各种交互式信息服务. 交互式视频点播系统一般由VOD前端处理系统、传输网络、...

北碚区13854726590: 不懂电脑术语,关于电脑配置···· -
佟依清芬: DirectX诊断工具 是XP自带的 重新安装Win XP也是有的 请放心 DirectX是Windows操作系统的一种扩展功能,微软定义为“硬件设备无关性”.通过它可以增强计算机的多媒体功能,比如3D图形的显示能力,增强声音处理能力等.其主要目的...

北碚区13854726590: DirectX诊断工具显示不出显示设备 -
佟依清芬: vga是通用显卡驱动设备的意思!问题的症结还是在于你没有安装正确的显卡驱动... 如果没有专用驱动,用DirectX是诊断不出显卡类型的! 建议你下载everest硬件检测程序,用它可以检测出绝大部分类型的硬件!当然包括显卡啦! 同时everest还会指出硬件对应驱动的下载连接! 即使没有指出,你也可以根据检测出来的牌子和型号,到驱动网站下载~~

北碚区13854726590: VRAM是什么?硬体加速模式是什么 -
佟依清芬: Video Random Access Memory:显存,帧存储器,刷新存储器,或VRAM(缩写). 【概述】 显卡上的随机存取存储器.是一种双端口内存,它允许在同一时间被所有硬件(包括中央处理器、显示芯片等)访问.它比EDO DRAM快20%...

北碚区13854726590: DirectX诊断工具无法开启? -
佟依清芬: 桌面右键属性-设置--高级-疑难解答 中的硬件加速开全,再在DX中启用加速.

北碚区13854726590: Media Foundation与DirectShow的具体差别有哪些 -
佟依清芬: DirectShow是微软公司在ActiveMovie和Video for Windows的基础上推出的新一代基于COM(Component Object Model)的流媒体处理的开发包,与DirectX开发包一起发布.DirectShow使用一种叫Filter Graph的模型来管理整个数据流的处理过程...

北碚区13854726590: 显卡的接口在DirectX诊断工具的哪里?
佟依清芬: 在Windows中,与游戏以及多媒体直接相关的就是DirectX,通过系统自带的DirectX诊断工具就可以对游戏和多媒体出现的显示、声音不正常等问题进行诊断,让它们运行得更顺畅. 一、认识DirectX DirectX是Windows操作系统的一种扩展功能...

北碚区13854726590: 硬件加速的疑问 -
佟依清芬: 就硬件而言,造成蓝屏的只有内存,跟显卡,主板鼓包容易重启,电源老了根本起步来机器.如果是硬件加速问题,有可能是CPU,或者显卡,你更新一下显卡驱动试试.

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网