0

好的,所以我使用 mciSendString 创建了一个 SOUND 类。我正在使用它来播放我正在制作的 RPG 风格游戏的音乐和其他声音文件。它有效,而且效果很好……但是。我的问题是它需要声音文件的完整路径才能正常工作(不确定这是否属实)。

以下是 mcisendstring 的一些怪癖:

  • mcisendstring 讨厌空格,空格会导致崩溃(无法加载文件) - 添加引号
  • 路径中的点会导致加载失败(仅点应用于扩展)
  • 非常长的路径将导致加载失败(允许的最大字符数为 255)
  • 相对路径会导致加载失败...(不能使用像 chicken.mp3 之类的东西...必须使用 C:\chicken.mp3)
  • 如果repeat = true,.wav 文件将无法加载

我尝试将文件添加到我的资源并尝试设置资源的路径,但是它说:Value of type '1-dimensional array of Byte' cannot be converted to 'String'.

任何帮助是极大的赞赏 :)

这是我的代码:

Public Class SOUND

Public Declare Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" _
(ByVal lpstrCommand As String, ByVal lpstrReturnString As String, ByVal uReturnLength As Integer, ByVal hwndCallback As Integer) As Integer
'Command String VERY IMPORTANT

Private oName As String = Nothing

Public Property Name As String
    Set(value As String)
        oName = value
    End Set
    Get
        Return oName
    End Get
End Property

Public Sub Play(ByVal id As Integer, ByVal repeat As Boolean, Optional volume As Integer = 1000)

    If repeat = True Then

        mciSendString("Open " & GetFile(id) & " alias " & oName, CStr(0), 0, 0) 'Open the file
        mciSendString("play " & oName & " repeat ", CStr(0), 0, 0) 'then play with repeating value

    Else

        mciSendString("Open " & GetFile(id) & " alias " & oName, CStr(0), 0, 0)
        mciSendString("play " & oName, CStr(0), 0, 0)

    End If

    'Optionally Set Volume
    mciSendString("setaudio " & oName & " volume to " & volume, CStr(0), 0, 0)

End Sub

Public Sub Kill(ByVal song As String)

    mciSendString("close " & song, CStr(0), 0, 0)
    oName = Nothing

End Sub

' Media Library
Private Function GetFile(ByVal id As Integer) As String

    Dim path As String = ""

    'mcisendstring Hates spaces, spaces will cause crash (failure to load file) - ADD QUOTES
    'Dots in path can cause failure to load (only dot should be for the extention)
    'Very Long Paths will cause failure to load (Max Characters allowed is 255)
    'Relative paths will cause failure to load...(cannot use something like chicken.mp3 ... must use ex:[C:\chicken.mp3])
    '.wav files will fail to load if repeat = true

    Select Case id

        Case 0 'Game Over

            path = "C:\FinalFantasy7-SendaDreamIntoTheUniverse.mp3"

        Case 1 'Battle Sequence

            path = "C:\FinalFantasyTactics-Garland_Magic.mp3"

        Case 2 'Battle Victory

            path = "C:\FinalFantasyLegend2-Victory.mp3"

        Case 3 'Mission Time

            path = "C:\FinalFantasyAdventure-Mission.mp3"

    End Select

    path = Chr(34) & path & Chr(34)
    'Chr(34) is quotes...cannot just use "" because it will think that it is part of the string/path itself.


    Return path
End Function

结束类

我需要的:

  • 我需要以某种方式将 .mp3 文件作为可用于路径的资源,或者我需要一些其他方法,而不是让这些文件位于根驱动器或其他完整的计算机路径中。

我需要的东西的例子

改变

Select Case id

            Case 0 'Game Over

                path = "C:\FinalFantasy7-SendaDreamIntoTheUniverse.mp3"
End Select

Select Case id

            Case 0 'Game Over

                path = My.Resources.FinalFantasyAdventure_Mission
End Select

我如何播放声音:

(在另一个测试表上)

Dim intSound As Integer = 0
Dim snd As New SOUND 'SOUND is the sound class with mcisendstring

Private Sub PlaySoundBtn_Click(sender As System.Object, e As System.EventArgs) Handles PlaySoundBtn.Click

    intSound += 1

    With snd
        .Name = "SOUND" & intSound 'SOUND is the alias along with the number (this one is SOUND1)
        .Play(3, True, 500)
        '3 is the song ID, True is for the repeat, 500 is for the optional volume (Max = 1000)
    End With

End Sub

PS 我在我的项目中使用 XNA Graphics,我也有 NuGet 的 BizArk Core。因此,如果我可以使用其中任何一个,请告诉我如何使用其中任何一个来完成我需要做的事情。提前感谢您的帮助。

4

2 回答 2

1

如上所述,这是一个旧线程,但我想谷歌仍然会有人找到它(就像我今天所做的那样)。

只是一个额外的建议,有时您不会将音频文件放在输出目录中,或者可能希望分发独立​​的可执行文件。还存在文件可以从输出目录中删除的风险,并且能够重新创建它很方便。此外,将资源作为可执行文件的一部分并在输出目录中占用的空间比仅将其作为可执行文件的一部分占用更多的空间,因此有时仅将文件暂时放在磁盘上(并稍后删除)而不是让在那里有一个永久副本,以便您可以访问它。

在这些情况下,能够在运行时从资源中获取文件并将其保存到磁盘上您可以访问的某个位置(如果您想稍后删除它,可能是一个临时文件位置)是很有用的。

下面非常简单的代码可以做到这一点:

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load

    SaveResourceObject("FinalFantasyAdventure_Mission", "C:\FinalFantasyAdventure_Mission.mp3")

End Sub

Sub SaveResourceObject(Resource as String, FileName as String)
    Dim myMemStream As New System.IO.MemoryStream
    My.Resources.ResourceManager.GetObject(Resource).CopyTo(myMemStream)
    Dim myBytes() As Byte = myMemStream.ToArray
    My.Computer.FileSystem.WriteAllBytes(FileName, myBytes, False)
End Sub

注意,上面代码中的 Resource 变量实际上是资源的名称,而不是资源本身。因此,如果您尝试执行以下操作,您将收到错误消息:

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    SaveResourceObject(My.Resources.FinalFantasyAdventure_Mission, "C:\FinalFantasyAdventure_Mission.mp3")
End Sub

如果您愿意,您可以轻松地修改代码以接受实际资源作为参数。

请注意,我在上面的示例中使用了“C:\”,但我建议您在应用程序数据文件夹中创建自己的文件夹,您可以使用以下命令找到该文件夹​​:

Dim AppDataPath as String = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData)

或者,如果您已经导入 System.Environment,则更简单:

Dim AppDataPath as String = GetFolderPath(SpecialFolder.ApplicationData)
于 2017-09-16T06:29:43.120 回答
0

我知道这是一个超级旧的线程,但如果它对任何人有帮助,这里有一个解决方案。

您将不得不使用完整路径,但假设您的资源存储在/projectfolder/resources/您可以使用

Dim filePath As String = Chr(34) & Application.StartupPath & "/../../Resources/myMusic.mp3" & Chr(34)
mciSendString("open " & filePath & " alias myMusic", CStr(0), 0, 0)

在 VB.NET 项目中,是存储Application.StartupPath文件夹的完整路径.exe。通常位于path/projectfolder/bin/debug/path/projectfolder/bin/release/. 附加/../../resources/到它会带你到/projectfolder/resources/,让你不知道你的文件夹的完整路径,因为 VB.NET 自己找到它。

于 2015-11-02T12:27:51.580 回答