imperialeast 发表于 2026-7-24 09:55:47

给WAV文件加音乐标签工具(适用与win10——win11)

本帖最后由 imperialeast 于 2026-7-24 20:24 编辑

’给WAV文件加音乐标签工具,部分代码

Option Explicit

' Unicode(UTF16) -> MultiByte(UTF8) API
Private Declare Function WideCharToMultiByte Lib "kernel32.dll" (ByVal CodePage As Long, ByVal dwFlags As Long, ByVal lpWideCharStr As Long, ByVal cchWideChar As Long, ByVal lpMultiByteStr As Long, ByVal cbMultiByte As Long, ByVal lpDefaultChar As Long, ByVal lpUsedDefaultChar As Long) As Long
Private Declare Function MultiByteToWideChar Lib "kernel32" (ByVal CodePage As Long, ByVal dwFlags As Long, ByVal lpMultiByteStr As Long, ByVal cbMultiByte As Long, ByVal lpWideCharStr As Long, ByVal cchWideChar As Long) As Long
Private Declare Sub RtlMoveMemory Lib "kernel32" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)

Private Declare Function PathFileExistsW Lib "shlwapi.dll" (ByVal lpathfile As Long) As Boolean

' 常量定义
Private Const WC_NO_BEST_FIT_CHARS As Long = &H400
Private Const CP_UTF8 As Long = 65001



Dim lpWav As String

' 输入:VB6原生字符串(UTF16)
' 输出:UTF8编码的Byte数组
Public Function UnicodeToUTF8(ByVal strUnicode As String) As Byte()
    Dim lngStrLen As Long
    Dim lngBufSize As Long
    Dim abytUTF8() As Byte
   
    ' 源字符串长度(字符数)
    lngStrLen = Len(strUnicode)
    If lngStrLen = 0 Then
      ReDim UnicodeToUTF8(-1) ' 返回空数组
      Exit Function
    End If
   
    ' 第一步:获取需要的UTF8缓冲区大小
    lngBufSize = WideCharToMultiByte( _
      CP_UTF8, WC_NO_BEST_FIT_CHARS, _
      StrPtr(strUnicode), lngStrLen, _
      0, 0, 0, 0)
   
    If lngBufSize <= 0 Then
      ReDim UnicodeToUTF8(-1)
      Exit Function
    End If
   
    ' 分配字节数组
    ReDim abytUTF8(1 To lngBufSize)
   
    ' 第二步:真正转换到字节数组
    Call WideCharToMultiByte( _
      CP_UTF8, WC_NO_BEST_FIT_CHARS, _
      StrPtr(strUnicode), lngStrLen, _
      VarPtr(abytUTF8(1)), lngBufSize, _
      0, 0)
   
    UnicodeToUTF8 = abytUTF8
End Function

Public Function UnicodeToUTF8_BOM(ByVal s As String) As Byte()
    Dim raw() As Byte
    Dim out() As Byte
    Dim I As Long, rawLen As Long
   
    raw = UnicodeToUTF8(s)
    ' 空判断
    If Not Not raw Then
      rawLen = UBound(raw)
    Else
      ReDim UnicodeToUTF8_BOM(-1)
      Exit Function
    End If
   
    ' BOM 3字节 + raw全部字节
    ReDim out(1 To 3 + rawLen)
    out(1) = &HEF
    out(2) = &HBB
    out(3) = &HBF
   
    ' 逐字节拷贝
    For I = 1 To rawLen
      out(3 + I) = raw(I)
    Next I
    UnicodeToUTF8_BOM = out
End Function

Public Sub SaveAsUTF8(ByVal sText As String, ByVal sFilePath As String)
    Dim bUTF8() As Byte
    Dim fNum As Integer
    bUTF8 = UnicodeToUTF8(sText)
    fNum = FreeFile
    Open sFilePath For Binary As #fNum
      Put #fNum, , bUTF8
    Close #fNum
End Sub

Public Function BytesToHex(bArr() As Byte) As String
    Dim I As Long
    Dim sOut As String
    For I = LBound(bArr) To UBound(bArr)
      sOut = sOut & Right("00" & Hex(bArr(I)), 2) & " "
    Next
    BytesToHex = Trim(sOut)
End Function
'============FormCommnd====================

Private Sub CD_Click()
Dim lW As String, LstD() As Byte, Dt() As String, LstStr As String, lD As String
On Error GoTo Err_x
lpWav = GetFilePaths(Form1.hWnd, "打开WAVE文件", "WAV文件|*.WAV|", Explorer窗口, App.Path, Chr(0))

lpWav = Left(lpWav, InStrRev(lpWav, Chr(0)) - 1)
T.Text = ""
GetHeadInfoMsg lpWav, LstD, lW, lD
'Dat = wH.ChunkID & "|" & wH.ChunkSize & "|" & wH.Format & "|" & _
            wH.SubChunk1ID & "|" & wH.SubChunk1Size & "|" & _
            wH.AudioFormat & "|" & wH.NumChannels & "|" & wH.BitsPerSaple & "|" & wH.BlockAlign & "|" & wH.SapleRate & "|" & wH.ByteRate & "|" & _
            wH.SubChunk2ID & "|" & wH.SubChunk2Size

