windows 读取mp3文件 显示到带时间轴的波形显示控件代码 C++
时间: 2024-05-16 12:16:56 浏览: 125
以下是一个基于 Windows 平台的使用 GDI+ 绘制波形图的示例代码,可以展示 MP3 文件的波形,并将其显示在带时间轴的控件上。
首先需要安装 GDI+,可以在 Visual Studio 中添加依赖项或手动下载安装。然后在代码中包含头文件 `Gdiplus.h` 并在程序初始化时初始化 GDI+。
接下来,我们需要使用一个第三方库来解码 MP3 文件并将其转换为 PCM 数据。这里我们使用了开源库 `libmpg123`,可以在官网下载并安装。安装完成后,在代码中包含头文件 `mpg123.h`,并使用以下代码解码 MP3 文件:
```cpp
// 打开 MP3 文件
mpg123_handle* mh;
mh = mpg123_new(NULL, NULL);
mpg123_open(mh, "sample.mp3");
// 获取 MP3 文件信息
long rate;
int channels, enc;
mpg123_getformat(mh, &rate, &channels, &enc);
// 分配缓冲区
unsigned char* buffer = new unsigned char[mpg123_outblock(mh)];
// 解码 MP3 文件并转换为 PCM 数据
int samples;
short pcm[4096];
while (mpg123_read(mh, buffer, mpg123_outblock(mh), &samples) == MPG123_OK) {
mpg123_decode(mh, buffer, samples, pcm, sizeof(pcm), &samples);
// 将 PCM 数据保存到文件或处理
}
```
解码并转换完成后,我们可以使用 GDI+ 绘制波形图。我们可以使用 `Graphics::DrawLine()` 方法在控件上绘制线条,以表示波形图。代码如下:
```cpp
// 绘制波形图
void DrawWaveform(Graphics* graphics, int x, int y, int width, int height, short* pcm, int count) {
Pen pen(Color(255, 255, 255));
graphics->SetSmoothingMode(SmoothingModeHighQuality);
graphics->SetInterpolationMode(InterpolationModeHighQualityBicubic);
float scaleX = (float)width / count;
float scaleY = (float)height / 65536;
for (int i = 0; i < count - 1; i++) {
float x1 = x + i * scaleX;
float y1 = y + pcm[i] * scaleY + height / 2;
float x2 = x + (i + 1) * scaleX;
float y2 = y + pcm[i + 1] * scaleY + height / 2;
graphics->DrawLine(&pen, x1, y1, x2, y2);
}
}
```
最后,我们需要在窗口中创建一个带时间轴的控件,并在 Windows 消息循环中处理该控件的绘制事件。代码如下:
```cpp
// 创建控件
HWND hwndTimeline = CreateWindowEx(0, WC_STATIC, NULL, WS_CHILD | WS_VISIBLE | WS_BORDER, 10, 10, 400, 100, hwnd, NULL, hInstance, NULL);
// 绘制事件
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
// 获取控件尺寸
RECT rc;
GetClientRect(hwndTimeline, &rc);
// 创建 GDI+ Graphics 对象
Graphics graphics(hdc);
graphics.SetCompositingQuality(CompositingQualityHighQuality);
// 绘制波形图
DrawWaveform(&graphics, rc.left, rc.top + 20, rc.right - rc.left, rc.bottom - rc.top - 20, pcm, count);
EndPaint(hwnd, &ps);
break;
}
```
完整代码示例:
```cpp
#include <Windows.h>
#include <Gdiplus.h>
#include <mpg123.h>
#pragma comment(lib, "gdiplus.lib")
#pragma comment(lib, "libmpg123.lib")
using namespace Gdiplus;
// 绘制波形图
void DrawWaveform(Graphics* graphics, int x, int y, int width, int height, short* pcm, int count) {
Pen pen(Color(255, 255, 255));
graphics->SetSmoothingMode(SmoothingModeHighQuality);
graphics->SetInterpolationMode(InterpolationModeHighQualityBicubic);
float scaleX = (float)width / count;
float scaleY = (float)height / 65536;
for (int i = 0; i < count - 1; i++) {
float x1 = x + i * scaleX;
float y1 = y + pcm[i] * scaleY + height / 2;
float x2 = x + (i + 1) * scaleX;
float y2 = y + pcm[i + 1] * scaleY + height / 2;
graphics->DrawLine(&pen, x1, y1, x2, y2);
}
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_CREATE: {
// 打开 MP3 文件
mpg123_handle* mh;
mh = mpg123_new(NULL, NULL);
mpg123_open(mh, "sample.mp3");
// 获取 MP3 文件信息
long rate;
int channels, enc;
mpg123_getformat(mh, &rate, &channels, &enc);
// 分配缓冲区
unsigned char* buffer = new unsigned char[mpg123_outblock(mh)];
// 解码 MP3 文件并转换为 PCM 数据
int samples;
short pcm[4096];
while (mpg123_read(mh, buffer, mpg123_outblock(mh), &samples) == MPG123_OK) {
mpg123_decode(mh, buffer, samples, pcm, sizeof(pcm), &samples);
// 将 PCM 数据保存到文件或处理
}
// 关闭 MP3 文件
mpg123_close(mh);
mpg123_delete(mh);
delete[] buffer;
break;
}
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
// 获取控件尺寸
RECT rc;
GetClientRect(hwndTimeline, &rc);
// 创建 GDI+ Graphics 对象
Graphics graphics(hdc);
graphics.SetCompositingQuality(CompositingQualityHighQuality);
// 绘制波形图
DrawWaveform(&graphics, rc.left, rc.top + 20, rc.right - rc.left, rc.bottom - rc.top - 20, pcm, count);
EndPaint(hwnd, &ps);
break;
}
case WM_DESTROY: {
PostQuitMessage(0);
break;
}
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
// 初始化 GDI+
ULONG_PTR gdiplusToken;
GdiplusStartupInput gdiplusStartupInput;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
// 创建窗口类
WNDCLASS wc = {};
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.lpszClassName = "MyWindowClass";
RegisterClass(&wc);
// 创建窗口
HWND hwnd = CreateWindow(wc.lpszClassName, "My Window", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, nCmdShow);
// 创建控件
HWND hwndTimeline = CreateWindowEx(0, WC_STATIC, NULL, WS_CHILD | WS_VISIBLE | WS_BORDER, 10, 10, 400, 100, hwnd, NULL, hInstance, NULL);
// Windows 消息循环
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// 关闭 GDI+
GdiplusShutdown(gdiplusToken);
return 0;
}
```
阅读全文