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

LAME 封装器 (音频转换器)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.56/5 (13投票s)

2013 年 9 月 20 日

CPOL

7分钟阅读

viewsIcon

57394

downloadIcon

3421

LAME 库的 C++ 封装,可将 PCM (*.wav) 转换为 mp3,反之亦然,只需两行代码。

 

介绍  

20 世纪 90 年代初,随着互联网的普及,音频文件的存储和共享方式发生了新的转变。世界普遍使用 PCM 格式,但该格式需要大量的比特和带宽,而当时这些资源并不充足,无法有效地存储和流式传输这些文件(一个 4 秒的立体声 44.1khz PCM 文件大约需要 1MB 的空间)。

MP3 被发明出来,它是一种有损压缩 PCM 数据的方法(通过移除或降低某些声音细节的精度,这些细节被认为超出大多数人的听觉能力),在 128kbps 编码时,其大小约为 PCM 数据的 1/11。

MP3 格式因其显著减小的文件大小而迅速普及,能够将 PCM 转换为此文件格式的编解码器/编码器也随之发展起来。

LAME

Lame Aint an MP3 Encoder(LAME 不是一个 MP3 编码器)由 Mike Cheng 于 1998 年中期创建,改进工作至今仍在进行。它是编码质量非常好的编码器之一(实际上被绝大多数人认为是最好的)。源代码可在 http://lame.sourceforge.net 获取,或者从本文附件中获取已编译的静态库

包装器

编写此封装库是为了简化 LAME 的使用,因为 LAME 本身可能非常复杂(强大的功能也带来复杂性)。此封装库将:

  1. 在每次调用时将编码/解码操作简化为两行代码(如果您使用封装库的默认值)。
  2. 使参数设置变得非常简单,甚至包括 id3 标签的设置。

设置您的开发环境

如果您已经知道如何设置开发环境以编译 LAME,请跳至本节的第二部分。

我将使用 Visual Studio,如果您使用其他 IDE,请自行查找如何将静态库链接到您的项目。

  1. http://lame.sourceforge.net 下载并编译 LAME 库,从本文附件中抓取 LAME 存档并解压
  2. 在 Visual Studio 的菜单栏中点击“项目”按钮,从下拉菜单中选择“属性页”(<您的项目名称> 属性页),然后转到“配置属性”部分。转到“链接器”子部分,然后是“常规”项。从现在可用的选项列表中选择“附加库目录”,然后添加解压后的存档路径。
  3. 转到“输入”项并选择“附加依赖项”。添加 libmp3lame-static.liblibmpghip-static.lib(每行一个)。
  4. 现在返回到“配置属性”部分,然后是“C/C++”子部分,接着是“常规”项。从现在可用的选项列表中选择“附加包含目录”,然后添加解压后的存档路径。

LAME 环境已准备就绪。

其次,抓取 lameHelper_dd_mm_yyyy 存档并解压。

  1. 将两个文件(lameHelper.cpp 和 lameHelper.h)添加到您的项目中。
  2. 在您的项目中包含 #include lameHelper.h。
#include "lameHelper.h"

使用封装库

要使用此封装库,请执行以下操作:

#include "lameHelper.h"

int main()
{
	lameHelper lhHandle;
	return 0;
}

编码 (PCM 转换为 mp3)

该类有三个重载的 encode() 成员函数,用于处理 PCM 到 mp3 的转换。

int lameHelper::encode(char* pcm_in, char* mp3_out);

int lameHelper::encode(char* pcm_in, char* mp3_out, settings_t settings);

int lameHelper::encode(char* pcm_in, char* mp3_out, settings_t settings, WNDPROC callback_proc);

//asynchronous member function
void* encode(char* pcm_in, char* mp3_out, settings_t settings, WNDPROC callback_proc, bool async);

encode(char* pcm_in, char* mp3_out)

encode(char*, char*) 可用于使用封装库默认设置对 PCM 进行编码,这些默认设置在 lameHelper.cpp 的 settings_t::settings_t() 中指定。

默认设置包括:id3 标签设置为 NULL 或空字符串,声道设置为立体声,编码模式为 CBR,采样率为 44100hz,重采样频率为 44100hz,比特率为 128kbps,质量为 5。

参数 

  • pcm_in: PCM (*.wav) 文件的路径。
  • mp3_out: mp3 的输出路径(包括文件名)。

返回值 

该成员函数在成功时返回 0,如果一个或两个路径不可读或不可写则返回 -1,如果 LAME 初始化失败则返回 -2

#include "lameHelper.h"