'//MsgBox UBound(LstD)
   Dt = Split(lW, "|")
If UBound(Dt) >= 12 Then
   
   LstStr = "文件类型:" & Dt(0) & vbCrLf & "文件大小(字节):" & Dt(1) & vbCrLf & "文件格式:" & Dt(2) & vbCrLf & "Fmt标示:" & Dt(3) & vbCrLf & _
          "数据备注是(>16)否(16):" & Dt(4) & vbCrLf & "音频编码方式(Pcm=1):" & Dt(5) & vbCrLf & "声道:" & Dt(6) & vbCrLf & "采样位数:" & Dt(7) & vbCrLf & _
          "采样字节数:" & Dt(8) & vbCrLf & "采样频率:" & Dt(9) & vbCrLf & "文件码率(kbps):" & (Val(Dt(10)) * 8 \ 1000) & vbCrLf & "架构方式:" & Dt(11) & vbCrLf & _
          "LIST/DATA长度(字节):" & Dt(12) & vbCrLf
      If UCase(Dt(11)) = "DATA" Then
         LstStr = LstStr & "时间(秒):" & CLng(Dt(12)) / ((CLng(Dt(9)) * Val(Dt(7)) * Val(Dt(6))) / 8)
          Else
         Dim St() As String
         St = Split(lD, "|")
      If UBound(St) > 0 Then LstStr = LstStr & lD & vbCrLf & "时间(秒):" & Val(St(1)) / ((CLng(Dt(9)) * Val(Dt(7)) * Val(Dt(6))) / 8)
      End If
End If

'LIST结构信息
Dim Dat() As Byte
'ReDim Dat(UBound(LstD) - 4) As Byte
GetWantData LstD, Dat, 4, UBound(LstD) - 4

   
LstStr = LstStr & vbCrLf & vbCrLf & "LIST架构信息>>" & vbCrLf & "INFO" & vbCrLf & GetWavListKey(Dat)


   T.Text = Replace(LstStr, Chr(0), "") & vbCrLf & "文件路径:" & lpWav
' End If
   Exit Sub
Err_x:
T.Text = LstStr & vbCrLf & "文件路径:" & lpWav
End Sub

Public Function GetXFontSize(ByVal XF As Form, ByVal THeight As Long) As Long
Dim I As Long, X(1 To 32) As Long
   For I = 1 To 32
      XF.ScaleMode = 3
      XF.Font.Size = I
      If XF.TextHeight("H") = THeight Then
          GetXFontSize = I
      End If
    Next
   
If GetXFontSize = 0 Then
    For I = 1 To 32
      XF.ScaleMode = 3
      XF.Font.Size = I
         If XF.TextHeight("H") > THeight And I > 1 Then
            X(I) = XF.TextHeight("H")
         If X(I - 1) < THeight Then
            GetXFontSize = IIf(X(I) - THeight < THeight - X(I - 1), I, I - 1)
         End If
          Exit For
         End If
       Next
End If
End Function

Private Sub CmdI_Click()
Dim LDI(2) As LSTDATAINFO, Ls(2) As Variant
LDI(0).ID = "ICRD"
LDI(0).Size = 26
Ls(0) = UnicodeToUTF8(Year(Now) & "-" & Format(Month(Now), "00") & "-" & Format(Day(Now), "00") & "T" & Format(Hour(Now), "00") & ":" & Format(Minute(Now), "00") & ":" & Format(Second(Now), "00") & "+08:00" & Chr(0))
LDI(1).ID = "INAM"
LDI(1).Size = 6
Ls(1) = UnicodeToUTF8("XiaYU" & Chr(0))
LDI(2).ID = "ISFT"
LDI(2).Size = 13
Ls(2) = UnicodeToUTF8("Lavf60.4.100 " & Chr(0))


Dim lpOut As String
lpOut = Left(lpWav, InStrRev(lpWav, ".") - 1) & "_list.wav"
CreateListWaveFile lpWav, lpOut, LDI, Ls
End Sub

Private Sub Command1_Click()
Dim LDI(4) As LSTDATAINFO, Ls(4) As Variant
If IT(1).Text = "标题" Or IT(1).Text = "" Or IT(0).Text = "艺术家" Or IT(0).Text = "" Or IT(2).Text = "专辑" Or IT(2).Text = "" Then Exit Sub
If CB(0).Text = "中日英文字" Then
   Ls(0) = UnicodeToUTF8(IT(0).Text & Chr(0))
   LDI(0).Size = Val(UBound(UnicodeToUTF8(IT(0).Text & Chr(0))))
   Else
   Ls(0) = UnicodeToUTF8_BOM(IT(0).Text & Chr(0))
   LDI(0).Size = Val(UBound(UnicodeToUTF8_BOM(IT(0).Text & Chr(0))))
End If

