65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 DirectShow 将 Wav 文件转换为 MP3 或其他格式

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.84/5 (46投票s)

2002年7月31日

CPOL

3分钟阅读

viewsIcon

720901

downloadIcon

22239

一个简单的类,用于将立体声 44 kHz、16 位 wav 文件转换为其他格式,包括 MP3。该类展示了如何使用 DirectShow API 进行音频转换。

Sample Image - DShowEncoder.gif

引言

本文介绍如何使用 DirectShow API 进行简单的音频转换,特别是 Wav 到 MP3 的转换。DirectShow API 中的音频编解码器分为三种类型:原生编解码器、ACM 编解码器和 DMO(DirectX 媒体对象)编解码器。

用于音频压缩的原生音频编解码器很少。对于 MP3 编码,我找到的唯一一个是Elecard 的 LAME DirectShow 包装器。大多数 MP3 编码器都采用 ACM(音频压缩管理器)格式,该格式随 Windows 多媒体 API 一起推出。CDSEncoder 类及其相关的类 CDSCodecCDSCodecFormat 枚举 ACM 编解码器及其各自的压缩参数,构建图并进行编码。

GraphBuilder 和其他过滤器

该图由五个过滤器组成

  • 文件源(异步)用于读取输入 wav 文件,
  • WAV 解析器用于 wav 解析,
  • ACM 编解码器用于音频压缩(在本例中:MP3 ACM,由 ACM 包装器过滤器包装),
  • WAV 目标,用于 wav 输出多路复用,
  • 文件写入器用于写入输出文件。

重要提示

WAV Dest 过滤器不包含在标准过滤器中,但需要从 DirectX SDK(SDK_root\Samples\Multimedia\DirectShow\Filters\WavDest)编译。为了方便起见,已编译的 WAV Dest 过滤器包含在演示 zip 文件中,但您必须通过RegSrv32 wavdest.ax注册它。

ACM 编解码器和 ACM 包装器过滤器

所有 ACM 编解码器都列在 DirectShow 的音频压缩器过滤器类别(CLSID_AudioCompressorCategory)中,并且不能直接实例化。我们必须使用设备枚举器来使用它们。

注意:根据您的配置,您的计算机上可能安装了针对同一格式的多个 ACM 编解码器。对于 MP3 编解码器,情况可能如此。您可以通过控制面板设置优先级或停用其中一些编解码器,如下面的图片所示。

Codec configuration

设备枚举器或如何浏览 ACM 编解码器

必须使用设备枚举器来检索 ACM 编解码器的实例。它通过IEnumMoniker接口返回编解码器列表,因此我们可以通过调用IMoniker::BindToObject()获得过滤器接口(IBaseFilter),并通过调用IMoniker::BindToStorage()获得过滤器名称。

使用 IAMStreamConfig 接口配置 ACM 编解码器

一旦实例化了所需的编解码器,我们就可以获得用于过滤器配置的IBaseFilter接口。由于每个IBaseFilter都有一个或多个 Pin,我们必须使用IEnumPins接口和IPin::QueryDirection()调用来搜索输出 Pin。
使用输出 Pin,我们可以查询IAMStreamConfig接口来配置以下属性

  • 声道数,
  • 每秒样本数,
  • 每秒平均字节数,
  • 每个样本的位数。

注意:对于某些编解码器(包括 MP3),必须在图形渲染后调用IAMStreamConfig::SetFormat()

CDSEncoder

CDSEncoder承担以下任务

  • 枚举音频编解码器(CLSID_AudioCompressorCategory),
  • 构建、渲染和运行图形。

class CDSEncoder : public CArray<CDSCodec*, CDSCodec*>
{
public:
  void BuildGraph(CString szSrcFileName, CString szDestFileName, 
    int nCodec, int nFormat);
  CDSEncoder();
  virtual ~CDSEncoder();

protected:
  void BuildCodecArray();
  HRESULT AddFilterByClsid(IGraphBuilder *pGraph, LPCWSTR wszName, 
    const GUID& clsid, IBaseFilter **ppF);
  BOOL SetFilterFormat(AM_MEDIA_TYPE* pStreamFormat, 
    IBaseFilter* pBaseFilter);

  IGraphBuilder *m_pGraphBuilder;
};

由于CDSEncoder继承自CArray,因此编解码器集合通过CArray方法公开,每个编解码器都作为CDSCodec对象返回。

CDSCodec

CDSCodec承担以下任务

  • 枚举编解码器支持的参数,
  • 公开编解码器名称。

class CDSCodec : public CArray<CDSCodecFormat*, CDSCodecFormat*>
{
public:
  CDSCodec();
  virtual ~CDSCodec();

  CString m_szCodecName;
  IMoniker  *m_pMoniker;
  void BuildCodecFormatArray();
};

由于CDSCodec继承自CArray,因此编解码器支持的参数集合通过CArray方法公开,每个参数都作为CDSCodecFormat对象返回。

CDSCodecFormat

CDSCodecFormat公开了一个编解码器参数的属性

  • 声道数,
  • 每秒样本数,
  • 每秒字节数,
  • 每个样本的位数。

class CDSCodecFormat  
{
public:
  WORD BitsPerSample();
  DWORD BytesPerSec();
  DWORD SamplesPerSecond();
  WORD NumberOfChannels();
  CDSCodecFormat();
  virtual ~CDSCodecFormat();

public:
  AM_MEDIA_TYPE* m_pMediaType;
};

已知问题

错误检查

本文的目标是演示如何使用 DirectShow 进行简单的音频转换。这些类不如它们应该的那样安全。如果您计划在生产环境中使用它,请记住这一点。

源 Wav 格式

没有采样转换,因此如果您使用 44 kHz Wav,则只能生成 44 kHz 输出文件。

Windows Media

Windows Media 格式只能与证书一起使用,该证书可从微软的Windows Media SDK获得。

使用 DirectShow 将 Wav 文件转换为 MP3 或其他格式 - CodeProject - 代码之家
© . All rights reserved.