青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

天行健 君子當自強而不息

用DirectX Audio和DirectShow播放聲音和音樂(6)


本篇是 用DirectX Audio和DirectShow播放聲音和音樂(5)的續篇。

 

加載音色庫(樂器)

DirectMusic 加載器在使用固有文件或者MIDI文件的時候會自動加載默認的音色庫。樂器總是被一組一組地使用,很多組樂器音色的集合被稱之為DLS音色庫(可下載的音樂)。每組樂器使用三個值編號,它們是:最高有效位(most-significant byte,MSB),最低有效位(least-significant byte,LSB)和組編號。

通常播放MIDI文件的樂器組是標準化的,也就是說編號為1的樂器總是鋼琴,如果想使用新的鋼琴作為樂器,可以從DLS集合中加載。DirectMusic包含了標準的樂器集合,通常稱之為GM/GS集合(GM = General MIDI,GS = General Synthesizer),這個集合由日本羅蘭(Roland)公司提出,稱為MIDI合成器標準。

如果使用新的樂器取代標準MIDI樂器庫中的樂器,需要確定該樂器的MSB和LSB為0,否則就需要為樂器庫中的每個樂器都嘗試新的賦值,以免打亂樂器庫樂器排列。如果只想修改音色庫中的一對樂器,只需要將它們保存在樂器庫中即可。在下次加載DLS的時候,就會自動用新修改的樂器覆蓋住內存中的舊樂器,如下圖所示:

當DLS加載完成的時候,就可以通知 DirectMusic使用音色庫對音樂進行播放了。

加載DLS音色庫,需要從加載器中獲取一個IDirectMusicCollection8對象,然后再次使用IDirectMusicLoader8::GetObject加載音色庫,但是這一次指定的是音色庫對象和音色庫文件名。

以下代碼演示了如何加載指定的音色庫:

//--------------------------------------------------------------------------------
// Load DirectMusic collection object.
//--------------------------------------------------------------------------------
IDirectMusicCollection8* Load_DLS_Collection(char* filename)
{
    DMUS_OBJECTDESC dm_obj_desc;
    IDirectMusicCollection8* dm_collection;

    
// get the object

    ZeroMemory(&dm_obj_desc, 
sizeof(DMUS_OBJECTDESC));

    dm_obj_desc.dwSize      = 
sizeof(DMUS_OBJECTDESC);
    dm_obj_desc.guidClass   = CLSID_DirectMusicCollection;
    dm_obj_desc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME | DMUS_OBJ_FULLPATH;

    
// Converts a sequence of multibyte characters to a corresponding sequence of wide characters
    mbstowcs(dm_obj_desc.wszFileName, filename, MAX_PATH);

    
// retrieves an object from a file or resource and returns the speficied interface
    if(FAILED(g_dm_loader->GetObject(&dm_obj_desc, IID_IDirectMusicCollection8, (LPVOID*)&dm_collection)))
        
return NULL;

    
return dm_collection;
}

音色庫被加載后,還需要給音樂片段指定音色庫,這個工作通過設置指定的音樂片段的音軌參數來完成,設置參數使用函數 IDirectMusicSegment8::SetParam。

The SetParam method sets data on a track inside this segment.

Syntax

HRESULT SetParam(
REFGUID
rguidType,
DWORD dwGroupBits,
DWORD dwIndex,
MUSIC_TIME mtTime,
void* pParam
);

Parameters

rguidType

Reference to (C++) or address of (C) the type of data to set. See Standard Track Parameters.

dwGroupBits

Group that the desired track is in. Use 0xFFFFFFFF for all groups. For more information, see Identifying the Track.

dwIndex

Index of the track in the group identified by dwGroupBits in which to set the data, or DMUS_SEG_ALLTRACKS to set the parameter on all tracks in the group that contain the parameter.

mtTime

Time at which to set the data.

pParam

Address of a structure containing the data, or NULL if no data is required for this parameter. The structure must be of the appropriate kind and size for the data type identified by rguidType.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method can return one of the error values shown in the following table.

Return code
DMUS_E_SET_UNSUPPORTED
DMUS_E_TRACK_NOT_FOUND
E_POINTER

 

MIDI的配置

一首歌曲如果已經和音色庫一起被完整地加載到了內存中,這首音樂基本上已經可以使用了,唯一存在的問題是因為系統需要進行配置,以便適應一般MIDI文件的配置,所以需要告訴系統加載的文件是否是一個MIDI文件。告訴DirectMusic使用的是MIDI文件,需要再一次調用參數配置函數 IDirectMusicSegment8:: SetParam。

以下代碼演示了如何使用設置MIDI配置:
 

    // retrieves an object from a file or resource and returns the speficied interface
    if(FAILED(g_dm_loader->GetObject(&dm_obj_desc, IID_IDirectMusicSegment8, (LPVOID*)&g_dm_segment)))
        
return FALSE;

    
// setup midi playing
    if(strstr(filename, ".mid"))
    {
        
// set data on a track inside the segment
        if(FAILED(g_dm_segment->SetParam(GUID_StandardMIDIFile, 0xFFFFFFFF, 0, 0, NULL)))
            
return FALSE;
    }

播放音樂的下一個準備工作就是配置音色庫,將音色庫裝載到演奏器中,通過調用IDirectMusicSegment8:: Download函數來完成操作。

The Download method downloads band data to a performance or audiopath.

Syntax

HRESULT Download(
IUnknown*
pAudioPath
);

Parameters

pAudioPath

Pointer to the IUnknown interface of the performance or audiopath that receives the data.

Return Values

