由于兼职要做DSP,所以要直接对samples进行处理,考虑到这点,我选择了directsound .(对DSP感兴趣的朋友可以看我关于DSP的一系列文章,我会逐渐添加。)
在这里谈一点粗浅的感受。
Directsound 属于DIRCTX 也是直接对硬件进行操作,同时包括了3D音效,声音的输入,输出等内容,在这里,我简单的谈一下声音的读写。
DIRECTSOUND8 创建了输出声音的硬件对象(device object )一切对于声音的输出的操作都要基于这个对象,因此,第一步便是枚举声音设备的GUID,并通过回调函数(callback)进行处理。
同理DIRECTSOUNDCAPTURE8 负责的则是声音的输入设备对象的创建。它们俩的回调函数要基于一样的原型(prototype)定义如下:
BOOL CALLBACK DSEnumCallback(
LPGUID lpGuid,
LPCSTR lpcstrDescription,
LPCSTR lpcstrModule,
LPVOID lpContext
) lpGuid
Address of the GUID that identifies the device being enumerated, or NULL for the primary device. This value can be passed to the DirectSoundCreate8 or DirectSoundCaptureCreate8 function to create a device object for that driver. lpcstrDescription
Address of a null-terminated string that provides a textual description of the DirectSound device. lpcstrModule
Address of a null-terminated string that specifies the module name of the DirectSound driver corresponding to this device. lpContext
Address of application-defined data. This is the pointer passed to DirectSoundEnumerate or DirectSoundCaptureEnumerate as the lpContext parameter.
当然硬件的枚举不是必须的,往往可以传递NULL,表示使用基本设备(primary device),具体的细节可以查询directx sdk.
例如: DSDEVID_DefaultPlayback The default system audio device. You can also specify this device by passing a NULL pointer in the device GUID parameter. The default device is the one enumerated as “Primary DirectSound Driver”.
DSDEVID_DefaultVoicePlayback The default voice communications device. Typically this is a secondary device such as a USB headset with microphone.
要注意的是实际上directsound 最重要的部分是音频buffer,这个buffer是一个环形buffer,通过lock和unlock方法确保对其进行安全的操作,不断的进行写入/写出,从而实现音频的输入,或者输出。要注意的是directsound比较好的一点就在于可以通过几个二级buffer一起输出音频,从而完成混音。但同时在使用DIRECTSOUND8 时,一级buffer是不能直接进行操作的。
事实上根据DSP的原理,混音可以是时域上的sanple的直接相加。
更的细节我将逐渐给出。