2

シナリオ


私は通常、MP3Gainアプリケーションを使用して、mp3 ファイルの再生ゲインを設定します。

アプリケーションは、mp3 ファイルのAPEv2タグに次のフィールドを作成できます。

ここに画像の説明を入力

(スクリーンショットはWinAmpプレーヤーから取得したものです)

質問


TagLibSharpライブラリを使用してID3v1およびID3v2パーサーを作成しましたが、このライブラリを使用して前述のAPEv2フィールドを読み書きできるかどうか疑問に思っています。

リサーチ


MP3Gainアプリはフィールドに一意の名前を使用しているため、おそらくTagLibsharpそれらをサポートしていないと思いますが、TagLibsharpライブラリにはReadBlock()Removeblock()Find()およびRFind()メソッドがあり、そのために使用する必要があると思いますが、正確な使用方法はわかりませんそれらを組み合わせて...

これは私が持っている唯一のものです:

Dim file As New TagLib.Mpeg.AudioFile("C:\input.mp3")
Dim data As Byte() = Encoding.ASCII.GetBytes("MP3GAIN_MINMAX")
Dim vector As New ByteVector(data)
Dim offset As Long = file.Find(vector)

これは、予想される抽象化または動作を示すためだけに Vb.Net で記述された疑似コードです。

Imports TagLib

Public NotInheritable Class Mp3File

    Private tagFile As Global.TagLib.Mpeg.AudioFile

    Public ReadOnly Property APEv2 As APEv2Tag
        Get
            Return Me.apeTagB
        End Get
    End Property
    Private ReadOnly apeTagB As APEv2Tag

    Public Sub New(ByVal file As FileInfo)
        Me.tagFile = New Global.TagLib.Mpeg.AudioFile(file.FullName)
        Me.apeTagB = New APEv2Tag(Me.tagFile)
    End Sub

End Class

