如何读取MP3头文件

char tag[ 3+1 ];  //MP3头文件标识
 char author[ 30+1]; //作者
 char title[ 30+1 ]; //曲目名
 char year[ 4+1 ]; //发行年份
 char remark[ 30+1 ]; //评论
 char disc_name[ 30+1 ]; //专辑名称

bool ReadMp3Info( const char* fn )
{
 FILE *fp;
 fp = fopen( fn, "r" );
 if( !fp )
  return false;

 fseek( fp, -128, SEEK_END );  //读取最后128位的mp3信息

 fread( tag, 1, 3, fp );//读取tag
 tag[ 3 ] = '/0';

 if( strcmp( tag, "TAG" )  != 0 ) //如果tag值不为“TAG”,则表示不是一个标准可读信息的MP3文件
  return false;


 fread( title, 1, 30, fp );
 fread( author, 1, 30, fp );

 fread( disc_name, 1, 30, fp );
  fread( year, 1, 4, fp );
 fread( remark, 1, 30, fp );

 fclose( fp );
 return true;

}

以下是一个基于 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; } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值