VB.NET-Tipp 0146: Informationen zu Titel, Jahr, Interpret, Album und Genre aus MPEG 4-Audiodateien lesen
von Fabi
Beschreibung
Die vorgestellte Klasse ermöglicht es die Informationen zu Titel, Jahr, Interpret, Album und Genre aus einer MPEG 4-Audiodatei zu lesen. Eine Beschreibung des Aufbaus des MPEG4-Containers findet sich beispielsweise unter http://atomicparsley.sourceforge.net/mpeg-4files.html. Es ist möglich die Klasse zum Auslesen weiterer Metainformationen aus den Dateien zu erweitern.
Schwierigkeitsgrad: | Framework-Version(en): .NET Framework 1.0, .NET Framework 1.1, .NET Framework 2.0, .NET Framework 3.0, .NET Framework 3.5, .NET Framework 4 | .NET-Version(en): Visual Basic 2002, Visual Basic 2003, Visual Basic 2005, Visual Basic 2008, Visual Basic 2010 | Download: |
' Dieser Quellcode stammt von http://www.activevb.de ' und kann frei verwendet werden. Für eventuelle Schäden ' wird nicht gehaftet. ' Um Fehler oder Fragen zu klären, nutzen Sie bitte unser Forum. ' Ansonsten viel Spaß und Erfolg mit diesem Source! ' Projektversion: Visual Studio 2008 ' Option Strict: Aus ' Option Explicit: An ' Option Infer: An ' ' Referenzen: ' - System ' - System.Data ' - System.Deployment ' - System.Drawing ' - System.Windows.Forms ' - System.Xml ' - System.Core ' - System.Xml.Linq ' - System.Data.DataSetExtensions ' ' Imports: ' - Microsoft.VisualBasic ' - System ' - System.Collections ' - System.Collections.Generic ' - System.Data ' - System.Drawing ' - System.Diagnostics ' - System.Windows.Forms ' - System.Linq ' - System.Xml.Linq ' ' ############################################################################## ' ################################# Form1.vb ################################### ' ############################################################################## Public Class Form1 Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click Dim ofd As New OpenFileDialog _ With {.Filter = "MPEG4 Files|*.mp4;*.m4a"} ofd.ShowDialog() If IO.File.Exists(ofd.FileName) Then Dim Info As New MPEG4Info(ofd.FileName) lstInfo.Items.Add("Info geladen aus " & ofd.FileName) lstInfo.Items.Add("Titel: " & Info.Title) lstInfo.Items.Add("Interpret: " & Info.Artist) lstInfo.Items.Add("Album: " & Info.Album) lstInfo.Items.Add("Jahr: " & Info.Year) lstInfo.Items.Add("Genre: " & Info.Genre) End If End Sub End Class ' ############################################################################## ' ############################### MPEG4Class.vb ################################ ' ############################################################################## Class MPEG4Info Private FileName As String = "" ' Pfad zur Datei Private ILST() As Byte ' Byte Array für die Box ILST Private cDay() As Byte ' Byte Array für die Box ©day Private cArt() As Byte ' Byte Array für die Box ©art Private cAlb() As Byte ' Byte Array für die Box ©alb Private cNam() As Byte ' Byte Array für die Box ©nam Private cGen() As Byte ' Byte Array für die Box ©gen/gnre Sub New(ByVal File As String) FileName = File ' Auslesen der Box ILST ILST = ReadBox("ilst") End Sub ' Hier wird eine Box aus der Datei in ein Byte-Array eingelesen Private Function ReadBox(ByVal BoxName As String) As Byte() Dim ReturnBytes() As Byte Dim FileStram As New IO.FileStream(FileName, IO.FileMode.Open) Dim TempArr(3) As Byte Dim Pos As Long Dim TempString As String = "" Dim Len As Long ' Hier wird jede 4er-Bytekette im Filestream nach dem Boxnamen ' durchsucht. For i = 3 To FileStram.Length - 1 FileStram.Position = i - 3 FileStram.Read(TempArr, 0, 4) TempString = "" For j = 0 To TempArr.Count - 1 TempString &= Chr(TempArr(j)) Next ' Wenn der Boxname gefunden wurde, wird der Anfangspunkt der Kette ' im Array an die Startpositions-Variable übergeben. If TempString.ToUpper = BoxName.ToUpper Then Pos = i - 3 Exit For ElseIf i = FileStram.Length - 1 Then ' Wird die Box nicht gefundet, gebe Nothing zurück Return Nothing Exit Function End If Next ' Hier werden die Größenbytes der Box ausgelesen ... FileStram.Position = Pos - 4 FileStram.Read(TempArr, 0, 4) ' ... ausgerechnet und an die Längenvariable (Länge in Bytes) übergeben. Array.Reverse(TempArr) Len = BitConverter.ToInt32(TempArr, 0) ' Jetzt wird nur noch die Leseposition an die Stelle gesetzt, an der der ' Inhalt der Box beginnt und die Rückgabebytes auf die richtige Größe ' gebracht. FileStram.Position = Pos + 4 ReDim ReturnBytes(Len - 9) ' Hier wird der Inhalt der Box ausgelesen (Len-8, da die Größe 8 Bytes ' für größenangabe und Boxname enthält) FileStram.Read(ReturnBytes, 0, Len - 8) Return ReturnBytes End Function ' Hier wird eine Box aus einem Byte-Array in ein Byte-Array eingelesen ' (ähnlich ReadBox) Private Function ReadChildBox(ByVal ChildBoxName As String, _ ByVal ParentBoxData() As Byte) As Byte() Dim ReturnBytes() As Byte Dim Pos As Long Dim temparr(3) As Byte Dim TempString As String = "" Dim Len As Long If ParentBoxData Is Nothing Then Return Nothing End If For i = 3 To ParentBoxData.Length - 1 TempString = "" For j = 3 To 0 Step -1 TempString &= Chr(ParentBoxData(i - j)) Next If TempString.ToUpper = ChildBoxName.ToUpper Then Pos = i - 3 Exit For ElseIf i = ParentBoxData.Length - 1 Then Return Nothing Exit Function End If Next For i = Pos - 4 To Pos - 1 temparr(i - (Pos - 4)) = ParentBoxData(i) Next Array.Reverse(temparr) Len = BitConverter.ToInt32(temparr, 0) ReDim ReturnBytes(Len - 9) For i = Pos + 4 To Pos - 5 + Len ReturnBytes(i - (Pos + 4)) = ParentBoxData(i) Next Return ReturnBytes End Function 'Mit dieser Funktion wird der zur GenreID gehorende String ermittelt Private Function GetGenreString(ByVal GenreID As Integer) As String Dim AvailableGenres() As String = {"Blues", "Classic Rock", "Country", _ "Dance", "Disco", "Funk", "Grunge", "Hip - Hop", "Jazz", "Metal", _ "New Age", "Oldies", "Other", "Pop", "R&B", "Rap", "Reggae", _ "Rock", "Techno", "Industrial", "Alternative", "Ska", _ "Death Metal", "Pranks", "Soundtrack", "Euro -Techno", "Ambient", _ "Trip -Hop", "Vocal", "Jazz Funk", "Fusion", "Trance", _ "Classical", "Instrumental", "Acid", "House", "Game", _ "Sound Clip", "Gospel", "Noise", "AlternRock", "Bass", "Soul", _ "Punk", "Space", "Meditative", "Instrumental Pop", _ "Instrumental Rock", "Ethnic", "Gothic", "Darkwave", _ "Techno-Industrial", "Electronic", "Pop-Folk", "Eurodance", _ "Dream", "Southern Rock", "Comedy", "Cult", "Gangsta", "Top 40", _ "Christian Rap", "Pop/Funk", "Jungle", "Native American", _ "Cabaret", "New Wave", "Psychadelic", "Rave", "Showtunes", _ "Trailer", "Lo - Fi", "Tribal", "Acid Punk", "Acid Jazz", "Polka", _ "Retro", "Musical", "Rock & Roll", "Hard Rock", "Folk", _ "Folk/Rock", "National Folk", "Swing", "Bebob", "Latin", _ "Revival", "Celtic", "Bluegrass", "Avantgarde", "Gothic Rock", _ "Progressive Rock", "Psychedelic Rock", "Symphonic Rock", _ "Slow Rock", "Big Band", "Chorus", "Easy Listening", "Acoustic", _ "Humour", "Speech", "Chanson", "Opera", "Chamber Music", "Sonata", _ "Symphony", "Booty Bass", "Primus", "Porn Groove", "Satire", _ "Slow Jam", "Club", "Tango", "Samba", "Folklore", "Ballad", _ "Power Ballad", "Rhythmic Soul", "Freestyle", "Duet", "Punk Rock", _ "Drum Solo", "A Cappella", "Euro - House", "Dance Hall", "Goa", _ "Drum & Bass", "Club - House", "Hardcore", "Terror", "Indie", _ "BritPop", "Negerpunk", "Polsk Punk", "Beat", _ "Christian Gangsta Rap", "Heavy Metal", "Black Metal", _ "Crossover", "Contemporary Christian", "Christian Rock", _ "Merengue", "Salsa", "Thrash Metal", "Anime", "JPop", "Synthpop"} Try Return AvailableGenres(GenreID) Catch Return " " End Try End Function ReadOnly Property Year As String Get Dim RetString As String = "" cDay = ReadChildBox("©day", ILST) cDay = ReadChildBox("data", cDay) If cDay Is Nothing Then Return "" For i = 8 To cDay.Length - 1 If InStr("0123456789", Chr(cDay(i))) > 0 Then RetString &= Chr(cDay(i)) End If Next Return RetString End Get End Property ReadOnly Property Title As String Get Dim RetString As String = "" cNam = ReadChildBox("©nam", ILST) cNam = ReadChildBox("data", cNam) If cNam Is Nothing Then Return "" For i = 8 To cNam.Length - 1 RetString &= Chr(cNam(i)) Next Return RetString End Get End Property ReadOnly Property Album As String Get Dim RetString As String = "" cAlb = ReadChildBox("©alb", ILST) cAlb = ReadChildBox("data", cAlb) If cAlb Is Nothing Then Return "" For i = 8 To cAlb.Length - 1 RetString &= Chr(cAlb(i)) Next Return RetString End Get End Property ReadOnly Property Artist As String Get Dim RetString As String = "" cArt = ReadChildBox("©art", ILST) cArt = ReadChildBox("data", cArt) If cArt Is Nothing Then Return "" For i = 8 To cArt.Length - 1 RetString &= Chr(cArt(i)) Next Return RetString End Get End Property ReadOnly Property Genre As String Get Dim RetString As String = "" cGen = ReadChildBox("gnre", ILST) cGen = ReadChildBox("data", cGen) If cGen Is Nothing Then cGen = ReadChildBox("©gen", ILST) cGen = ReadChildBox("data", cGen) If cGen Is Nothing Then Return "" For i = 8 To cGen.Length - 1 RetString &= Chr(cGen(i)) Next Return RetString End If RetString = GetGenreString(cGen(cGen.Length - 1)) Return RetString End Get End Property End Class ' ############################################################################## ' ######################## WindowsApplication2.vbproj ########################## ' ############################################################################## <?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">x86</Platform> <ProductVersion>9.0.30729</ProductVersion> <SchemaVersion>2.0</SchemaVersion> <ProjectGuid>{F513AE9A-64B2-4F7B-943B-6E5F77CF496E}</ProjectGuid> <OutputType>WinExe</OutputType> <StartupObject>WindowsApplication1.My.MyApplication</StartupObject> <RootNamespace>WindowsApplication1</RootNamespace> <AssemblyName>WindowsApplication2</AssemblyName> <FileAlignment>512</FileAlignment> <MyType>WindowsForms</MyType> <TargetFrameworkVersion>v3.5</TargetFrameworkVersion> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' "> <PlatformTarget>x86</PlatformTarget> <DebugSymbols>True</DebugSymbols> <DebugType>full</DebugType> <DefineDebug>True</DefineDebug> <DefineTrace>True</DefineTrace> <OutputPath>bin\Debug\</OutputPath> <DocumentationFile>WindowsApplication2.xml</DocumentationFile> <NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' "> <PlatformTarget>x86</PlatformTarget> <DebugType>pdbonly</DebugType> <DefineDebug>False</DefineDebug> <DefineTrace>True</DefineTrace> <Optimize>True</Optimize> <OutputPath>bin\Release\</OutputPath> <DocumentationFile>WindowsApplication2.xml</DocumentationFile> <NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn> </PropertyGroup> <PropertyGroup> <OptionExplicit>On</OptionExplicit> </PropertyGroup> <PropertyGroup> <OptionCompare>Binary</OptionCompare> </PropertyGroup> <PropertyGroup> <OptionStrict>Off</OptionStrict> </PropertyGroup> <PropertyGroup> <OptionInfer>On</OptionInfer> </PropertyGroup> <ItemGroup> <Reference Include="System" /> <Reference Include="System.Data" /> <Reference Include="System.Deployment" /> <Reference Include="System.Drawing" /> <Reference Include="System.Windows.Forms" /> <Reference Include="System.Xml" /> <Reference Include="System.Core" /> <Reference Include="System.Xml.Linq" /> <Reference Include="System.Data.DataSetExtensions" /> </ItemGroup> <ItemGroup> <Import Include="Microsoft.VisualBasic" /> <Import Include="System" /> <Import Include="System.Collections" /> <Import Include="System.Collections.Generic" /> <Import Include="System.Data" /> <Import Include="System.Drawing" /> <Import Include="System.Diagnostics" /> <Import Include="System.Windows.Forms" /> <Import Include="System.Linq" /> <Import Include="System.Xml.Linq" /> </ItemGroup> <ItemGroup> <Compile Include="Form1.vb"> <SubType>Form</SubType> </Compile> <Compile Include="Form1.Designer.vb"> <DependentUpon>Form1.vb</DependentUpon> <SubType>Form</SubType> </Compile> <Compile Include="MPEG4Class.vb" /> <Compile Include="My Project\AssemblyInfo.vb" /> <Compile Include="My Project\Application.Designer.vb"> <AutoGen>True</AutoGen> <DependentUpon>Application.myapp</DependentUpon> </Compile> <Compile Include="My Project\Resources.Designer.vb"> <AutoGen>True</AutoGen> <DesignTime>True</DesignTime> <DependentUpon>Resources.resx</DependentUpon> </Compile> <Compile Include="My Project\Settings.Designer.vb"> <AutoGen>True</AutoGen> <DependentUpon>Settings.settings</DependentUpon> <DesignTimeSharedInput>True</DesignTimeSharedInput> </Compile> </ItemGroup> <ItemGroup> <EmbeddedResource Include="Form1.resx"> <DependentUpon>Form1.vb</DependentUpon> </EmbeddedResource> <EmbeddedResource Include="My Project\Resources.resx"> <Generator>VbMyResourcesResXFileCodeGenerator</Generator> <LastGenOutput>Resources.Designer.vb</LastGenOutput> <CustomToolNamespace>My.Resources</CustomToolNamespace> <SubType>Designer</SubType> </EmbeddedResource> </ItemGroup> <ItemGroup> <None Include="My Project\Application.myapp"> <Generator>MyApplicationCodeGenerator</Generator> <LastGenOutput>Application.Designer.vb</LastGenOutput> </None> <None Include="My Project\Settings.settings"> <Generator>SettingsSingleFileGenerator</Generator> <CustomToolNamespace>My</CustomToolNamespace> <LastGenOutput>Settings.Designer.vb</LastGenOutput> </None> </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" /> <!-- To modify your build process, add your task inside one Of the targets below And uncomment it. Other similar extension points exist, see Microsoft.Common.targets. <Target Name="BeforeBuild"> </Target> <Target Name="AfterBuild"> </Target> --> </Project>
Ihre Meinung
Falls Sie Fragen zu diesem Artikel haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.