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

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

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

Студворк — интернет-сервис помощи студентам
Всем доброго времени суток. Неожиданно мне потребовалось начать работу непосредственно с данными 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
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
02.04.2010, 22:11
Ответы с готовыми решениями:

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

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

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

6
 Аватар для Sergei
1513 / 780 / 103
Регистрация: 22.04.2008
Сообщений: 1,610
03.04.2010, 00:20
Вот класс в котором читаются данные об 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  [ТС]
Sergei, спасибо. Значит, если я правильно понял из этой
C#
1
byte[] buffer = new byte[128];
строки, размер тэга - 128 байт, значит, у меня получится
C#
1
short[] ID3 = new short[64];
Если я не совсем верно выразился в первом сообщении, поясню: информация о файле, а также содержимое тэгов и заголовков меня как таковое не интересует, мне нужно работать непосредственно с блоками данных.
Осталось найти размер "заголовка" и размер блока "данных".
0
 Аватар для Mikant
1322 / 995 / 127
Регистрация: 08.12.2009
Сообщений: 1,299
04.04.2010, 03:07
от файла к файлу размеры заголовков могут меняться (для неверующих - уверуйте). так вот, мой совет - рассчитывать размер вручную. по байтам... пока не выйдет. грубо говоря - пытайся менять параметр размера пока не считаешь удачно. ну и начни со 128, естессна)
0
3 / 3 / 0
Регистрация: 31.01.2010
Сообщений: 36
04.04.2010, 13:47  [ТС]
Хотя бы блок данных имеет постоянный размер? Или придется сначала считывать тэг, пока не обнаружится начало первого фрейма, потом считывать заголовок, пока он не считается, потом считывать данные, пока не найдется начало второго фрейма, и так до конца файла?..
0
3 / 3 / 0
Регистрация: 31.01.2010
Сообщений: 36
20.04.2010, 21:46  [ТС]
Появилось время, и я снова занялся этим вопросом. Если верить вот этому (и если я правильно все понял), заголовок фрейма имеет длину 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
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; ....
"
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
28.07.2010, 18:54
Помогаю со студенческими работами здесь

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

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Новые блоги и статьи
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Ниже машинный перевод статьи The Thinkpad X220 Tablet is the best budget school laptop period . Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы,. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru