Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.66/58: Рейтинг темы: голосов - 58, средняя оценка - 4.66
3 / 3 / 0
Регистрация: 31.01.2010
Сообщений: 36
1

Чтение и изменение данных в MP3 файле

02.04.2010, 22:11. Показов 12117. Ответов 6
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Всем доброго времени суток. Неожиданно мне потребовалось начать работу непосредственно с данными mp3 файла. Если я правильно понял структуру (а я ее так и не понял), файл можно представить следующим образом: *ID3-тэг*---*фрейм*---*фрейм*---*фрейм*... Сам фрейм при этом делится на *заголовок* и *данные* (нечто подобное я прочитал в википедии, поправьте, если я не прав). Вот с этими *данными* мне и нужно работать.

На данный момент основная проблема в том, что я не знаю размер "тэга", "заголовка" и "данных". (надеюсь, они имеют фиксированный размер).

И заодно еще один вопрос: можно ли создать в конце файла свой фрейм, если скопировать заголовок последнего фрейма в файле и добавить свои данные?..

Привожу существующий на данный момент код (на работоспособность не проверялся из-за указанных выше проблем с размерами)
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
    class MP3File
    {
        short[] ID3 = new short[1 /* Здесь должен быть размер тега */];
        short[] header = new short[1 /* Здесь должен быть размер заголовка */];
        short[] data = new short[1 /* Здесь должен быть размер данных */];
        List<short[]> headerList = new List<short[]>();
        List<short[]> dataList = new List<short[]>();
 
        public MP3File(string fileName)
        {
            this.ReadFile(fileName);
        }
 
        // Чтение файла
        private void ReadFile(string fileName)
        {
            BinaryReader reader = new BinaryReader(new FileStream(fileName, FileMode.Open));
            FileInfo fi = new FileInfo(fileName);
            headerList.Clear();
            dataList.Clear();
            long size = fi.Length / 2; // Определить размер в байтах, т.к. short занимает 2 байта, делим размер на 2
            int lenghtCounter = 0;
            for (int i = 0; i < ID3.Length && lenghtCounter < size; i++)
            {
                ID3[i] = reader.ReadInt16();
                lenghtCounter++;
            }
 
            while (lenghtCounter < size)
            {
                for (int i = 0; i < header.Length; i++)
                {
                    header[i] = reader.ReadInt16();
                    lenghtCounter++;
                }
                for (int i = 0; i < data.Length; i++)
                {
                    data[i] = reader.ReadInt16();
                    lenghtCounter++;
                }
                headerList.Add(header);
                dataList.Add(data);
            }
 
        }
 
        // Запись получившегося "нечто" в файл
        private void WriteFile(string fileName)
        {
            BinaryWriter file = new BinaryWriter(new FileStream(fileName, FileMode.Create));
            for (int i = 0; i < ID3.Length; i++)
            {
                file.Write(ID3[i]);
            }
            for (int i = 0; i < headerList.Count; i++)
            {
                for (int j = 0; j < headerList[i].Length; j++)
                {
                    file.Write(headerList[i][j]);
                }
                for (int j = 0; j < dataList[i].Length; j++)
                {
                    file.Write(dataList[i][j]);
                }
            }
            file.Close();
        }
 
    }
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
02.04.2010, 22:11
Ответы с готовыми решениями:

Добавление, изменение данных в XML файле
Здравствуйте! Не могу понять как: 1. можно добавлять данные в xml без перетирания существующих в...

Чтение MP3-тегов
Доброго времени суток. Помогите пожалуйста разобраться. Выбирается музыкальный файл, мр3 например....

Чтение файла mp3 из Properties.Resources
Я использую сторонний класс для воспроизведения mp3, а сам файл mp3 находится в...

Сохранение ID3v2 тегов в mp3 файле
Доброго времени суток. Ребята. Подскажите как можно сохранить теги в mp3 файле. Уже дня три...