If the method succeeds, the return value is S_OK or DMUS_S_PARTIALDOWNLOAD. See Remarks for IDirectMusicBand8::Download.

If it fails, the method may return one of the error values shown in the following table.

Return code
DMUS_E_NOT_FOUND
DMUS_E_TRACK_NOT_FOUND
E_POINTER

Remarks

All bands and waveform data in the segment are downloaded.

Always call IDirectMusicSegment8::Unload before releasing the segment.


僅當音樂文件為MIDI文件的時候,才需要調用這個函數,因為該函數會改變音樂文件的信息,如果在不適當的時候強制調用該函數,會導致主音軌改變或者丟失。如果要改變音色庫(比如重新指定一個新的DLS給一個段音樂),必須首先卸載音色庫數據,然后再加載新的音色庫,并重新播放音樂。

以下代碼示例了如何使用Download。
 
// downloads band data to a performance
if(FAILED(g_dm_segment->Download(g_dm_performance)))
   
return FALSE;

當完成播放或者切換音色庫時,必須調用一個卸載函數IDirectMusicSegment8::Unload,用它釋放音色庫及其他資源。

g_pDMSegment->Unload(g_pDS);

 

循環和重復

在播放之前最后一個要做的工作是設置重復點和重復次數。例如有一小段音樂,希望重復播放這段音樂里的一小部分,這時就需要設置循環起始點和結束點,然后設置重復播放次數,如下圖所示:

設置循環點是IDirectMusicSegment8::SetLoopPoints函數的職責。

The SetLoopPoints method sets the start and end points of the part of the segment that repeats the number of times set by the IDirectMusicSegment8::SetRepeats method.

Syntax

HRESULT SetLoopPoints(
MUSIC_TIME
mtStart,
MUSIC_TIME mtEnd
);

Parameters

mtStart

Point at which to begin the loop.

mtEnd

Point at which to end the loop. A value of 0 loops the entire segment.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method can return DMUS_E_OUT_OF_RANGE.

Remarks

When the segment is played, it plays from the segment start time until mtEnd, then loops to mtStart, plays the looped portion the number of times set by IDirectMusicSegment8::SetRepeats, and then plays to the end.

The default values are set to loop the entire segment from beginning to end.

The method fails if mtStart is greater than or equal to the length of the segment, or if mtEnd is greater than the length of the segment. If mtEnd is 0, mtStart must be 0 as well.

This method does not affect any currently playing segment states created from this segment.

The loop points of a cached segment persist even if the segment is released, and then reloaded. To ensure that a segment is not subsequently reloaded from the cache, call IDirectMusicLoader8::ReleaseObject on it before releasing it.


很多情況下,我們希望重復播放整首歌曲,這個時候就不需要使用SetLoopPoints函數。設置完循環點后,就可以設置重復次數了(當然,先設置重復次數也是可以的)。如果希望音樂播放一次后就停止,設置重復次數為0,如果希望將曲目播放兩次,需要將重復次數設置為1。設置重復次數使用 IDirectMusicSegment8::SetRepeats函數,這個函數只有一個參數,就是曲目重復的次數,如果將這個值設置為 DMUS_SEG_REPEAT_INFINITE,那么播放就會一直持續。

The SetRepeats method sets the number of times the looping portion of the segment is to repeat.

Syntax

HRESULT SetRepeats(
DWORD
dwRepeats
);

Parameters

dwRepeats

Number of times that the looping portion of the segment is to repeat, or DMUS_SEG_REPEAT_INFINITE to repeat until explicitly stopped. A value of 0 specifies a single play with no repeats.

Return Values

The method returns S_OK.


播放和停止播放

如果要讓演奏器播放音樂片段,只需要調用 IDirectMusicPerformance8::PlaySegmentEx函數就可以了。

The PlaySegmentEx method begins playback of a segment. The method offers greater functionality than IDirectMusicPerformance8::PlaySegment.

Syntax

HRESULT PlaySegmentEx(
IUnknown*
pSource,
WCHAR *pwzSegmentName,
IUnknown* pTransition,
DWORD dwFlags,
__int64 i64StartTime,
IDirectMusicSegmentState** ppSegmentState,
IUnknown* pFrom,
IUnknown* pAudioPath
);

Parameters

pSource

Address of the IUnknown interface of the object to play.

pwzSegmentName

Reserved. Set to NULL.

pTransition

IUnknown interface pointer of a template segment to use in composing a transition to this segment. Can be NULL. See Remarks.

dwFlags

Flags that modify the method's behavior. See DMUS_SEGF_FLAGS.

i64StartTime

Performance time at which to begin playing the segment, adjusted to any resolution boundary specified in dwFlags. The time is in music time unless the DMUS_SEGF_REFTIME flag is set. A value of zero causes the segment to start playing as soon as possible.

ppSegmentState

Address of a variable that receives an IDirectMusicSegmentState interface pointer for this instance of the playing segment. Use QueryInterface to obtain IDirectMusicSegmentState8. The reference count of the interface is incremented. This parameter can be NULL if no segment state pointer is wanted.

pFrom

IUnknown interface pointer of a segment state or audiopath to stop when the new segment begins playing. If it is an audiopath, all segment states playing on that audiopath are stopped. This value can be NULL. See Remarks.

pAudioPath

IUnknown interface pointer of an object that represents the audiopath on which to play, or NULL to play on the default path.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method can return one of the error values shown in the following table.

Return code
DMUS_E_AUDIOPATH_INACTIVE
DMUS_E_AUDIOPATH_NOPORT
DMUS_E_NO_MASTER_CLOCK
DMUS_E_SEGMENT_INIT_FAILED
DMUS_E_TIME_PAST
E_OUTOFMEMORY
E_POINTER
 