If CB(1).Text = "中日英文字" Then
   Ls(1) = UnicodeToUTF8(IT(1).Text & Chr(0))
   LDI(1).Size = Val(UBound(UnicodeToUTF8(IT(1).Text & Chr(0))))
   Else
   Ls(1) = UnicodeToUTF8_BOM(IT(1).Text & Chr(0))
   LDI(1).Size = Val(UBound(UnicodeToUTF8_BOM(IT(1).Text & Chr(0))))
End If

If CB(2).Text = "中日英文字" Then
   Ls(2) = UnicodeToUTF8(IT(2).Text & Chr(0))
   LDI(2).Size = Val(UBound(UnicodeToUTF8(IT(2).Text & Chr(0))))
   Else
   Ls(2) = UnicodeToUTF8_BOM(IT(2).Text & Chr(0))
   LDI(2).Size = Val(UBound(UnicodeToUTF8_BOM(IT(2).Text & Chr(0))))
End If

If CB(3).Text = "中日英文字" Then
   Ls(3) = UnicodeToUTF8(IT(3).Text & Chr(0))
   LDI(3).Size = Val(UBound(UnicodeToUTF8(IT(3).Text & Chr(0))))
   Else
   Ls(3) = UnicodeToUTF8_BOM(IT(3).Text & Chr(0))
   LDI(3).Size = Val(UBound(UnicodeToUTF8_BOM(IT(3).Text & Chr(0))))
End If

LDI(0).ID = "IART"
LDI(1).ID = "INAM"
LDI(2).ID = "IPRD"
LDI(3).ID = "IGNR"



LDI(4).ID = "ISFT" '"IGNR"
LDI(4).Size = 13
Ls(4) = UnicodeToUTF8("Lavf60.4.100" & Chr(0))   'StrConv(IT(3).Text, vbUnicode)
Dim lpOut As String
lpOut = Left(lpWav, InStrRev(lpWav, ".") - 1) & "_list.wav"
CreateListWaveFile lpWav, lpOut, LDI, Ls

End Sub

Private Sub Command2_Click()
Dim lpOut As String
lpOut = Left(lpWav, InStrRev(lpWav, ".") - 1) & "_nolist.wav"

CreateNoListWaveFile lpWav, lpOut

End Sub

Private Sub Form_Load()
Dim I As Byte
For I = 0 To 3
CB(I).AddItem "中日英文字"
CB(I).AddItem "其他文字"
CB(I).Text = "中日英文字"
Next
End Sub

'Judge ID rule
Private Function GetRuleID(ByVal ID As String) As Boolean
Dim I As Integer, StrX As String, Str3 As String
For I = 1 To 4
   StrX = Mid(ID, I, 1)
   If I <= 3 Then
          If Asc(StrX) < 65 Or Asc(StrX) > 122 Then
            GetRuleID = False: Exit For
            Else
            GetRuleID = True
         End If
      Else
            Str3 = Left(ID, 3)
            If (Asc(StrX) < 65 Or Asc(StrX) > 122) Then
               If UCase(Str3) = "FMT" And Asc(StrX) = 32 Then
                   GetRuleID = True
                  Else
                   GetRuleID = False: Exit For
               End If
                Else
                GetRuleID = True
            End If
   End If
Next
End Function

'GET LIST INFO
Private Function GetWavListKey(Dat() As Byte) As String
Dim wBt() As Byte, LDI As LSTDATAINFO, StepX As Integer, TmpStr As String, ID As String
On Error GoTo Err_INF
Do Until StepX >= UBound(Dat)
         GetWantData Dat, wBt, StepX, 8
         RtlMoveMemory LDI, wBt(0), 8
         Erase wBt
         ID = LDI.ID
      If GetRuleID(ID) = False Then
            StepX = StepX + 1
            GetWantData Dat, wBt, StepX, 8
            RtlMoveMemory LDI, wBt(0), 8
            Erase wBt
         Else
            TmpStr = TmpStr & LDI.ID & "="
            TmpStr = Replace(TmpStr, Chr(0), "")
            StepX = StepX + 8
            GetWantData Dat, wBt, StepX, Val(LDI.Size)
            TmpStr = TmpStr & Utf8ToStr(wBt, LDI.Size) & vbCrLf
            Erase wBt
            StepX = StepX + Val(LDI.Size)
            If StepX = UBound(Dat) Then Exit Do
      End If
Loop

   
GetWavListKey = TmpStr
Exit Function
Err_INF:
GetWavListKey = ""
End Function
'--- UTF-8 Byte数组 → VB6 Unicode String ---
Private Function Utf8ToStr(b() As Byte, ByVal Length As Long) As String
    Dim Ws As String, Rtn As Long
    If Length <= 0 Then Exit Function
    Ws = Space$(Length)
    ' MultiByteToWideChar CP_UTF8=65001
    Rtn = MultiByteToWideChar(65001, 0, VarPtr(b(0)), Length, StrPtr(Ws), Length)
    Utf8ToStr = Left(Ws, Rtn)
End Function


页: [1]
查看完整版本: 给WAV文件加音乐标签工具(适用与win10——win11)