delphi - 传送 Wav 音频数据的 DirectShow 过滤器的媒体类型设置是否正确?

标签 delphi audio filter directshow wav

我使用 Delphi 6 Pro 和 DSPACK DirectShow 组件库来创建一个 DirectShow 过滤器,该过滤器从自定义音频源提供 Wav 格式的数据。需要明确的是,我将原始 PCM 音频样本作为字节数据提供。不涉及 Wave 文件,但我的 Filter Graph 下游的其他 Filter 期望输出引脚以字节形式提供标准 WAV 格式样本数据。

注意:当我从自定义音频源获取数据时,我将其格式化为所需的 channel 数、采样率和每个样本的位数,并将其存储在我创建的 TWaveFile 对象中。该对象具有正确格式化的 TWaveFormatEx 数据成员,该数据成员已正确设置以反射(reflect)我存储的数据的基础格式。

我不知道如何在 GetMediaType() 调用期间正确设置 MediaType 参数:

    function TBCPushPinPlayAudio.GetMediaType(MediaType: PAMMediaType): HResult;

    .......

    with FWaveFile.WaveFormatEx do
    begin
        MediaType.majortype                 := (1)
        MediaType.subtype                   := (2)
        MediaType.formattype                := (3)
        MediaType.bTemporalCompression      := False;
        MediaType.bFixedSizeSamples         := True;
        MediaType.pbFormat                  := (4)
        // Number of bytes per sample is the number of channels in the
        //  Wave audio data times the number of bytes per sample
        //  (wBitsPerSample div 8);
        MediaType.lSampleSize := nChannels * (wBitsPerSample div 8);
    end;

(1)、(2) 和 (3) 的正确值是多少?我了解 MEDIATYPE_Audio、MEDIATYPE_Stream 和 MEDIASUBTYPE_WAVE GUID 常量,但我不确定它们的去向。

此外,我假设我需要将 WaveFormatEx 结构/记录从 FWaveFile 对象复制到 pbFormat 指针 (4)。我对此有两个问题:

1) 我认为应该使用 CoTaskMemAlloc() 创建一个新的 TWaveFormatEx 对象,并将我的 FWaveFile 对象的 TWaveFormatEx 对象复制到它上面,然后再将 pbFormat 指针分配给它,对吗?

2) TWaveFormatEx 是要传递的正确结构吗?以下是 TWaveFormatEx 的定义方式:

tWAVEFORMATEX = packed record
    wFormatTag: Word;       { format type }
    nChannels: Word;        { number of channels (i.e. mono, stereo, etc.) }
    nSamplesPerSec: DWORD;  { sample rate }
    nAvgBytesPerSec: DWORD; { for buffer estimation }
    nBlockAlign: Word;      { block size of data }
    wBitsPerSample: Word;   { number of bits per sample of mono data }
    cbSize: Word;           { the count in bytes of the size of }

结束;

更新:2011 年 12 月 11 日

我想强调 @Roman R 附加在他接受的回复中的评论之一,他告诉我使用 MEDIASUBTYPE_PCM 作为子类型,因为它非常重要。我花费了大量时间来追查 DirectShow“无中间过滤器组合”错误,因为我忘记了为子类型使用该值并且正在(错误地)使用MEDIASUBTYPE_WAVE 相反。 MEDIASUBTYPE_WAVE 与许多其他过滤器(例如系统捕获过滤器)不兼容,这是失败的根本原因。这里更大的教训是,如果您正在调试过滤器间媒体格式协商错误,请确保所连接的引脚之间的格式完全相同。我在最初的调试过程中犯了一个错误,即只比较引脚之间相同的 WAV 格式参数(格式标签、 channel 数、每个样本的位数、采样率)。但是由于我对 MEDIASUBTYPE_WAVE 使用不当导致子类型的差异导致引脚连接失败。一旦我按照 Roman 的建议将子类型更改为 MEDIASUBTYPE_PCM,问题就消失了。

最佳答案

(1) 是MEDIATYPE_Audio

(2) 通常是从 FOURCC 代码到 GUID 的映射,请参阅 Media Types音频媒体类型部分。

(3) 是 FORMAT_WaveFormatEx

(4) 是指向 WAVEFORMATEX 结构的指针(通常由 COM 任务内存分配器 API 分配)。

1) - 是的,您应该分配内存,通过直接复制或初始化将有效数据放在那里,然后将此指针放入 pbFormat 并将结构大小放入 cbFormat

2) - 是的,它看起来不错,它首先是这样定义的:WAVEFORMATEX structure .

关于delphi - 传送 Wav 音频数据的 DirectShow 过滤器的媒体类型设置是否正确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7909947/

相关文章:

java - 如何使用这种方法制作声音循环?

swift - React Native - IOS推送通知 - 如何在应用程序处于后台时播放铃声?

javascript - 如何为音频文件数组的每个索引动态地将 src 值绑定(bind)到指令范围变量

javascript - 如何使用数组和 JQuery 创建可过滤菜单?

python - 如何实现我自己的搜索过滤器 - Django?

Delphi - 形成最大化事件

ios - 有没有一种方法可以使用 Delphi XE5/iOS7 在 iOS 键盘上切换 Shift 键

Haskell笛卡尔积,带过滤器的Monad

delphi - 小刻度 TeeChart delphi 对数刻度

mysql - Delphi 从 MySql 加载 Blob