如果希望停止播放,只需要調用IDirectMusicPerformance8::Stop函數就可以了。

The Stop method stops playback of a segment or segment state.

This method has been superseded by IDirectMusicPerformance8::StopEx, which can stop playback of a segment, segment state, or audiopath.

Syntax

HRESULT Stop(
IDirectMusicSegment*
pSegment,
IDirectMusicSegmentState* pSegmentState,
MUSIC_TIME mtTime,
DWORD dwFlags
);

Parameters

pSegment

Segment to stop playing. All segment states based on this segment are stopped at mtTime. See Remarks.

pSegmentState

Segment state to stop playing. See Remarks.

mtTime

Time at which to stop the segment, segment state, or both. If the time is in the past or if 0 is passed in this parameter, the specified segment and segment states stop playing immediately.

dwFlags

Flag that indicates when the stop should occur. Boundaries are in relation to the current primary segment. For a list of values, see IDirectMusicPerformance8::StopEx.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method can return E_POINTER.

Remarks

If pSegment and pSegmentState are both NULL, all music stops, and all currently cued segments are released. If either pSegment or pSegmentState is not NULL, only the requested segment states are removed from the performance. If both are non-NULL and DMUS_SEGF_DEFAULT is used, the default resolution from the pSegment is used.

If you set all parameters to NULL or 0, everything stops immediately, and controller reset messages and note-off messages are sent to all mapped performance channels.


卸載音樂數據

使用完音樂之后,第一件要做的事就是卸載音色庫數據,可以通過IDirectMusicSegment8::Unload來完成。

The Unload method unloads instrument data from a performance or audiopath.

Syntax

HRESULT Unload(
IUnknown *
pAudioPath
);

Parameters

pAudioPath

Pointer to the IUnknown interface of the performance or audiopath from which to unload the instrument data.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method can return one of the error values shown in the following table.

Return code
DMUS_E_TRACK_NOT_FOUND
E_POINTER
 

Remarks

The method succeeds even if no data was previously downloaded.


還要釋放加載器中的高速緩存數據,通過IDirectMusicLoader8::ReleaseObjectByUnknown來實現。

The ReleaseObjectByUnknown method releases the loader's reference to an object. This method is similar to IDirectMusicLoader8::ReleaseObject and is suitable for releasing objects for which the IDirectMusicObject8 interface is not readily available.

Syntax

HRESULT ReleaseObject(
IUnknown *
pObject
);

Parameters

pObject

Address of the IUnknown interface pointer of the object to release.

Return Values

If the method succeeds, the return value is S_OK, or S_FALSE if the object has already been released or cannot be found in the cache.

If it fails, the method can return E_POINTER.


如果開始的時候加載了音色庫,現在是時候從加載器對象中將它卸載掉了,就像剛才從加載器中卸載音樂片段對象一樣。另外,清空緩存很重要,有一個函數可以強制清空整個緩存區,但是并不需要在卸載加載器前調用它,因為在卸載過程中這個操作是自動完成的。

The ClearCache method removes all saved references to a specified object type.

Syntax

HRESULT ClearCache(
REFGUID
rguidClass
);

Parameters

rguidClass

Reference to (C++) or address of (C) the identifier of the class of objects to clear, or GUID_DirectMusicAllTypes to clear all types. For a list of standard loadable classes, see IDirectMusicLoader8.

Return Values

The method returns S_OK.

Remarks

This method clears all objects that are currently being held, but does not turn off caching. Use the IDirectMusicLoader8::EnableCache method to turn off automatic caching.

To clear a single object from the cache, call the IDirectMusicLoader8::ReleaseObject method.
 

修改音樂

在使用DirectMusic緩沖的時候,我們可以在播放音樂的時候對音樂做很多處理,比如通過DirectSound聲音緩沖對象改變音量、節拍、加入特殊效果等。

 

音量設置

我們可以改變兩個音量設置。第一個是演奏器的音量(整個音樂系統的音量),第二個是每個音樂片段對象的回放音量。如下圖所示,當每個音樂片段被加載到演奏器中的時候,音樂片段的音量會被修改,演奏器的音量又被全局音量所影響。

演奏器音量(主音量)是一個全局參數,調用IDirectMusicPerformance8::SetGlobalParam設置。

The SetGlobalParam method sets global values for the performance.

Syntax

HRESULT SetGlobalParam(
REFGUID
rguidType,
void* pParam,
DWORD dwSize
);

Parameters

rguidType

Reference to (C++) or address of (C) the identifier of the type of data.

pParam

Address of data to be copied and stored by the performance.

dwSize

Size of the data. This is constant for each rguidType.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method can return one of the error values shown in the following table.

Return code
E_FAIL
E_POINTER
E_OUTOFMEMORY
 

Remarks

The dwSize parameter is needed because the performance does not know about all types of data. New types can be created as needed.

For the parameters defined by DirectMusic and their associated data types, see Setting and Retrieving Global Parameters.

 

參數rguidType指定允許的GUID類型如下:

By using the IDirectMusicPerformance8::SetGlobalParam and IDirectMusicPerformance8::GetGlobalParam methods, you can set and retrieve parameters that affect the entire performance rather than a single track.

The parameter to be set or retrieved is identified by a GUID in the rguidType parameter of the method. Each parameter is associated with a particular data type, whose size is given in the dwSize parameter. The predefined GUIDs and their data types are shown in the following table.

