gpt4 book ai didi

c# - 带有winmm3.dll的音频播放/倒带功能

转载 作者:太空宇宙 更新时间:2023-11-03 13:26:01 27 4
gpt4 key购买 nike

我正在使用Winmm.dll在C#的mp3播放器上工作

我的快退功能现在有问题。

当播放功能启动时,我启动了一个计时器。

当我启动FFW功能时,我希望它从elapsedTime的当前值开始ffw 5000ms。

例如,如果我开始播放歌曲并按FFW 6秒进入歌曲,则播放应以6000ms + 5000ms(ffw5sec)继续。

但是什么也没发生。这次我做错了什么?

namespace kTP
{
public class MusicPlayer
{
[DllImport("winmm.dll")]
private static extern long mciSendString(string lpstrCommand, StringBuilder lpstrReturnString, int uReturnLength, int hwndCallback);

private bool isPlaying = false;
private int ffw5sec = 5000;

Timer elapsedTime = new Timer();

public void Open(string file)
{
string command = "open \"" + file + "\" type MPEGVideo alias MyMp3";
mciSendString(command, null, 0, 0);
}

public void Play()
{
isPlaying = true;
elapsedTime.Start();
elapsedTime.Interval = (1000);

string command = "play MyMp3";
mciSendString(command, null, 0, 0);
}

public void Pause()
{
isPlaying = false;
string command = "pause MyMp3";
mciSendString(command, null, 0, 0);
}

public void Stop()
{
isPlaying = false;
string command = "stop MyMp3";
mciSendString(command, null, 0, 0);

elapsedTime.Stop();

command = "close MyMp3";
mciSendString(command, null, 0, 0);
}

// return to start of song and resume playback
public void ReturnToStart()
{
isPlaying = true;
string command = "seek MyMp3 to start";
mciSendString(command, null, 0, 0);

command = "play MyMp3";
mciSendString(command, null, 0, 0);
}

// Fast Forward
// needs a better skip Implementation
public void FFW()
{
if (isPlaying == true)
{
string command = "set MyMp3 time format ms";
mciSendString(command, null, 0, 0);

command = "seek MyMp3 to " + (elapsedTime.ToString() + ffw5sec.ToString());
mciSendString(command, null, 0, 0);

command = "play MyMp3";
mciSendString(command, null, 0, 0);

//ffw5sec += 5000;
}
}

}
}

最佳答案

在这行代码中:

command = "seek MyMp3 to " + (elapsedTime.ToString() + ffw5sec.ToString());


您将elapsedTime和ffw5sec的字符串形式连接起来,而elapsedTime的字符串形式是不可解析的,即您无法将其解析为整数。
同样在您的问题中,您不会告诉其他人您确切使用的是哪个计时器。
在C#.NET框架中,存在三种Timer类。

有:

System.Timers.Timer,
System.Threading.Timer, and
System.Windows.Forms.Timer


但是,任何这些计时器类的字符串形式都不是不可解析的。

System.Timers.Timer的字符串形式为 "System.Timers.Timer"System.Threading.Timer的字符串形式为 "System.Threading.Timer"System.Windows.Forms.Timer的字符串形式为 "System.Windows.Forms.Timer, Interval: {0}",其中 {0}System.Windows.Forms.Timer.Interval属性替换。

无论如何,我知道您不使用 System.Threading.Timer,因为在问题中发布的代码中,我看到您使用了空的构造函数来创建计时器 Timer(),并且 System.Threading.Timer不包含采用0的构造函数。参数,但我仍然不知道它是 System.Timers.Timer还是 System.Windows.Forms.Timer

seek命令的字符串格式的语法为:

"seek {0} to {1}"


其中 {0}被要查找的音频文件的路径和名称或别名替换,对于您而言,{0}是 MyMp3。并且 {1}替换为音频文件中的时间,该时间只能是整数

表达式: (elapsedTime.ToString() + ffw5sec.ToString()),根本不返回可以解析为整数的字符串。

驱动程序无法执行此命令。

还建议使用 String.Format方法为 mciSendString函数准备和制作mci字符串命令,而不要使用串联字符串方法,因为String.Format方法比串联字符串方法更易于使用和方便。这样,您就不会感到困惑和犯错误。同样,通过String.Format格式化的mci字符串命令比串联的mci字符串命令更易读。

您所做的另一个错误是,您首先将elapsedTime和ffw5sec转换为字符串,然后将它们串联在一起,然后将结果字符串连接到mci string命令。

那样做是错误的。您应首先添加代表时间的elapsedTime和ffw5sec的整数值,然后将结果转换为字符串并将其连接到mci string命令。

