إستخراج ال Tags من ملف MP3 - RaggiTech - 02-10-12
كاتب الموضوع : crazy-man
بسم الله الرحمن الرحيم
إستخراج ال Tags من ملف MP3
مقدمة :
درسنا اليوم ليس له علاقة فقط بالفيجوال بيسك دوت نت بل يمكن استغلاله في لغات برمجة اخرى، الدرس سيكون حول كيفية استخراجنا لمعلومات معينة من ملف من نوع MP3. هذا الأمر كنت بحاجة اليه عند عملي لبرنامج من نوع MP3 Player طبعا هناك مكتبات جاهزة تساعدك على ذلك و أيضا أداة ال WMP تمكنك من ذلك لكني كنت أريد أن أعمل الكود الخاص باستخراج تلك المعلومات لأغراض شخصية فمنها اني عندما أريد قراءة تلك المعلومات لا اريد استعمال اداة ال WMP لأنه من اجل استخراجها يجب ان تمرر اسم الملف اليها و ذلك معناه انها تفتح الملف بل و تقرأه لكي تعطيك تلك المعلومات، الحل كما قلت كان بايجاد أداة اخرى لعمل ذلك و فعلا توجد DLL's لعمل ذلك، لكن لما اخاطر باستعمال DLL قد يكون يستعمل طريقة تجعل برنامجي يستهلك ذاكرة اكثر من اللازم، لذا قررت ان اكتب الكود بنفسي خصوصا أني أعرف ان كل تلك المعلومات موجودة في الملف نفسه.
ID3
أول خطوة كانت كيف سأعرف أين توجد تلك المعلومات بالتحديد في الملف ؟؟؟
بعد بحيث لم يستغرف خمس دقائق وجدت ان هذه المعلومات TAGS تكون في آخر الملف و كل تلك المنطقة او كل تلك المعلومات تسمى ID3، بعد بحث آخر :d وجدت مقالة حولها في ال WikiPedia :
http://en.wikipedia.org/wiki/ID3
الذي يهمنا في هذا المقال أن المعلومات التي نريد موجودة في ال 128 بايت الأخيرة من ملف ال MP3 و هي مقسمة كالتالي :
[LTR]
0 -> 3 = "TAG"
3 -> 33 = Title
33 -> 63 = Artist Name
63 -> 93 = Album
93 -> 97 = Year
97 -> 127 = Comments
127 -> 128 = Genre
[/LTR]
طبعا نبدأ من بداية ال Structure و التي تحتل ال 128 بايت الأخير.
الآن بعد ان عرفنا أين نجد المعلومات و ال Structure الخاصة بها أظن انكم متشوفون لكتابة الكود الخاص بكم الذي يقرأ هذه المعلومات، جيد أتمنى ان يعتبر كل واحد منكم هذا كتمرين له و يحاول ان يكتب كود خاص به و لما لا لا يضعه لنا كرد هنا لعله يكون أحسن من طريقتي.
كتابة الكود
الآن من أجل عمل مرتب وجميل سنقوم بإنشاء Structure خاصة بنا وستكون على الشكل التالي :
كود :
Public Structure MP3TAG
Dim Title As String
Dim Artist As String
Dim Album As String
Dim Année As String
Dim Commentaires As String
Dim Genre As String
End Structure
الآن بعد انشاءنا لل Structure الخاصة بنا سوف نقوم بتسجيل طول كل معلومة ال Structure في ملف ال MP3، يعني اسم المغني يحتوي على كم Char ؟ لو عدت معي للأعلى ستجده يبتدأ من البايت 33 الى 63 يعني الطول المخصص له هو 30 بايت .
كود :
TAG = 3 Chars
Title = 30 Chars
Artist = 30 Chars
Album = 30 Chars
Year = 4 Chars
Comment = 30 Chars
Genre = 1 Char
الآن نقوم بتسجيل هذه المعلومات في برنامجنا على شكل Constants و سيكون تعريفها بالشكل التالي :
كود :
Const TitleChars As Integer = 30
Const ArtistChars As Integer = 30
Const AlbumChars As Integer = 30
Const YearChars As Integer = 4
Const CommentsChars As Integer = 30
Const GenreChars As Integer = 1
جميل، لحد الآن كل الأمور واضحة، الآن ننتقل للكود الذي سيمكننا من استخراج هذه المعلومات لأننا لحد الآن لم نعمل سوى بعض التعريفات، نقوم بعمل Function تعيد لنا متغير من نوع MP3TAG وهوال Structure التي عرفناها في الأول و سيكون تعريف الدلة كالتالي :
كود :
Private Function GetMp3Tags(ByVal MP3Path As String) As MP3TAG
End Function
داخل هذا ال Function سنبدأ العمل،
الخطوة الاولى هي فتح الملف بشكل Binary لذا فال StreamReader لن تنفعنا بل سنستعمل بدلها ال BinaryReader، نقوم بتعريفها بالشكل التالي :
كود :
Dim Mp3Binary As New BinaryReader(File.Open("D:\music\Kan Tayeb.mp3", FileMode.Open))
الملاحظة التي يمكن ملاحظتها هي انه لم نمرر للكلاس BinaryReader مسار ملف معين كما نفعل مع ال StreamReader بل استعملنا File.Open() ذلك ا نال BinaryReader يستقبل Stream و ال File.Open() يقوم بقراء ملف و يرجع FileStream و طبعنا حددنا نوع الفتح : FileMode.Open .
الآن لدينا محتوي ملف ال MP3 في الدالة Mp3Binary.
سنقوم الآن باعلان متغير من نوع Char و سيكون بالتحديد Array ذو حجم ال Structure الخاصة بال Tags في ملف ال MP3 و التعريف سيكون كالتالي :
كود :
Dim Tags(125) As Char
الآن سوف ... "هيهووووووووووووووو لحظة لحظة، في البداية قلت ا نال Tags تحتل ال 128 بايت الأخير من الملف لكنك أعلنت Array من 125 فقط ، أين الباقي؟؟؟"
ملاحظة في محلها لكن لو عدت معي الى البداية و ال Structure فسنجد ان كلمة "TAG" تحتل ال 3 Bytes الأولى من ال Structure و نحن فعليا لانحتاجها لذا سوف لن نأخذها في الحسبان لذا سنقرأ فقط 125 بايت، الآن تبين كل شئ، أليس كذلك J.
الخطوة التالية ستكون بأن نضع مؤشرنا على آخر 125 بايت في الملف و حن نعرف ان محتوى الملف الآن موجود في المتغير Mp3Binary و من أجر وضع المؤشر او بتعبير آخر من أجل أن ننتقل الى بداية آخر 125 بايت سيكون الكود كالتالي :
كود :
Mp3Binary.BaseStream.Position = Mp3Binary.BaseStream.Length – 125
الخاصية Position تمكننا من تحديد مكان البداية في Stream معينة و نحن حددنا له ان البداية ستكون طول ال Stream – 125 أظن ان هذه الجملةلا تحتاج لشرح أكثر.
الآن بعد ان انتقلنا الى بداية ال 125 بايت الأخيرة سوف نقوم بقراءتها ووضعها في ال Array التي اعلناها Tags() و الكود هو :
كود :
Mp3Binary.Read(Tags, 0, 125)
دالة Read هنا استقبلت ثلاث Params الأول ال Array التي توضع فيها المعلومات و هذه ال Array يمكن ان تكون من Char كما هو الحل في مثالنا أو Byte ثانيا نقطة بداية القراءة و هي 0 بالطبع و أخيرا كم عدد ال Bytesالتي يجب قراءتها.
الآن بعد ان وضعنا المعلومات التي نريدها في ال Array الخاص بنا فلم نعد نحتاج المتغير Mp3Binary لذا نقوم باغلاقه :
الآن التعامل مع Array من نوع Char سيكون اكثر تعقيدا لذا من اجل تفادي هذه التعقيدات نحوله الى String :
كود :
Dim TagToString As String = Convert.ToString(Tags)
الآن لدينا TagToString يحتوي على المعلومات الخاصة بملف ال MP3 ك String
الآن يسهل لدينا قراءة المعلومات و استخراج ما نريد.
كود الاستخراج من ال String سيكون كالتالي :
كود :
'Get Title
GetMp3Tags.Title = TagToString.Substring(0, TitleChars)
'Get Artist
GetMp3Tags.Artist = TagToString.Substring(TitleChars, ArtistChars)
'Get Album
GetMp3Tags.Album = TagToString.Substring(TitleChars + ArtistChars, AlbumChars)
'Get Year
GetMp3Tags.Year = TagToString.Substring(TitleChars + ArtistChars + AlbumChars, YearChars)
'Get Comments
GetMp3Tags.Comments = TagToString.Substring(TitleChars + ArtistChars + AlbumChars + YearChars, CommentsChars)
'Get Genre
GetMp3Tags.Genre = TagToString.Substring(TitleChars + ArtistChars + AlbumChars + YearChars + CommentsChars, GenreChars)
لنأخذ مثالا السطر الأول الذي يقوم باستخراج اسم المغني :
كود :
GetMp3Tags.Title = TagToString.Substring(0, TitleChars)
بكل بساطة أسندنا للمتغير Title والذي هو ضمن ال Structure المسماة GetMp3Tags اسم المقطع عن طريق استعمال SubString في ال String التي تحتوي على كل المعلومات و طبعا أخذنا اسم المقطع من الحرف الأول الى الحرف رقم 30 و هوالمحدد في ال Constant المسماة TitleChars،
بعدها سنأخذ اسم المغني و ستكون بدايته من الحرف 30 الى الحرف 60 :
كود :
GetMp3Tags.Artist = TagToString.Substring(TitleChars, ArtistChars)
بالنسبة لاسم ال Album ستكون بدايته هي بداية طول اسم المقطع + اسم المغني : TitleChars + ArtistChars و طوله طبعا هو قيمة الثابث AlbumChars :
كود :
GetMp3Tags.Album = TagToString.Substring(TitleChars + ArtistChars, AlbumChars)
نفس الأمر بالنسبة للمعلومات الأخرى دائما نبدأ بمجموع طول ال Tags السابقة وبهذا سنحصل على ما نريد.
الكود الكامل
الآن اليكم الكود كاملا و يمكنكم تجربته :
كود :
Imports System.IO
Public Class Form1
Public Structure MP3TAG
Dim Title As String
Dim Artist As String
Dim Album As String
Dim Year As String
Dim Comments As String
Dim Genre As String
End Structure
Const TitleChars As Integer = 30
Const ArtistChars As Integer = 30
Const AlbumChars As Integer = 30
Const YearChars As Integer = 4
Const CommentsChars As Integer = 30
Const GenreChars As Integer = 1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim FormattedString As String = ""
Dim MyMP3Tags As MP3TAG
MyMP3Tags = GetMp3Tags("d:\music\el-lilady.mp3")
With MyMP3Tags
MessageBox.Show("Title : " & .Title)
MessageBox.Show("Artist : " & .Artist)
MessageBox.Show("Album : " & .Album)
MessageBox.Show("Year : " & .Year)
MessageBox.Show("Comments : " & .Comments)
MessageBox.Show("Genre : " & .Genre)
End With
End Sub
Private Function GetMp3Tags(ByVal MP3Path As String) As MP3TAG
Dim Mp3Binary As New BinaryReader(File.Open("D:\music\Kan Tayeb.mp3", FileMode.Open))
Dim Tags(125) As Char
Mp3Binary.BaseStream.Position = Mp3Binary.BaseStream.Length - 125
Mp3Binary.Read(Tags, 0, 125)
Mp3Binary.Close()
Dim TagToString As String = Convert.ToString(Tags)
'Get Title
GetMp3Tags.Title = TagToString.Substring(0, TitleChars)
'Get Artist
GetMp3Tags.Artist = TagToString.Substring(TitleChars, ArtistChars)
'Get Album
GetMp3Tags.Album = TagToString.Substring(TitleChars + ArtistChars, AlbumChars)
'Get Year
GetMp3Tags.Year = TagToString.Substring(TitleChars + ArtistChars + AlbumChars, YearChars)
'Get Comments
GetMp3Tags.Comments = TagToString.Substring(TitleChars + ArtistChars + AlbumChars + YearChars, CommentsChars)
'Get Genre
GetMp3Tags.Genre = TagToString.Substring(TitleChars + ArtistChars + AlbumChars + YearChars + CommentsChars, GenreChars)
Return GetMp3Tags
End Function
End Class
|