Parameter type GUID
(rguidType)
Data
(*pParam)
Description
GUID_PerfAutoDownload BOOL This parameter controls whether instruments are automatically downloaded when a segment is played. By default, it is off. See Downloading and Unloading Bands.
GUID_PerfMasterGrooveLevel char The master groove level is a value that is always added to the groove level established by the command track. The resulting value is adjusted, if necessary, to fall within the range from 1 through 100.
GUID_PerfMasterTempo float The master tempo is a scaling factor applied to the tempo by the final output tool. By default, it is 1. A value of 0.5 would halve the tempo, and a value of 2.0 would double it. This value can be set in the range from DMUS_MASTERTEMPO_MIN through DMUS_MASTERTEMPO_MAX.
GUID_PerfMasterVolume long The master volume is an amplification or attenuation factor, in hundredths of a decibel, applied to the default volume of the entire performance and any other performances using the same synthesizer. The range of permitted values is determined by the port. For the default software synthesizer, the allowed range is +20db to -200dB, but the useful range is +10db to -100db. Hardware MIDI ports do not support changing master volume. Setting this parameter is equivalent to calling IKsControl::KsProperty for the GUID_DMUS_PROP_Volume property set on every port in the performance.
 

Applications can also use custom types of global parameters. To create a new type, establish a GUID and a data type for it.

Note   All parameters have to be set before they can be retrieved. When a parameter is set, the performance allocates memory for the data in a linked list of items that are identified by GUID. If SetGlobalParam has never been called on the parameter, it does not appear in this linked list, and GetGlobalParam fails.

為了簡化音量的操作,我們不使用分貝來設置音量,而是使用百分數。百分數的范圍從0 - 100,0表示沒有聲音,100表示最大音量。最大音量的時候對音樂有少許的放大效果,有些時候這個放大效果會使得音樂發生扭曲,所以設置音量的時候需要格外小心。

下面這個小函數的作用就是用百分數來設置主音量:

//--------------------------------------------------------------------------------
// Set volume for performance.
//--------------------------------------------------------------------------------
BOOL set_master_volume(long level)
{
    
// get volume range and calculate volume
    long range  = labs(DMUS_VOLUME_MAX - DMUS_VOLUME_MIN);
    
long volume = DMUS_VOLUME_MIN + range / 100 * level;

    
// set volume for performance
    if(FAILED(g_dm_performance->SetGlobalParam(GUID_PerfMasterVolume, &volume, sizeof(long))))
        
return FALSE;

    
return TRUE;
}
 

如果要對音樂片段設置音量,需要獲取對音頻通道接口的控制。因為在播放音樂的時候已經創建了音頻通道,現在只需要用函數將這個對象獲取即可,可以通過調用IDirectMusicPerformance8::GetDefaultAudioPath來實現。

The GetDefaultAudioPath method retrieves the default audiopath set by IDirectMusicPerformance8::InitAudio or IDirectMusicPerformance8::SetDefaultAudioPath.

Syntax

HRESULT GetDefaultAudioPath(
IDirectMusicAudioPath**
ppAudioPath
);

Parameters

ppAudioPath

Address of a variable that receives the IDirectMusicAudioPath8 interface pointer of the default audiopath.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method can return one of the error values shown in the following table.

Return code
DMUS_E_AUDIOPATHS_NOT_VALID
DMUS_E_NOT_INIT
E_POINTER

 

一旦獲得了指向IDirectMusicAudioPath8對象的指針,就能使用IDirectMusicAudioPath8::SetVolume函數修改變量了。

The SetVolume method sets the audio volume on the audiopath. The volume can be faded in or out.

Syntax

HRESULT SetVolume(
long
lVolume,
DWORD dwDuration
);

Parameters

lVolume

Value that specifies the attenuation, in hundredths of a decibel. This value must be in the range from -9600 to 0. Zero is full volume.

dwDuration

Value that specifies the time, in milliseconds, over which the volume change takes place. A value of 0 ensures maximum efficiency.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method can return one of the error values shown in the following table.

Return code
DMUS_E_NOT_INIT
E_INVALIDARG
 

Remarks

This method works by sending a volume curve message. Any volume events occurring later, such as a band change, override the volume set by this method. IDirectMusicAudioPath8::SetVolume is useful mainly for adjusting currently playing sounds; for example, to fade out before stopping a segment. If you want to make a global change that affects all playback, use one of the following techniques:

  • Obtain the buffer object from the audiopath and use IDirectSoundBuffer8::SetVolume.
  • Obtain the port object from the audiopath and use IKsControl::KsProperty to change the GUID_DMUS_PROP_Volume property set.
  • Set the master volume for the performance. See Setting and Retrieving Global Parameters.

下面這個函數使用0-100之間的數值來設置音樂片段的音量,100表示音量最大,0表示靜音。

//--------------------------------------------------------------------------------
// Set volume for DirectMusic segment.
//--------------------------------------------------------------------------------
BOOL set_segment_volume(long level)
{    
    IDirectMusicAudioPath8* audio_path;

    
// get pointer to audio path
    if(FAILED(g_dm_performance->GetDefaultAudioPath(&audio_path)))
        
return FALSE;

    
// calculate audio volume and set volume for audio path
    long volume = -96 * (100 - level);

    
if(FAILED(audio_path->SetVolume(volume, 0)))
    {
        audio_path->Release();
        
return FALSE;
    }

    
return TRUE;
}
 

改變節拍

想象一下擁有改變音樂節拍的魔法。比如,當玩家靠近一個怪物,正要引發一場激烈戰斗的時候,節奏突然變快了,游戲者立刻就能知道他已經進入了麻煩之中。這一切很不錯,很讓人激動,而這一切在DirectMusic實現起來并不困難。