6
1512 / 779 / 103
Регистрация: 22.04.2008
Сообщений: 1,610
03.04.2010, 00:20 2
Вот класс в котором читаются данные об MP3 файле.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace MP3Collection
{
    public class MP3File
    {
        public MP3File(string path, string defaultAlbumArt)
        {
            HasTag = false;
 
            // make sure the file exists
            if (File.Exists(path))
            {
                try
                {
                    // set the FileName property
                    FileName = path;
 
                    // open the file
                    FileStream fs;
                    fs = new FileStream(path, FileMode.Open);
 
                    // read the tag
                    byte[] buffer = new byte[128];
                    fs.Seek(-128, SeekOrigin.End);
                    fs.Read(buffer, 0, 128);
                    fs.Close();
 
                    // convert the tag buffer into a string
                    UTF8Encoding encoder = new UTF8Encoding();
                    string tag = encoder.GetString(buffer);
 
                    // if there is a ID3 v1 tag, then read it (we can know by looking at the first 3 bytes for the word TAG)
                    if (tag.Substring(0, 3) == "TAG")
                    {
                        HasTag = true;
 
                        Title = RemoveWhiteSpace(tag.Substring(3, 30));
                        Artist = RemoveWhiteSpace(tag.Substring(33, 30));
                        Album = RemoveWhiteSpace(tag.Substring(63, 30));
                        Year = RemoveWhiteSpace(tag.Substring(93, 4));
                        Comment = RemoveWhiteSpace(tag.Substring(97, 28));
 
                        if (tag[125] == 0)
                            Track = (int)buffer[126];
                        else
                            Track = 0;
                    }
 
                    // look for album art
                    string[] artPaths = Directory.GetFiles(Path.GetDirectoryName(path), "AlbumArt_*Large.jpg");
 
                    if (artPaths.Length == 0) artPaths = Directory.GetFiles(Path.GetDirectoryName(path), "AlbumArt*.jpg");
                    if (artPaths.Length == 0) artPaths = Directory.GetFiles(Path.GetDirectoryName(path), "Album*.jpg");
                    if (artPaths.Length == 0) artPaths = Directory.GetFiles(Path.GetDirectoryName(path), "*.jpg");
 
                    if (artPaths.Length > 0)
                    {
                        AlbumArt = artPaths[0];
                    }
                    else
                    {
                        AlbumArt = defaultAlbumArt;
                    }
 
                }
                catch { }
            }
        }
 
        private string RemoveWhiteSpace(string s)
        {
            string newstring = "";
 
            foreach (char c in s)
            {
                if (char.IsLetterOrDigit(c) || char.IsPunctuation(c) || char.IsSeparator(c))
                {
                    newstring += c;
                }
            }
 
            return newstring.Trim();
        }
 
        private bool _HasTag;
        public bool HasTag
        {
            get { return _HasTag; }
            set { _HasTag = value; }
        }
 
 
        private string _FileName;
        public string FileName
        {
            get { return _FileName; }
            set { _FileName = value; }
        }
 
        private string _AlbumArtPath;
        public string AlbumArt
        {
            get { return _AlbumArtPath; }
            set { _AlbumArtPath = value; }
        }
 
        private string _Title;
        public string Title
        {
            get { return _Title; }
            set { _Title = value; }
        }
 
        private string _Artist;
        public string Artist
        {
            get { return _Artist; }
            set { _Artist = value; }
        }
 
        private string _Album;
        public string Album
        {
            get { return _Album; }
            set { _Album = value; }
        }
 
        private string _Year;
        public string Year
        {
            get { return _Year; }
            set { _Year = value; }
        }
 
        private string _Comment;
        public string Comment
        {
            get { return _Comment; }
            set { _Comment = value; }
        }
 
        private int _Track;
        public int Track
        {
            get { return _Track; }
            set { _Track = value; }
        }
    }
}
1
3 / 3 / 0
Регистрация: 31.01.2010
Сообщений: 36
03.04.2010, 08:55  [ТС] 3
Sergei, спасибо. Значит, если я правильно понял из этой
C#
1
byte[] buffer = new byte[128];
строки, размер тэга - 128 байт, значит, у меня получится
C#
1
short[] ID3 = new short[64];
Если я не совсем верно выразился в первом сообщении, поясню: информация о файле, а также содержимое тэгов и заголовков меня как таковое не интересует, мне нужно работать непосредственно с блоками данных.
Осталось найти размер "заголовка" и размер блока "данных".
0
1319 / 992 / 127
Регистрация: 08.12.2009
Сообщений: 1,299
04.04.2010, 03:07 4
от файла к файлу размеры заголовков могут меняться (для неверующих - уверуйте). так вот, мой совет - рассчитывать размер вручную. по байтам... пока не выйдет. грубо говоря - пытайся менять параметр размера пока не считаешь удачно. ну и начни со 128, естессна)
0
3 / 3 / 0
Регистрация: 31.01.2010
Сообщений: 36
04.04.2010, 13:47  [ТС] 5
Хотя бы блок данных имеет постоянный размер? Или придется сначала считывать тэг, пока не обнаружится начало первого фрейма, потом считывать заголовок, пока он не считается, потом считывать данные, пока не найдется начало второго фрейма, и так до конца файла?..
0
3 / 3 / 0
Регистрация: 31.01.2010
Сообщений: 36
20.04.2010, 21:46  [ТС] 6
Появилось время, и я снова занялся этим вопросом. Если верить вот этому (и если я правильно все понял), заголовок фрейма имеет длину 32 бита, а длина фрейма изменяется.
Формулы длины фрейма:
For Layer I files us this formula:

FrameLengthInBytes = (12 * BitRate / SampleRate + Padding) * 4

For Layer II & III files use this formula:

FrameLengthInBytes = 144 * BitRate / SampleRate + Padding
Вот только входит ли длина заголовка в длину фрейма, или фрейм идет после заголовка?..

Далее, ID3v1 находится в конце файла, его можно считать без проблем. А вот как прочитать ID3v2 я пока не понимаю, сейчас разбираюсь с этим исходником, но 99,99% его функционала мне не нужны. Может, кто-нибудь знает способ попроще?..

Добавлено через 14 часов 9 минут
Нашел еще один исходник для чтения ID3v2, сейчас разбираюсь (английский не знаю )
0
a_book
28.07.2010, 18:54 7
Sergei, Не поделитесь ли архивом с полной версией проекта MP3?

P.s:
"
C#
1
2
3
4
5
6
using System;
...
using System.IO;
namespace MP3Collection
{
    public class MP3File
... "

"
C#
1
2
3
4
5
6
7
8
9
10
using System;
...
using System.Text;
 
namespace MP3Collection
{
    public class MP3Collection : ObservableCollection<MP3File>, ISupportInitialize
    {
        private string _directoryPath;
        private bool _expendFolders; ....
"
28.07.2010, 18:54
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
28.07.2010, 18:54
Помогаю со студенческими работами здесь

Чтение ID3v2 в MP3 тегов без использования сторонних библиотек
Здравствуйте господа. Я столкнулся с проблемой при чтении ID3v2 тегов: в случае использования...

Чтение mp3-тегов в консольном приложении
Всем привет.Требуется небольшая помощь.Есть консолька которая запускается из командной строки и...

Чтение MP3-тегов: исправить код
Добрый день программисты! Есть вот такой кусочек кода namespace ConsoleApplication1 { ...

Сохранение и чтение данных в файле
У меня такой вопрос, как сделать так чтобы информация сохранялась в 1 текстовый файл и считывалась,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru