对于mp3歌曲,TMediaPlayer的Length属性错误!求解!(100分)

  • 主题发起人 主题发起人 hmisty
  • 开始时间 开始时间
H

hmisty

Unregistered / Unconfirmed
GUEST, unregistred user!
做一个mp3播放器,发现mediaplay控件的length属性所得到的长度与mp3实际长度不符。比如 蝴蝶花,长度3分钟左右,可是length返回10分钟!
 
[:)]关于这个问题,我可以自己回答么?呵呵。昨晚查了一晚上资料,还看了MPlayer.pas的源码,看到它是用的mcisendcommand来实现的操作,具体代码如下:
property Length: Longint read GetLength;
......
function TMediaPlayer.GetLength: Longint;
var
StatusParm: TMCI_Status_Parms;
begin

CheckIfOpen;
{raises exception if device is not open}
FFlags := mci_Wait or mci_Status_Item;
StatusParm.dwItem := mci_Status_Length;
FError := mciSendCommand( FDeviceID, mci_Status, FFlags, Longint(@StatusParm));
Result := StatusParm.dwReturn;
end;

关于mcisendcommand的语法可以在win32 api中查到
而在csdn文章 http://www.csdn.net/develop/read_article.asp?id=14940
中描述了MPlayer控件设计中的一个错误,其中还提到“而且MediaPlay.Length的长度也不正确”,可惜无法和原作者联系。
于是自己动手,用mcisendstring写了一个getMP3Len函数来获取mp3长度,发现与mediaplayer的length属性返回值是一样的。
百思不得其解之际用cooleditor把那首mp3打开,发现其采样率竟然只有37kbps。用winamp播放,拖动,才发现这首mp3制作不好,采样率是变化的!
于是计算了一下:
3,605,771bytes*8bits/byte/37*1024bps=761s=12.69min
终于明白了,mci api计算播放时间不过是将文件大小除以采样率;
于是用cooledit将采样率恒定,另存,再次用mediaplayer.length检测长度,就正确了。
但是问题并没有结束,为什么winamp和explorer都可以给出正确的长度呢?可见他们都不是用的mci api来做的,于是继续查找资料,发现在可以通过directX sdk来操作媒体文件:
g_pGraphBuilder: IGraphBuilder = nil;
g_pMediaControl: IMediaControl = nil;
// 播放状态设置.
g_pMediaSeeking: IMediaSeeking = nil;
// 播放位置.
g_pAudioControl: IBasicAudio = nil;
// 音量/平衡设置.
g_pVideoWindow: IVideoWindow = nil;
//设置播放窗体.
PLAYING: boolean = false;
//判断是否正在播放

function Initdxcom: boolean;
begin
Result := false;
// 初始化COM接口
if failed(CoInitialize(nil)) then
exit;
// 创建DirectShow Graph
if failed(CoCreateInstance(OLE2.TGUID(CLSID_FilterGraph), nil, CLSCTX_INPROC, OLE2.TGUID(IID_IGraphBuilder), g_pGraphBuilder)) then
exit;
// 获取IMediaControl 接口
if failed(g_pGraphBuilder.QueryInterface(IID_IMediaControl, g_pMediaControl)) then
exit;
// 获取IMediaSeeking 接口
if failed(g_pGraphBuilder.QueryInterface(IID_IMediaSeeking, g_pMediaSeeking)) then
exit;
// 获取IBasicAudio 接口
if failed(g_pGraphBuilder.QueryInterface(IID_IBasicAudio, g_pAudioControl)) then
exit;
// 获取IVideowindow 接口
if failed(g_pGraphBuilder.QueryInterface(IID_IVideoWindow, g_pVideoWindow)) then
exit;
// 所有接口获取成功
Result := true;
end;

然后渲染:
_hr := g_pGraphBuilder.renderfile(@wfile, nil);
// 建立了一个能够播放文件的Filter Graph
渲染后就可以进行各种播放操作和状态查询
但是需要uses DirectShow,可是我的delphi中没有,所以也没能够实验。但是我觉得这种方法所获得媒体长度应该是更真实的。
谁能告诉我如何才能进行directshow编程,不胜感激!
hmisty 2003.7.25
 
MP3压缩工具的问题,一般用XING压缩的MP3格式返回时间都比原来长很多,你可以用UE之类的软件直接打开MP3看看文件头你就知道了,如果你一定要用MEDIAPLAYER解决方法是判断一下文件头,XING压缩的好像要除以一个采样*频率吧!具体记不清了,好久以前搞的了。
 
要进行DIRECTSHOW编程可以到微软网站上下个SDK
 
后退
顶部