DirectMusic中,節奏速度的度量單位通常是每分鐘多少個拍子(beats per minute BPM)。一般來說這個數值通常會是120,我們有很多方法可以改變節拍速度,最簡單的方法就是使用一個縮放因子調節演奏器的主節拍速度。比如設置縮放因子為0.5,使得拍子的速度變為正常拍子的一半,設置縮放因子為2使得拍子速度變為正常拍子的兩倍。

下面這個函數修改演奏器的節拍,取值從0 - 100

//--------------------------------------------------------------------------------
// Set tempo for DirectMusic performance.
//--------------------------------------------------------------------------------
BOOL set_tempo(long level)
{
    
float tempo = (float) level / 100.0f;
   
    
if(FAILED(g_dm_performance->SetGlobalParam(GUID_PerfMasterTempo, &tempo, sizeof(float))))
        
return FALSE;

    
return TRUE;
}

需要注意,改變節拍速度不是立即生效的,需要過幾秒鐘。另外需要記住的是set_tempo函數影響的是全局節拍速度,也就是說所有音樂的節拍速度都被修改了,所以當播放完歌曲后,需要將拍子設置回原來的值。

 

獲取聲道控制

在這么多音樂效果的特性里面,最后獲取的是DirectSound緩存對象,因為DirectSound緩存是音色庫合成音樂的關鍵所在,所以能對它做很多事情。想要獲取緩存,首先可以獲取音頻通道對象,然后用它來獲取音頻緩沖區對象。

在下圖中,可以看到音樂數據從演奏器中通過音頻通道合成音樂的一個默認流程,我們可以在這個流程的任何步驟中截取并修改。

獲取音頻通道是函數IDirectMusicAudioPath8::GetObjectInPath的工作。

The GetObjectInPath method retrieves an interface for an object in the audiopath.

Syntax

RESULT GetObjectInPath(
DWORD
dwPChannel,
DWORD dwStage,
DWORD dwBuffer,
REFGUID guidObject,
DWORD dwIndex,
REFGUID iidInterface,
void ** ppObject
);

Parameters

dwPChannel

Performance channel to search, or DMUS_PCHANNEL_ALL to search all channels. The first channel is numbered 0. (See Remarks.)

dwStage

Stage in the audiopath. Can be one of the values in the following table.

Value Description
DMUS_PATH_AUDIOPATH_GRAPH Get the audiopath toolgraph. One is created if none exists.
DMUS_PATH_AUDIOPATH_TOOL Get a tool from the audiopath toolgraph.
DMUS_PATH_BUFFER Get a DirectSound buffer.
DMUS_PATH_BUFFER_DMO Get a DMO in a buffer.
DMUS_PATH_MIXIN_BUFFER Get a global mix-in buffer.
DMUS_PATH_MIXIN_BUFFER_DMO Get a DMO in a global mix-in buffer.
DMUS_PATH_PERFORMANCE Get the performance.
DMUS_PATH_PERFORMANCE_GRAPH Get the performance toolgraph. One is created if none exists.
DMUS_PATH_PERFORMANCE_TOOL Get a tool from the performance toolgraph.
DMUS_PATH_PORT Get the synthesizer.
DMUS_PATH_PRIMARY_BUFFER Get the primary buffer.
 

dwBuffer

Index of the buffer (if dwStage is DMUS_PATH_BUFFER or DMUS_PATH_MIXIN_BUFFER), or index of the buffer in which the DMO resides (if dwStage is DMUS_PATH_BUFFER_DMO or DMUS_PATH_MIXIN_BUFFER_DMO).

guidObject

Class identifier of the object, or GUID_All_Objects to search for an object of any class. This parameter is ignored if only a single class of object can exist at the stage specified by dwStage, and can be set to GUID_NULL.

dwIndex

Index of the object within a list of matching objects. Set to 0 to find the first matching object. If dwStage is DMUS_PATH_BUFFER or DMUS_PATH_MIXIN_BUFFER, this parameter is ignored, and the buffer index is specified by dwBuffer.

iidInterface

Identifier of the desired interface, such as IID_IDirectMusicTool.

ppObject

Address of a variable that receives a pointer to the requested interface.

Return Values

If the method succeeds, the return value is S_OK.

If it fails, the method can return one of the error values shown in the following table.

Return code
DMUS_E_NOT_FOUND
E_INVALIDARG
E_OUTOFMEMORY
E_NOINTERFACE
E_POINTER

Remarks

The value in dwPChannel must be 0 for any stage that is not channel-specific. Objects in the following stages are channel-specific and can be retrieved by setting a channel number or DMUS_PCHANNEL_ALL in dwPChannel:

DMUS_PATH_AUDIOPATH_TOOL
DMUS_PATH_BUFFER
DMUS_PATH_BUFFER_DMO
DMUS_PATH_PERFORMANCE_TOOL
DMUS_PATH_PORT

The precedence of the parameters in filtering out unwanted objects is as follows:

  1. dwStage.
  2. guidObject. If this value is not GUID_All_Objects, only objects whose class identifier equals guidObject are searched. However, this parameter is ignored for stages where only a single class of object can exist, such as DMUS_PATH_AUDIOPATH_GRAPH.
  3. dwPChannel. If the stage is channel-specific and this value is not DMUS_PCHANNEL_ALL, only objects on the channel are searched.
  4. dwBuffer. This is used only if dwStage is DMUS_PATH_BUFFER, DMUS_PATH_MIXIN_BUFFER, DMUS_PATH_BUFFER_DMO, or DMUS_PATH_MIXIN_BUFFER_DMO.
  5. dwIndex.

If a matching object is found but the interface specified by iidInterface cannot be obtained, the method fails.

The following example function shows how to enumerate the buffers in an audiopath:

void DumpAudioPathBuffers(IDirectMusicAudioPath *pDirectMusicAudioPath)
{
DWORD dwBuffer = 0;
IDirectSoundBuffer *pDirectSoundBuffer;

while (S_OK == pDirectMusicAudioPath->GetObjectInPath(
DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, dwBuffer,
GUID_NULL, 0, IID_IDirectSoundBuffer,
(void**) &pDirectSoundBuffer))
{
// Do something with pDirectSoundBuffer.
// . . .
dwBuffer++;
pDirectSoundBuffer->Release();
}
}

下面這個函數從演奏器獲取默認的音頻通道對象,并返回一個可以演奏的IDirectSoundBuffer8對象。

//--------------------------------------------------------------------------------
// Get DirectSound buffer from audio path.
//--------------------------------------------------------------------------------
IDirectSoundBuffer8* get_sound_buffer()
{
    IDirectMusicAudioPath8* audio_path;
    IDirectSoundBuffer*     ds_buffer;
    IDirectSoundBuffer8*    ds_buffer8;

    
// get autio path
    if(FAILED(g_dm_performance->GetDefaultAudioPath(&audio_path)))
        
return NULL;

    
// create DirectSound buffer
    if(FAILED(audio_path->GetObjectInPath(DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, 0, GUID_NULL, 0, 
                                          IID_IDirectSoundBuffer, (LPVOID*) &ds_buffer)))
    {
        audio_path->Release();
        
return FALSE;
    }

    audio_path->Release();

    
// query interface to DirectSound buffer8
    if(FAILED(ds_buffer->QueryInterface(IID_IDirectSoundBuffer8, (void**) &ds_buffer8)))
    {
        ds_buffer->Release();
        
return FALSE;
    }

    ds_buffer->Release();

    
return ds_buffer8;
}


以下給出一個完整的示例,來演示如何加載和播放MIDI音樂。

點擊下載源碼和工程

完整源碼示例:
 
/***************************************************************************************
PURPOSE:
    Midi Playing Demo
 ***************************************************************************************/


#include <windows.h>
#include <stdio.h>
#include <dsound.h>
#include <dmusici.h>
#include "resource.h"

#pragma comment(lib, "dxguid.lib")
#pragma comment(lib, "dsound.lib")

#pragma warning(disable : 4996)

#define Safe_Release(p) if((p)) (p)->Release();

// window handles, class.
HWND g_hwnd;
char g_class_name[] = "MidiPlayClass";

IDirectSound8*              g_ds;               
// directsound component
IDirectMusicPerformance8*   g_dm_performance;   // directmusic performance
IDirectMusicLoader8*        g_dm_loader;        // directmusic loader
IDirectMusicSegment8*       g_dm_segment;       // directmusic segment

//--------------------------------------------------------------------------------
// Window procedure.
//--------------------------------------------------------------------------------
long WINAPI Window_Proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    
switch(msg)
    {
    
case WM_DESTROY:
        PostQuitMessage(0);
        
return 0;
    }

    
return (long) DefWindowProc(hwnd, msg, wParam, lParam);
}

//--------------------------------------------------------------------------------
// Load DirectMusic collection object.
//--------------------------------------------------------------------------------
IDirectMusicCollection8* Load_DLS_Collection(char* filename)
{
    DMUS_OBJECTDESC dm_obj_desc;
    IDirectMusicCollection8* dm_collection;

    
// get the object

    ZeroMemory(&dm_obj_desc, 
sizeof(DMUS_OBJECTDESC));

    dm_obj_desc.dwSize      = 
sizeof(DMUS_OBJECTDESC);
    dm_obj_desc.guidClass   = CLSID_DirectMusicCollection;
    dm_obj_desc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME | DMUS_OBJ_FULLPATH;

    
// Converts a sequence of multibyte characters to a corresponding sequence of wide characters
    mbstowcs(dm_obj_desc.wszFileName, filename, MAX_PATH);

    
// retrieves an object from a file or resource and returns the speficied interface
    if(FAILED(g_dm_loader->GetObject(&dm_obj_desc, IID_IDirectMusicCollection8, (LPVOID*)&dm_collection)))
        
return NULL;

    
return dm_collection;
}

//--------------------------------------------------------------------------------
// Play midi file which specified with filename.
//--------------------------------------------------------------------------------
BOOL Play_Midi(char* filename)
{
    DMUS_OBJECTDESC dm_obj_desc;

    
// get the object

    ZeroMemory(&dm_obj_desc, 
sizeof(DMUS_OBJECTDESC));

    dm_obj_desc.dwSize      = 
sizeof(DMUS_OBJECTDESC);
    dm_obj_desc.guidClass   = CLSID_DirectMusicSegment;
    dm_obj_desc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME | DMUS_OBJ_FULLPATH;

    
// Converts a sequence of multibyte characters to a corresponding sequence of wide characters
    mbstowcs(dm_obj_desc.wszFileName, filename, MAX_PATH);

    
// retrieves an object from a file or resource and returns the speficied interface
    if(FAILED(g_dm_loader->GetObject(&dm_obj_desc, IID_IDirectMusicSegment8, (LPVOID*)&g_dm_segment)))
        
return FALSE;

    
// setup midi playing
    if(strstr(filename, ".mid"))
    {
        
// set data on a track inside the segment
        if(FAILED(g_dm_segment->SetParam(GUID_StandardMIDIFile, 0xFFFFFFFF, 0, 0, NULL)))
            
return FALSE;
    }

    
// downloads band data to a performance
    if(FAILED(g_dm_segment->Download(g_dm_performance)))
        
return FALSE;

    
// set to loop forever
    g_dm_segment->SetRepeats(DMUS_SEG_REPEAT_INFINITE);

    
// play on default audio path
    g_dm_performance->PlaySegmentEx(g_dm_segment, NULL, NULL, 0, 0, NULL, NULL, NULL);

    
return TRUE;
}

//--------------------------------------------------------------------------------
// Main function, routine entry.
//--------------------------------------------------------------------------------
int WINAPI WinMain(HINSTANCE inst, HINSTANCE, LPSTR cmd_line, int cmd_show)
{
    WNDCLASS            win_class;
    MSG                 msg;    

    
// create window class and register it
    win_class.style         = CS_HREDRAW | CS_VREDRAW;
    win_class.lpfnWndProc   = Window_Proc;
    win_class.cbClsExtra    = 0;
    win_class.cbWndExtra    = DLGWINDOWEXTRA;
    win_class.hInstance     = inst;
    win_class.hIcon         = LoadIcon(inst, IDI_APPLICATION);
    win_class.hCursor       = LoadCursor(NULL, IDC_ARROW);
    win_class.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
    win_class.lpszMenuName  = NULL;
    win_class.lpszClassName = g_class_name;    

    
if(! RegisterClass(&win_class))
        
return FALSE;

    
// create the main window
    g_hwnd = CreateDialog(inst, MAKEINTRESOURCE(IDD_MIDIPLAY), 0, NULL);

    ShowWindow(g_hwnd, cmd_show);
    UpdateWindow(g_hwnd);

    
// initialize and configure directsound

    // creates and initializes an object that supports the IDirectSound8 interface
    if(FAILED(DirectSoundCreate8(NULL, &g_ds, NULL)))
    {
        MessageBox(NULL, "Unable to create DirectSound object", "Error", MB_OK);
        
return 0;
    }

    
// set the cooperative level of the application for this sound device
    g_ds->SetCooperativeLevel(g_hwnd, DSSCL_NORMAL);

    
// initialize COM
    //
    // initialize the COM library on the current thread and identifies the concurrency model as single-thread
    // apartment (STA).
    CoInitialize(0);

    
// create the DirectMusic performance object
    //
    // creates a single uninitialized object of the class associated with a specified CLSID.
    CoCreateInstance(CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC, IID_IDirectMusicPerformance8, 
                     (
void**)&g_dm_performance);

    
// create the DirectMusic loader object
    CoCreateInstance(CLSID_DirectMusicLoader, NULL, CLSCTX_INPROC, IID_IDirectMusicLoader8, (void**)&g_dm_loader);

    
// initialize the performance with the standard audio path.
    // this initialize both directmusic and directsound and sets up the synthesizer.
    g_dm_performance->InitAudio(NULL, NULL, g_hwnd, DMUS_APATH_SHARED_STEREOPLUSREVERB, 128, DMUS_AUDIOF_ALL, NULL);
    
    
// tell directmusic where the default search path is

    
char path[MAX_PATH];
    WCHAR search_path[MAX_PATH];

    GetCurrentDirectory(MAX_PATH, path);

    
// maps a character string to a wide-character (Unicode) string
    MultiByteToWideChar(CP_ACP, 0, path, -1, search_path, MAX_PATH);

    
// set a search path for finding object files
    g_dm_loader->SetSearchDirectory(GUID_DirectMusicAllTypes, search_path, FALSE);

    
// play midi
    Play_Midi("escape.mid");
    
    
// start message pump, waiting for signal to quit.
    ZeroMemory(&msg, sizeof(MSG));

    
while(msg.message != WM_QUIT)
    {
        
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }        
    }

    
// release directsound objects

    
if(g_dm_segment)
        g_dm_segment->Unload(g_ds);

    
if(g_dm_loader)
        g_dm_loader->ReleaseObjectByUnknown(g_dm_segment);

    
if(g_dm_segment)
        g_dm_segment->Release();

    
if(g_ds)
        g_ds->Release();

    UnregisterClass(g_class_name, inst);

    
// release COM system
    //
    // Closes the COM library on the current thread, unloads all DLLs loaded by the thread, frees any other
    // resources that the thread maintains, and forces all RPC connections on the thread to close.
    CoUninitialize();
    
    
return (int) msg.wParam;
}
 

運行截圖:

 

閱讀下篇:用DirectX Audio和DirectShow播放聲音和音樂(7)
 

posted on 2007-07-31 01:42 lovedday 閱讀(3813) 評論(0)  編輯 收藏 引用

公告

導航

統計

常用鏈接

隨筆分類(178)

3D游戲編程相關鏈接

搜索