我要说的是,您不应调用ToString两次,但可以使用一次。

使用mci string命令的错误方式是:

"seek MyMp3 to " + (elapsedTime.ToString() + ffw5sec.ToString())"


制作mci string命令的正确方法是:

"seek MyMp3 to " + (elapsedTime + ffw5sec).ToString()


这仅在elapsedTime为整数的情况下有效,但如果不是,则应使用其将时间作为整数返回的属性之一。

如果elapsedTime的字符串形式是可解析的,则由于您的错误,mci字符串命令为: "seek MyMp3 to 50006000",因为您将“ 5000”与“ 6000”连接在一起,结果为“ 50006000”。

但是以正确的方式,mci字符串命令应为: "seek MyMp3 to 11000",因为首先将5000和6000相加,结果是11000作为整数。

您甚至根本不需要使用 ToString(),因为您可以将字符串与整数连接起来,而不仅是将字符串与字符串连接起来,无论如何都会产生字符串。例如,两种情况都有效:

"seek MyMp3 to " + **"** 11000 **"** = "seek MyMp3 to 11000",




"seek MyMp3 to " + 11000 = "seek MyMp3 to 11000"


因此,有更好的方法来制作mci string命令:

"seek MyMp3 to " + (elapsedTime + ffw5sec)


但是括号仍然很重要,因为如果没有括号,则将5000与mci string命令并置ffw5sec并置。结果再次是错误的:

"seek MyMp3 to " + elapsedTime + ffw5sec = "seek MyMp3 to 50006000"


也不要使用Timer类,因为在定时器和回调方法之外执行其他操作时,该类用于在每个间隔时间调用回调方法。

Timer类不用于测量经过的时间。您应该改用Stopwatch类,该类可以在System.Diagnostics命名空间中找到。将系统引用添加到您的项目中非常重要,因此您可以在此命名空间中找到此类。

Stopwatch类也具有Start方法,就像Timer类一样,但是区别在于Timer类的Start方法根据您所使用的计时器开始执行Elapsed事件,Tick事件或构造函数中提供的回调函数。使用我之前提到的。

Stopwatch类的实例与任何回调方法都没有联系。相反,它们具有私有时间数据字段和公共属性,以某种形式返回该时间数据。

有一个 ElapsedMilliseconds属性可返回秒表的所有运行时间所经过的时间(64位整数),以毫秒为单位。

还具有 ElapsedTicks属性,该属性与 ElapsedMilliseconds相同,但是返回的时间以ticks为单位进行度量。

一秒(毫秒)内超过1000个刻度。

Elapsed属性与ElapsedMilliseconds和ElapsedTicks相同,但时间根本不返回为长整数,而是TimeSpan结构,该结构也将秒表实例的私有时间数据存储为私有,也可以返回为int( 32位整数),根据其属性,以许多单位为长或双,例如天,小时,毫秒,分钟,秒,刻度等。

无论如何,将elapsedTime的类型从 Timer更改为 Stopwatch,并且不要忘记首先使用System.Diagnostics命名空间才能使用此类。您还需要在项目中引用系统参考。

现在,您终于可以修复命令:

command = String.Format("seek MyMp3 to {0}", elapsedTime.ElapsedMilliseconds + ffw5sec);


这应该很好用,但是有时不要忘记使用Reset或Restart方法将经过时间重置为零。如果您希望秒表在经过的时间重置为零后仍处于运行状态,请使用“重新启动”方法。否则,只需使用Reset方法。

如果仍然存在问题,那么您将不得不使用DllImport来终止mciGetErrorString函数,并在mciSendString不起作用时使用它来查找问题,因为您在其中输入了错误的参数。

C#中的mciGetErrorString的声明为:

[DllImport("winmm.dll")]
static extern Int32 mciGetErrorString(Int32 errorCode, StringBuilder errorText, Int32 errorTextSize);


无论在何处,建议将上述代码段添加到C#程序中的其他已声明方法之间,但要在Program类中声明入口点Main方法的位置。

每当mciSendString无法执行您在其中输入的命令时,它都会以整数形式返回错误代码。

您应该将该错误代码输入mciGetErrorString。 mciGetErrorString将修改StringBuilder实例并在其中写入错误字符串。

然后使用Object.ToString()或Console.Write或Console.WriteLine方法输出StringBuilder实例的字符串形式。

输出将描述错误,这是mciSendString未能执行命令的原因。这将帮助您找出问题所在,并直接考虑您的解决方案。

希望所有这些对您有所帮助。祝好运!

关于c# - 带有winmm3.dll的音频播放/倒带功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22427373/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com