int main()
{
	lameHelper lhHandle;
	lhHandle.encode("c:/.../song.wav", "c:/.../song.mp3");//Just two lines as promised
	
	return 0;
}

encode(char* pcm_in, char* mp3_out, settings_t settings)

此重载成员函数可用于在指定各种设置和选项的情况下进行编码。

参数 

  • pcm_in: PCM (*.wav) 文件的路径。
  • mp3_out: mp3 的输出路径(包括文件名)。
  • settings: settings_t 结构体的对象,用于指定设置和选项。

返回值 

该成员函数在成功时返回 0,如果一个或两个路径不可读或不可写则返回 -1,如果 LAME 初始化失败则返回 -2

settings_t

settings_t 结构体。

struct settings_t
{
	char* title;
	char* artist;
	char* album;
	char* comment;
	char* year;
	char* track;
	char* genre;
	char* albumart;

	encode_channel_e channels;
	bitrate_e abr_bitrate;
	bitrate_e cbr_bitrate;
	int quality;
	encode_mode_e enc_mode;
	samplerate_e resample_frequency;
	samplerate_e in_samplerate;

	//The constructor: used to set default values
	settings_t();
};

示例

#include "lameHelper.h"


int main()
{
	settings_t settings;
	settings.enc_mode = EM_ABR;
	settings.abr_bitrate = BR_128kbps;//If you are going to use ABR encode mode @ 128kbps
	settings.album = "The Album";//Setting the album (id3 tag)
	settings.albumart = "c:/.../art.jpg";//Setting the albumart
	settings.track = "01";//Setting the track

	//..and various other settings

	lameHelper lhHandle;
	lhHandle.encode("c:/.../song.wav", "c:/.../song.mp3", settings);
	
	return 0;
}

encode(char* pcm_in, char* mp3_out, settings_t settings, WNDPROC callback_proc)

前面描述的前两种方法都是同步的,并且没有关于当前任务进度的通知。此方法也是同步的(即,它也会阻塞),但会发送任务进度的通知。

参数

  • pcm_in: PCM (*.wav) 文件的路径。
  • mp3_out: mp3 的输出路径(包括文件名)。
  • settings: settings_t 结构体的对象,用于指定设置和选项。
  • callback_proc: 一个回调函数 (WNDPROC),它将接收进度通知。

返回值

该成员函数在成功时返回 0,如果一个或两个路径不可读或不可写则返回 -1,如果 LAME 初始化失败则返回 -2

注释 

WNDPROC callback_proc 中,msg 在编码/解码开始时接收 LH_STARTED 消息,在编码/解码过程中接收 LH_COMPUTED 消息(WPARAM 包含进度的百分比(作为 int)),并在编码/解码结束时接收 LH_DONE 消息。

一个典型的 callback_proc。

HRESULT CALLBACK proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch(msg)
	{
	case LH_STARTED:
		//Start of encoding / decoding
		break;
	case LH_COMPUTED:
		//Update of percentage done
		//wParam contains the percentage as int
		//the best way to use this is to pass wParam's value into a progress bar
		printf("%i ", wParam);
		break;
	case LH_DONE:
		//Notifying end of encoding / decoding
		break;
	}

	return 0;
}

一个示例。

#include “lameHelper.h”

HRESULT CALLBACK proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch(msg)
	{
	case LH_STARTED:
		//Start of encoding / decodeing
		break;
	case LH_COMPUTED:
		//Update of percentage done
		//wParam contains the percentage as int
		//the best way to use this is to pass wParam's value into a progress bar
		printf("%i ", wParam);
		break;
	case LH_DONE:
		//Notifying end of encoding / decoding
		break;
	}
	return 0;
}


int main()
{
	settings_t settings;
	//some settings here

	lameHelper lhHandle;
	lhHandle.encode("c:/.../song.wav", "c:/.../song.mp3", settings, proc);
	
	return 0;
}

encode(char* pcm_in, char* mp3_out, settings_t settings, WNDPROC callback_proc, bool async);

此成员函数是异步的(即,不会阻塞)。

参数

  • pcm_in: PCM (*.wav) 文件的路径。
  • mp3_out: mp3 的输出路径(包括文件名)。
  • settings: settings_t 结构体的对象,用于指定设置和选项。
  • callback_proc: 一个回调函数 (WNDPROC),它将接收进度通知。
  • async: 如果设置为 TRUE,函数将是异步的;如果设置为 FALSE,函数将是同步的,并且表现与 ncode(char* pcm_in, char* mp3_out, settings_t settings, WNDPROC callback_proc) 完全相同。默认为 FALSE。

返回值

如果 async 设置为 TRUE,函数在成功时返回一个 HANDLE,如果达到最大允许进程数则返回 -3。如果发生任何其他错误,将发送 LH_ERROR 消息,其中 WPARAM 包含错误代码。

如果 async 设置为 FALSE,成员函数在成功时返回 0,如果一个或两个路径不可读或不可写则返回 -1,如果 LAME 初始化失败则返回 -2

一个异步示例。

#include "lameHelper.h"


HRESULT CALLBACK proc1(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch(msg)
	{
	case LH_STARTED:
		//Start of encoding / decodeing
		break;
	case LH_COMPUTED:
		//Update of percentage done
		//wParam contains the percentage as int
		//the best way to use this is to pass wParam's value into a progress bar
		printf("%i ", wParam);
		break;
	case LH_ERROR:
		printf("Failed with error code %i\n", wParam);
		break;
	case LH_DONE:
		//Notifying end of encoding / decoding
		break;
	}
	return 0;
}

HRESULT CALLBACK proc2(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
HRESULT CALLBACK proc3(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);


int main()
{
	HANDLE hLameHelpers[3];
	settings_t se;
	//Other settings
	
	lameHelper lhHandle;
	
	hLameHelpers[0] = lhHandle.encode("song1.wav", "song1.mp3", se, proc1, true);
	hLameHelpers[1] = lhHandle.encode("song2.wav", "song2.mp3", se, proc2, true);
	hLameHelpers[2] = lhHandle.decode("song3.mp3", "song3.wav", proc3, true);
	
	WaitForMultipleObjects(3, hLameHelpers, TRUE, INFINITE);
	
	return 0;
}

解码 (mp3 转换为 PCM)

此封装库也支持 mp3 的解码,并且有两个重载的成员函数可用于此目的。

int lameHelper::decode(char* mp3_in, char* pcm_out);

int lameHelper::decode(char* mp3_in, char* pcm_out, WNDPROC callback_proc);

//asynchronous member function
void* decode(char* mp3_in, char* pcm_out, WNDPROC callback_proc, bool async);

解码根据 LAME 的默认设置进行。

请注意:从 mp3_in 获取的 mp3 数据应该是纯粹的 mp3 数据(即没有 id3 或 APE 标签)。要了解如何从 mp3 中移除 id3 标签,请阅读我的文章“id3lib 库的封装库”,其中 removeAllTags() 子部分。

decode(char* mp3_in, char* pcm_out)

此函数将 mp3 解码为 PCM。

参数

 

  • mp3_in: 输入 mp3 文件的路径。
  • pcm_out: 输出 PCM (*.wav) 的路径(包括文件名)。

返回值

该成员函数在成功时返回 0,如果一个或两个路径不可读或不可写则返回 -1,如果 LAME 初始化失败则返回 -2

	lameHelper lhHandle;
	lhHandle.decode("c:/.../song.mp3", "c:/.../song.wav");

decode(char* mp3_in, char* pcm_out, WNDPROC callback_proc) 

 

此函数将 mp3 解码为 PCM,并在过程中发送通知。

参数

  • mp3_in: 输入 mp3 文件的路径。
  • pcm_out: 输出 PCM (*.wav) 的路径(包括文件名)。
  • callback_proc: 一个回调函数 (WNDPROC),它将接收进度通知。

返回值 

该成员函数在成功时返回 0,如果一个或两个路径不可读或不可写则返回 -1,如果 LAME 初始化失败则返回 -2

	lameHelper lhHandle;
	lhHandle.decode("c:/.../song.mp3", "c:/.../song.wav", proc);//proc of above example applies

decode(char* mp3_in, char* pcm_out, WNDPROC callback_proc, bool async);

此成员函数是异步的(即,不会阻塞)。

参数

  • mp3_in: 输入 mp3 文件的路径。
  • pcm_out: 输出 PCM (*.wav) 的路径(包括文件名)。
  • callback_proc: 一个回调函数 (WNDPROC),它将接收进度通知。
  • async: 如果设置为 TRUE,函数将是异步的;如果设置为 FALSE,函数将是同步的。默认为 FALSE。

返回值

如果 async 设置为 TRUE,函数在成功时返回一个 HANDLE,如果达到最大允许进程数则返回 -3。如果发生任何其他错误,将发送 LH_ERROR 消息,其中 WPARAM 包含错误代码。

如果 async 设置为 FALSE,成员函数在成功时返回 0,如果一个或两个路径不可读或不可写则返回 -1,如果 LAME 初始化失败则返回 -2

历史

  1. 2013 年 9 月 25 日 - 添加了异步成员函数。
  2. 2013 年 9 月 20 日 - 初始文章。
© . All rights reserved.