最新評論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美一区三区三区高中清蜜桃| 亚洲美女黄色| 国产精品久久久久久一区二区三区| 国内精品免费在线观看| 亚洲自拍偷拍视频| 日韩视频免费观看| 欧美美女视频| 亚洲精品在线电影| 亚洲国产欧美一区| 久久婷婷成人综合色| 国内揄拍国内精品少妇国语| 校园激情久久| 亚洲免费视频成人| 国产精品视频一| 欧美资源在线| 久久精品青青大伊人av| 激情成人综合网| 欧美aⅴ99久久黑人专区| 午夜视黄欧洲亚洲| 欧美电影免费| 夜夜嗨av一区二区三区| 亚洲日韩视频| 国产精品久久久久久久久久妞妞| 亚洲欧美日韩精品在线| 亚洲二区免费| 羞羞视频在线观看欧美| 午夜国产精品视频| 国语精品中文字幕| 欧美成人福利视频| 欧美日本在线一区| 午夜精品久久久久久久久久久| 亚洲一区二区三区四区在线观看 | 国产欧美日韩精品一区| 久久九九国产精品怡红院| 久久精品夜色噜噜亚洲aⅴ| 亚洲级视频在线观看免费1级| 亚洲国产欧美不卡在线观看 | 亚洲视频在线观看网站| 亚洲精品一区在线观看香蕉| 国产精品v一区二区三区| 久久er精品视频| 蜜桃av一区二区| 亚洲网站在线观看| 午夜免费日韩视频| 亚洲精品乱码| 亚洲日韩成人| 国产主播在线一区| 亚洲精品国产精品乱码不99| 国产精品麻豆成人av电影艾秋| 久久久久久久一区二区| 欧美寡妇偷汉性猛交| 亚洲欧美成人精品| 免费黄网站欧美| 欧美在线播放视频| 欧美精品亚洲| 久久影视三级福利片| 欧美日韩一区不卡| 欧美成人乱码一区二区三区| 国产精品久久久久久久久久三级| 欧美激情精品久久久久久免费印度 | 香蕉久久精品日日躁夜夜躁| 久久手机精品视频| 亚洲女性裸体视频| 美女网站久久| 亚洲欧美视频在线| 欧美福利电影网| 久久精品视频一| 欧美午夜免费影院| 欧美电影在线观看| 国外精品视频| 亚洲欧美成人| 9久re热视频在线精品| 久久亚洲电影| 久久黄色影院| 国产精品揄拍500视频| av不卡在线| 夜夜爽夜夜爽精品视频| 噜噜噜躁狠狠躁狠狠精品视频| 欧美国产日韩二区| 欧美精品一级| 99re热这里只有精品视频| 欧美在线免费视频| 亚洲尤物在线| 国产精品久久亚洲7777| 亚洲精品美女久久7777777| 亚洲福利一区| 鲁大师影院一区二区三区| 麻豆91精品| 伊人夜夜躁av伊人久久| 久久国产日本精品| 欧美在线视频一区| 国产欧美日韩一区二区三区在线观看 | 欧美一二三区在线观看| 欧美性大战久久久久| 夜夜狂射影院欧美极品| 亚洲一区二区免费视频| 欧美午夜精品伦理| 亚洲一区二区三区四区五区午夜 | 伊人春色精品| 狂野欧美激情性xxxx欧美| 免费观看成人| 欧美激情偷拍| 久久人人爽人人爽爽久久| 美女诱惑一区| 亚洲国产精品一区在线观看不卡 | 麻豆9191精品国产| 欧美成人精品一区| 亚洲毛片网站| 国产精品久久久久一区二区三区 | 亚洲香蕉成视频在线观看| 午夜精品久久一牛影视| 国产一级久久| 乱中年女人伦av一区二区| 亚洲日韩成人| 亚洲一区在线免费观看| 国产婷婷成人久久av免费高清 | 亚洲永久精品大片| 久久免费精品日本久久中文字幕| 18成人免费观看视频| 欧美区国产区| 性欧美暴力猛交69hd| 免费观看亚洲视频大全| 99日韩精品| 国产日韩精品一区| 亚洲精品国产精品国自产在线 | 蜜臀av性久久久久蜜臀aⅴ四虎| 激情久久久久久| 欧美激情精品久久久久久免费印度| 亚洲精品孕妇| 久久久午夜电影| 亚洲美女视频网| 国产日韩欧美a| 欧美sm视频| 亚洲欧美在线另类| 91久久精品国产91久久性色tv| 亚洲一区免费视频| 在线观看欧美日韩| 国产精品嫩草99av在线| 久久最新视频| 亚洲欧美影院| 日韩系列欧美系列| 牛牛影视久久网| 久久gogo国模啪啪人体图| 亚洲久久成人| 在线观看成人一级片| 国产精品视频专区| 欧美精品乱人伦久久久久久| 性伦欧美刺激片在线观看| 日韩午夜精品| 亚洲黄色成人网| 欧美专区第一页| 亚洲免费中文字幕| 99国产精品99久久久久久| 怡红院精品视频在线观看极品| 国产精品网站一区| 欧美日韩国产综合一区二区| 久久久久久久一区二区三区| 亚洲在线视频观看| 一本大道久久a久久精品综合| 欧美日韩免费区域视频在线观看| 欧美一区二区啪啪| 宅男精品视频| 亚洲美女黄色| 亚洲毛片在线看| 亚洲另类视频| 亚洲六月丁香色婷婷综合久久| 欲色影视综合吧| 国语自产精品视频在线看一大j8| 国产精品爱啪在线线免费观看| 欧美精品久久99久久在免费线| 久久综合影视| 免费观看日韩| 欧美高清一区| 欧美精品久久久久久久久老牛影院 | 在线亚洲电影| 在线视频欧美日韩精品| 亚洲免费观看| 99热精品在线| 日韩亚洲欧美成人| 日韩午夜电影在线观看| 99re66热这里只有精品4| 亚洲精品网站在线播放gif| 亚洲精品精选| 一区二区三区毛片| 亚洲免费在线视频一区 二区| 亚洲一区二区三区高清不卡| 在线一区日本视频| 亚洲欧美日韩综合国产aⅴ| 一区二区三区四区五区精品| 一本一本久久| aa级大片欧美三级| 一区二区视频欧美| 欧美国产91| 欧美三级日本三级少妇99| 欧美日韩美女| 欧美国产日韩一区| 欧美亚州一区二区三区 | 国产欧美日本一区视频| 国产伦精品一区二区三区照片91| 国产日韩亚洲欧美精品|