''' <summary>
''' Represents the APEv2 tag for a MP3 file.
''' </summary>
Public Class APEv2Tag

    Protected ReadOnly mp3File As Global.TagLib.Mpeg.AudioFile

    Public Sub New(ByVal mp3File As Global.TagLib.Mpeg.AudioFile)
        Me.mp3File = mp3File
    End Sub

    Public Overridable Property MP3GAIN_MINMAX As Double
        Get
            If field exists then...
                Return TheValue...
            End If
        End Get
        Set(ByVal value As Double)
            ...
        End Set
    End Property

    ' More properties here...

End Class

アップデート:

ようやく自分で「読み取り」部分を完成させたと思いますが、フィールドが存在しないとファイルを上書き/破損する可能性があるため、ブロックの書き込み方法がわかりません...

    ''' ----------------------------------------------------------------------------------------------------
    ''' <summary>
    ''' Gets the <c>MP3GAIN_MINMAX</c> metatada field of the audio file.
    ''' </summary>
    ''' ----------------------------------------------------------------------------------------------------
    ''' <returns>
    ''' The <c>MP3GAIN_MINMAX</c> field value.
    ''' </returns>
    ''' ----------------------------------------------------------------------------------------------------
    <DebuggerStepThrough>
    Private Function GetFieldMP3GainMinMax() As String

        Dim data As Byte() = Encoding.UTF8.GetBytes("MP3GAIN_MINMAX")
        Dim vector As New ByteVector(data)
        Dim offset As Long = Me.mp3File.Find(vector)
        Dim result As String

        If (offset = -1) Then
            Return String.Empty

        Else
            Try
                offset += ("MP3GAIN_MINMAX".Length + 1)
                Me.mp3File.Seek(offset, SeekOrigin.Begin)
                result = Me.mp3File.ReadBlock(8).ToString.TrimEnd()
                Return result

            Catch ex As Exception
                Throw

            Finally
                Me.mp3File.Seek(0, SeekOrigin.Begin)

            End Try

        End If

    End Function

    ''' ----------------------------------------------------------------------------------------------------
    ''' <summary>
    ''' Gets the <c>MP3GAIN_UNDO</c> metatada field of the audio file.
    ''' </summary>
    ''' ----------------------------------------------------------------------------------------------------
    ''' <returns>
    ''' The <c>MP3GAIN_UNDO</c> field value.
    ''' </returns>
    ''' ----------------------------------------------------------------------------------------------------
    <DebuggerStepThrough>
    Private Function GetFieldMP3GainUndo() As String

        Dim data As Byte() = Encoding.UTF8.GetBytes("MP3GAIN_UNDO")
        Dim vector As New ByteVector(data)
        Dim offset As Long = Me.mp3File.Find(vector)
        Dim result As String

        If (offset = -1) Then
            Return String.Empty

        Else
            Try
                offset += ("MP3GAIN_UNDO".Length + 1)
                Me.mp3File.Seek(offset, SeekOrigin.Begin)
                result = Me.mp3File.ReadBlock(12).ToString.TrimEnd()
                Return result

            Catch ex As Exception
                Throw

            Finally
                Me.mp3File.Seek(0, SeekOrigin.Begin)

            End Try

        End If

    End Function

    ''' ----------------------------------------------------------------------------------------------------
    ''' <summary>
    ''' Gets the <c>REPLAYGAIN_TRACK_GAIN</c> metatada field of the audio file.
    ''' </summary>
    ''' ----------------------------------------------------------------------------------------------------
    ''' <returns>
    ''' The <c>REPLAYGAIN_TRACK_GAIN</c> field value.
    ''' </returns>
    ''' ----------------------------------------------------------------------------------------------------
    <DebuggerStepThrough>
    Private Function GetFieldReplayGainTrackGain() As String

        Dim data As Byte() = Encoding.UTF8.GetBytes("REPLAYGAIN_TRACK_GAIN")
        Dim vector As New ByteVector(data)
        Dim offset As Long = Me.mp3File.Find(vector)
        Dim result As String

        If (offset = -1) Then
            Return String.Empty

        Else
            Try
                offset += ("REPLAYGAIN_TRACK_GAIN".Length + 1)
                Me.mp3File.Seek(offset, SeekOrigin.Begin)
                result = Me.mp3File.ReadBlock(12).ToString.TrimEnd()
                Return result

            Catch ex As Exception
                Throw

            Finally
                Me.mp3File.Seek(0, SeekOrigin.Begin)

            End Try

        End If

    End Function

    ''' ----------------------------------------------------------------------------------------------------
    ''' <summary>
    ''' Gets the <c>REPLAYGAIN_TRACK_PEAK</c> metatada field of the audio file.
    ''' </summary>
    ''' ----------------------------------------------------------------------------------------------------
    ''' <returns>
    ''' The <c>REPLAYGAIN_TRACK_PEAK</c> field value.
    ''' </returns>
    ''' ----------------------------------------------------------------------------------------------------
    <DebuggerStepThrough>
    Private Function GetFieldReplayGainTrackPeak() As String

        Dim data As Byte() = Encoding.UTF8.GetBytes("REPLAYGAIN_TRACK_PEAK")
        Dim vector As New ByteVector(data)
        Dim offset As Long = Me.mp3File.Find(vector)
        Dim result As String

        If (offset = -1) Then
            Return String.Empty

        Else
            Try
                offset += ("REPLAYGAIN_TRACK_PEAK".Length + 1)
                Me.mp3File.Seek(offset, SeekOrigin.Begin)
                result = Me.mp3File.ReadBlock(8).ToString.TrimEnd()
                Return result

            Catch ex As Exception
                Throw

            Finally
                Me.mp3File.Seek(0, SeekOrigin.Begin)

            End Try

        End If

    End Function
4

1 に答える 1

4

TagLib# ファイルから APEv2 固有の情報を取得するプロセスは、この回答で説明されている ID3v2 タグのプロセスと似ています。

値の読み方は次のとおりです。

// Get the APEv2 tag if it exists.
TagLib.Ape.Tag ape_tag = (TagLib.Ape.Tag)file.GetTag(TagLib.TagTypes.Ape, false);

if(ape_tag != null) {

    // Get the item.
    TagLib.Ape.Item item = ape_tag.GetItem("MP3GAIN_MINMAX");

    if (item != null) {
        Console.Log(item.ToStringArray());
    }
}

フィールドが単一の文字列なのか、コンマで結合された 2 つの文字列なのか、スクリーンショットからはわかりません。

保存は逆方向ですが、少し簡単です。

// Get the APEv2 tag if it exists.
TagLib.Ape.Tag ape_tag = (TagLib.Ape.Tag)file.GetTag(TagLib.TagTypes.Ape, true);

if(ape_tag != null) {
    ape_tag.SetValue("MP3GAIN_MINMAX", value);
}

file.Save();

Vb.Net の例:

田畑:

ReadOnly mp3File As Global.TagLib.Mpeg.AudioFile = ...

プロパティ (MP3Gain 関連):

Property MP3GainMinMax As String
    Get
        Return Me.GetField("MP3GAIN_MINMAX")
    End Get
    Set(ByVal value As String)
        Me.SetField("MP3GAIN_MINMAX", value)
    End Set
End Property

Property MP3GainUndo As String
    Get
        Return Me.GetField("MP3GAIN_UNDO")
    End Get
    Set(ByVal value As String)
        Me.SetField("MP3GAIN_UNDO", value)
    End Set
End Property

Property ReplayGainTrackGain As String
    Get
        Return Me.GetField("REPLAYGAIN_TRACK_GAIN")
    End Get
    Set(ByVal value As String)
        Me.SetField("REPLAYGAIN_TRACK_GAIN", value)
    End Set
End Property

Property ReplayGainTrackPeak As String
    Get
        Return Me.GetField("REPLAYGAIN_TRACK_PEAK")
    End Get
    Set(ByVal value As String)
        Me.SetField("REPLAYGAIN_TRACK_PEAK", value)
    End Set
End Property

関数「取得」:

Function GetField(ByVal fieldName As String) As String

    Dim apeTag As TagLib.Ape.Tag =
        DirectCast(Me.mp3File.GetTag(TagTypes.Ape, create:=False), TagLib.Ape.Tag)

    If (apeTag IsNot Nothing) Then
        Dim item As TagLib.Ape.Item = apeTag.GetItem(fieldName)

        If (item IsNot Nothing) Then
            Return item.ToString()
        End If
    End If

    Return String.Empty

End Function

メソッド「設定」:

Sub SetField(ByVal fieldName As String, ByVal value As String)

    Dim apeTag As TagLib.Ape.Tag = 
        DirectCast(Me.mp3File.GetTag(TagTypes.Ape, create:=True), TagLib.Ape.Tag)

    apeTag.SetValue(fieldName, value)

End Sub
于 2016-03-31T21:56:08.540 に答える