zoukankan      html  css  js  c++  java
  • MP3 信息读取

    MP3 信息读取

    运行环境:Window7 64bit,.NetFramework4.61,C# 7.0; 编者:乌龙哈里 2017-03-13


    参考:

    章节:

    • Mp3 文件结构概述
    • ID3V1 标记
    • ID3V2 标记
    • Mp3 数据头

    正文:

    一、Mp3文件概述

    最近买了个车载mp3播放器,需要下载mp3文件。下载了一堆后发现,很多网上的mp3音质不怎么好,如何来分辨呢。只好研究mp3的文件格式。

    从 wiki 上获知,mp3的文件基本有3部分组成:

    ID3v2x 标记
    MP3 音乐数据
    ID3v1 标记

    二、ID3v1 标记

    Id3v1标记位于 mp3 文件末尾的128 byte,结构如下:

    起始长度内容
    0 3 标记 Tag
    3 30 歌曲名 SongTitle
    33 30 表演者 Artist
    63 30 专辑 Album
    93 4 年份 Year
    97 30 备注 Comment
    127 1 歌曲类型 Genre

    1、标记:
    标记是以“TAG”3个大写字母为标记。

    2、内容:
    歌名、表演者、专辑、年份、备注都是以ASCII编码的字符

    3、类型:
    类型是1位数字,具体见 8.1. Appendix A - Genre List from ID3v1

    三、ID3v2 标记

    Id3v2 标记是放在mp3文件头,具体长度要通过计算才知道。结构分为两部分: Id3v2 Tag Header,Id3v2 Frame

    1、Id3v2Tag Header:
    这个头部放在mp3文件最前面,长 10byte,具体结构:

    起始长度内容
    0 3 标志 Tag
    3 2 版本 version
    5 1 Flag
    6 4 Frame长度

    标志是以“ID3”3个字符为标记;
    版本为2个 byte的数字,前面1byte 一般为 03,表示id3v2.3版本,后面1byte的为小版本,一般为0;
    Flag具体看ID3 tag version 2.3.0 ,一般为0;
    Frame长度是指紧接着 10byte 长的头部数据后的id3v2tag Frame的长度,是4个byte的数字,每byte的二进制位中前面都为0,0xxxxxxxx,具体长度的算法用位计算为:

    byte[] data=new byte[10];
    //....(从文件中读取前10byte数据放入 data)
    int FrameLength=data[6] << 21 | data[7] << 14 | data[8] << 7 | data[9]

    2、Tag Frame帧数据。
    Tag Frame 是一个以10byte为头,后面不定长的数据帧,结构如下:

    部分相对起始长度内容
    0 4 标记 Frame ID
    5 4 内容长度
    8 2 Flages
    内容 10 不定长 内容

    FrameID 为4个字符,具体参考ID3 tag version 2.3.0
    内容长度为 4 byte的数据,和上面的不同,它的二进制是全8位的,但和 C# 存储int32不同,它前面的byte表示高位,具体计算如下:

    byte[] data=new byte[10];
    //....(读取10byte Frame头部数据放入 data)
    int ContentLength=data[6] << 24 | data[7] << 16 | data[8] << 8 | data[9]

    (1)FrameId 以“T”开头的,除了“TXXX”,都是字符串信息,具体结构为:

    起始长度内容
    0 1 Text encoding
    1 Frame头计算出来的长度 内容

    内容以 FF FE 开头的为 C# 里面的 Encoding.Unicode ,以 FE FF 开头的为 C# 里面的 Encoding.BigEndianUnicode;除上外是以 Ascii 编码的。

    (2)FrameId为“APIC”的是放 jpeg 或 png 格式的图像数据,具体见4.15. Attached picture

    四、mp3音乐数据头

    读完 id3v2tag 的数据后,紧接着下来就是具体的音乐数据。但是并不一定紧挨着 FrameLength+10,不知道是这些mp3录制的时候的软件问题还是其他我还没发现的问题,用ultraEdit看,音乐数据和 id3tag 中间还有一部分全都是0的数据,所以读完 id3v2tag 后还要一个字节一个字节的寻找 FF开头的数据。我只是需要知道mp3的音乐信息,所以只要在id3v2tag 后找到 FF 开头的4个字节的数据就成了。这4个字节全部都是用位来表示信息,具体见 MPEG Audio Layer I/II/III frame header

    写了一个程序读写,尚未完全完成,效果如下图:

    附练手全程序:

    <Window x:Class="Mp3信息.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:Mp3信息"
            mc:Ignorable="d"
            Title="Mp3信息1.0  [乌龙哈里2017-03-13]" Height="650" Width="500">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="32"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <Grid Grid.Row="0">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="1*"/>
                    <ColumnDefinition Width="6*"/>
                </Grid.ColumnDefinitions>
                <Button Name="btnFile" Content="Mp3" Margin="3" Grid.Column="0" Click="btnFile_Click"/>
                <TextBox Name="txtFile" Grid.Column="1" Margin="3"/>
            </Grid>
            
            <TabControl Grid.Row="1">
                
                <TabItem Header="单曲">
                    <Grid >
                        <Grid.RowDefinitions>
                            <RowDefinition Height="*"/>
                            <RowDefinition Height="200"/>
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="200"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <DataGrid Name="dgShow" AutoGenerateColumns="False" SelectionUnit="CellOrRowHeader" Grid.Row="0" Grid.ColumnSpan="2">
                            <DataGrid.Columns>
                                <DataGridTextColumn Header="名称"  Binding="{Binding [0]}"/>
                                <DataGridTextColumn Header="ID3V2"  Binding="{Binding [1]}"/>
                                <DataGridTextColumn Header="ID3V1"  Binding="{Binding [2]}"/>
                            </DataGrid.Columns>
                        </DataGrid>
                        <Image Name="imgCover" Grid.Row="1" Grid.Column="0"/>
                        <Grid Grid.Row="1" Grid.Column="1">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="1*"/>
                                <ColumnDefinition Width="1*"/>
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="32"/>
                                <RowDefinition Height="*"/>
                            </Grid.RowDefinitions>
                            <Button Name="btnModify2" Content="修改 ID3V2" FontSize="18" Foreground="Navy" Grid.Row="1" Grid.Column="0" Margin="10" Click="btnModify2_Click"/>
                            <ComboBox Name="cmbGenre" Margin="10,5,10,2" Grid.Row="0" Grid.Column="1" SelectionChanged="cmbGenre_SelectionChanged"/>
                            <Button Name="btnModify1" Content="修改 ID3V1" FontSize="18" Grid.Row="1" Grid.Column="1" Margin="10" Click="btnModify1_Click"/>
                        </Grid>
                    </Grid>
                </TabItem>
                <TabItem Header="批量">
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="40"/>
                            <RowDefinition Height="*"/>
                        </Grid.RowDefinitions>
                        <Button Name="btnMuti" Content="批量读取" FontSize="16" Margin="5" Grid.Row="0"/>
                        <DataGrid Name="dgMuti" Grid.Row="1">
                            <DataGrid.Columns>
                                <DataGridTextColumn Header="文件"  Binding="{Binding [0]}"/>
                                <DataGridTextColumn Header="Mpeg"  Binding="{Binding [1]}"/>
                                <DataGridTextColumn Header="Layer"  Binding="{Binding [2]}"/>
                                <DataGridTextColumn Header="波特率"  Binding="{Binding [3]}"/>
                                <DataGridTextColumn Header="频率"  Binding="{Binding [4]}"/>
                                <DataGridTextColumn Header="声道"  Binding="{Binding [5]}"/>
                            </DataGrid.Columns>
                        </DataGrid>
                    </Grid>
                </TabItem>
            </TabControl>
        </Grid>
    </Window>
    View Code
    using System.Windows;
    using System.Windows.Controls;
    
    namespace Mp3信息
    {
        /// <summary>
        /// MainWindow.xaml 的交互逻辑
        /// </summary>
        public partial class MainWindow : Window
        {
            private string filteStr = "MP3 File|*.mp3|All File|*.*";
            private Mp3FileInfo mp3 = new Mp3FileInfo();
    
            public MainWindow()
            {
                InitializeComponent();
     
                dgShow.ItemsSource = mp3.Mp3Infos;
                cmbGenre.ItemsSource = mp3.Genres;
            }
            //---打开文件按钮
            private void btnFile_Click(object sender, RoutedEventArgs e)
            {
                string filename = GetOpenFilePath(filteStr);
                if (!string.IsNullOrEmpty(filename))
                {
                    txtFile.Text = filename;
                    dgShow.BeginEdit();
                    mp3.GetMp3Info(filename);
                    dgShow.EndInit();
                    if (mp3.CoverExist)
                    {
                        imgCover.Source = mp3.CoverPicture;
                    }
                    cmbGenre.SelectedIndex =int.Parse(mp3.Mp3Infos[5][2]);
                }
            }
           //---取得打开文件名
            private string GetOpenFilePath(string filterstr)
            {
                var dlg = new Microsoft.Win32.OpenFileDialog();
                dlg.Filter = filterstr;
                if (dlg.ShowDialog() == true)
                {
                    return dlg.FileName;
                }
                return "";
            }
            //---取得保存文件名
            private string GetSaveFilePath(string filterstr)
            {
                var dlg = new Microsoft.Win32.SaveFileDialog();
                //dlg.FileName = Path.GetFileNameWithoutExtension(memoFilePath);
                //dlg.DefaultExt = ".memo";
                dlg.Filter = filterstr;
                if (dlg.ShowDialog() == true)
                {
                    return dlg.FileName;
                }
                return "";
            }
    
            private void btnModify1_Click(object sender, RoutedEventArgs e)
            {
                    mp3.SetV1TagInfo(txtFile.Text);
            }
    
            private void cmbGenre_SelectionChanged(object sender, SelectionChangedEventArgs e)
            {
                dgShow.BeginInit();
                mp3.Mp3Infos[5][2] = cmbGenre.SelectedIndex.ToString();
                dgShow.EndInit();
            }
    
            private void btnModify2_Click(object sender, RoutedEventArgs e)
            {
                mp3.SetV2TagInfo(txtFile.Text);
            }
        }
    }
    View Code
    /******************************************************
     * MP3 音乐格式文件信息读取
     * 作者:乌龙哈里
     * 最后修改:2017-03-07
     * 参考:
     * 1、http://id3.org/d3v2.3.0
     * 2、http://blog.csdn.net/alin0725/article/details/1876253
     * 3、http://www.mpgedit.org/mpgedit/mpeg%5Fformat/MP3Format.html
     * 4、https://en.wikipedia.org/wiki/MP3
     ******************************************************/
    namespace Mp3信息
    {
        using System;
        using System.Collections.Generic;
        using System.Collections.ObjectModel;
        using System.IO;
        using System.Linq;
        using System.Reflection;
        using System.Text;
        using System.Threading.Tasks;
        using System.Windows.Media.Imaging;
    
    
        /// <summary>
        /// 主程序class
        /// </summary>
        class Mp3FileInfo
        {
            public string Mp3File { get; set; }
            //注意:要先建立一个放置音乐类型的txt文件
            public string GenreFile { get; set; } = @".mp3genre.txt";
    
            private int V1TagLength = 128;
            private int V2TagHeaderLength = 10;
            private string V1TagSymbol = "TAG";
            private string V2TagSymbol = "ID3";
            private string V2TagPictureId = "APIC";
            private int[] V1TagStruct = new int[14];//id3v1数据结构
            public string[] Genres;//音乐类型
    
            private string[] Mpeg;
            private string[] Layer;
            private string[] Bitrate;
            private string[] Hz;
            private string[] Channel;
    
            public ObservableCollection<string[]> Mp3Infos = new ObservableCollection<string[]>();
            public BitmapSource CoverPicture;
            public bool CoverExist = false;
            public int  NewCoverType = -1;
            private string[] V2TagFrameIds;
    
            //---初始化
            public Mp3FileInfo()
            {
                FillV1TagStruct();
                FillGenres();
                FillHeader();
                FillV2TagFrameIds();
            }
            //---批量取得信息(以后再写)
            public void GetMutiInfo(string path)
            {
    
            }
            //---写id3v2信息(有问题,写成功后用windows的播放器播放正常,图片也出现,但歌名等信息不出现)
            public void SetV2TagInfo(string path)
            {
    
                List<(string frameid, string content)> list = new List<(string, string)>();
                int n = 0;
                for (int i = 0; i < V2TagFrameIds.Length; i++)
                {
                    if (Mp3Infos[i][1].Length > 0)
                    {
                        list.Add((V2TagFrameIds[i],Mp3Infos[i][1]));
                        n += Mp3Infos[i][1].Length*2 + 3 + 10;
                    }
                }
                n += 10;
                byte[] _data = new byte[n];
                Encoding.Default.GetBytes(V2TagSymbol,0,3,_data,0);
                _data[3] = 3;
                int m = 10;
                foreach (var info in list)
                {
                    Encoding.Default.GetBytes(info.frameid,0,4,_data,m);
                    int k = info.content.Length*2 + 3;
                    _data[m + 4] = (byte)(k >>24);
                    _data[m + 5] = (byte)(k >>16);
                    _data[m + 6] = (byte)(k >> 8);
                    _data[m + 7] = (byte)k;
                    _data[m + 10] = 1;
                    _data[m + 11] = 255;
                    _data[m + 12] = 254;
                    Encoding.Unicode.GetBytes(info.content,0,info.content.Length,_data,m+13);
                    m =m+ k + 10;
                }
                m = n;
                if (NewCoverType > -1)
                {
    
                }
                else
                {
                    using (FileStream fs=File.OpenRead(path))
                    {
                        int _framelength = GetV2TagFrameLength(fs);
                        byte[] _framedata = new byte[_framelength];
                        fs.Read(_framedata, 0, _framedata.Length);
                        var _frames = GetV2TagFrameInfo(_framedata);
                        int _index = -1;
                        for (int i = 0; i < _frames.Count; i++)
                        {
                            if (string.Compare(_frames[i].frameid, V2TagPictureId) == 0)
                            {
                                n += _frames[i].length;
                                _index = i;
                                break;
                            }
                        }
                        n = n+ (int)fs.Length - _framelength - 10;
                        Array.Resize(ref _data, n);
                        int k = m;
                        if (_index > -1)
                        {
                            k = m + _frames[_index].length;
                            for(int i=0; i < _frames[_index].length; i++)
                            {
                               _data[m++]=_framedata[_frames[_index].start + i];
                            }   
                        }
                        _data[6] = (byte)((k >> 21)&0x7F);
                        _data[7] = (byte)((k >> 14) & 0x7F);
                        _data[8] = (byte)((k >> 7) & 0x7F);
                        _data[9] = (byte)(k & 0x7F);
    
                        fs.Read(_data, m, (int)fs.Length - _framelength - 10);
    
                    }
                }
                using (FileStream fs = File.Create(@"d:	est123.mp3"))
                {
                    fs.Write(_data, 0, _data.Length);
                }
    
            }
            //---写id3v1信息
            public void SetV1TagInfo(string path)
            {
                byte[] info = new byte[V1TagLength];
                info[0] = (byte)V1TagSymbol[0];
                info[1] = (byte)V1TagSymbol[1];
                info[2] = (byte)V1TagSymbol[2];
                for (int i = 0; i < 5; i++)
                {
                    string s = Mp3Infos[i][2].Trim();
                    Encoding.Default.GetBytes(s, 0, s.Length, info, V1TagStruct[(i + 1) * 2]);
                }
                info[V1TagStruct[12]] = byte.Parse(Mp3Infos[5][2]);
                using (FileStream fs = File.OpenWrite(path))
                {
                    fs.Seek(-info.Length, SeekOrigin.End);
                    fs.Write(info, 0, info.Length);
                }
            }
            //---读取mp3信息
            public void GetMp3Info(string path)
            {
                Mp3Infos.Clear();
                FillMp3Infos();
                using (FileStream fs = File.OpenRead(path))
                {
                    GetV1TagInfo(fs);
                    int _v2TagLength = GetV2TagFrameLength(fs);
                    if (_v2TagLength > 0)
                    {
                        GetV2TagInfo(fs, _v2TagLength);
                        int[] _index = new int[5];
                        int n = V2TagFrameIds.Length;
                        GetMp3HeaderInfo(_index, fs, _v2TagLength);
                        Mp3Infos[n][1] = Mpeg[_index[0]];
                        Mp3Infos[n+1][1] = Layer[_index[1]];
                        Mp3Infos[n+2][1] = Bitrate[_index[2]];
                        Mp3Infos[n+3][1] = Hz[_index[3]];
                        Mp3Infos[n+4][1] = Channel[_index[4]];
                    }
                }
            }
            //---读取mp3 header 信息
            private void GetMp3HeaderInfo(int[] Index, FileStream fs, int Id3v2TagFrameLength)
            {
                byte[] _header = new byte[3];
                Func<bool> FindHeader = () =>
                 {
                     int m = 1024;
                     int start = 0;
                     fs.Seek(Id3v2TagFrameLength + V2TagHeaderLength, SeekOrigin.Begin);
                     while (start++ < m)
                     {
                         if (fs.ReadByte() == 255)
                         {
                             fs.Read(_header, 0, 3);
                             return true;
                         }
                     }
                     return false;
    
                 };
                if (FindHeader())
                {
                    int _mpegIndex = (_header[0] >> 3) & Convert.ToByte("00000011", 2);
                    int _layerIndex = (_header[0] >> 1) & Convert.ToByte("00000011", 2);
                    int _bitrateIndex = _header[1] >> 4;
                    int _hzIndex = (_header[1] >> 2) & Convert.ToByte("00000011", 2);
                    int _channelIndex = _header[2] >> 6;
                    int _bitrateIndexStep = _mpegIndex * 48 + (_layerIndex - 1) * 16;
                    int _hzIndexStep = _mpegIndex * 4;
                    Index[0] = _mpegIndex;
                    Index[1] = _layerIndex;
                    Index[2] = _bitrateIndex + _bitrateIndexStep;
                    Index[3] = _hzIndex + _hzIndexStep;
                    Index[4] = _channelIndex;
                }
            }
            //---读取id3v2标记内容
            private void GetV2TagInfo(FileStream fs, int Length)
            {
                CoverExist = false;
                NewCoverType = -1;
                byte[] _v2tag = new byte[Length];
                fs.Seek(V2TagHeaderLength, SeekOrigin.Begin);
                fs.Read(_v2tag, 0, _v2tag.Length);
                var _frames = GetV2TagFrameInfo(_v2tag);
                foreach (var _frame in _frames)
                {
                    int _index = GetV2TagFrameIdIndex(_frame.frameid);
                    if (_index > -1)
                    {
                        Mp3Infos[_index][1] = GetFrameStrContent(_v2tag, _frame.start + 10, _frame.length - 10);
                    }
                    else
                    {
                        //如果是APIC,则读取图片
                        if (string.Compare(_frame.frameid, V2TagPictureId) == 0)
                        {
                            GetImage(_v2tag, _frame.start + 10, _frame.length - 10);
                        }
                    }
    
                }
            }
            //---读取图片
            private void GetImage(byte[] source, int start, int contentLength)
            {
                //寻找图片位置
                Func<byte[], (bool found, int startpos)> FindImage = symbol =>
                    {
                        int n = start;
                        int m = start + 30;
                        while (n < m)
                        {
                            if (n > m - symbol.Length)
                            {
                                return (false, -1);
                            }
                            if (source[n] == symbol[0] && source[n + 1] == symbol[1] && source[n + 2] == symbol[2])
                            {
                                return (true, n);
                            }
                            n++;
                        }
                        return (false, -1);
                    };
                //取得图片信息
                Func<(int ImageKind, int startpos)> GetImageInfo = () =>
                 {
                     byte[] _imghead = new byte[3];
                     //jpeg header
                     _imghead[0] = 0xFF;
                     _imghead[1] = 0xD8;
                     _imghead[2] = 0xFF;
                     var t = FindImage(_imghead);
                     if (t.found)
                     {
                         return (0, t.startpos);
                     }
                     //png header
                     _imghead[0] = 0x89;
                     _imghead[1] = 0x50;
                     _imghead[2] = 0x4E;
                     t = FindImage(_imghead);
                     if (t.found)
                     {
                         return (1, t.startpos);
                     }
                     return (-1, -1);
                 };
                //读取图片
                var p = GetImageInfo();
                if (p.ImageKind > -1)
                {
                    CoverExist = true;
                    MemoryStream ms = new MemoryStream();
                    ms.Write(source, p.startpos, contentLength + start - 10 - p.startpos);
                    ms.Seek(0, SeekOrigin.Begin);
                    switch (p.ImageKind)
                    {
                        case 0:
                            JpegBitmapDecoder jpeg = new JpegBitmapDecoder(ms, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
                            CoverPicture = jpeg.Frames[0];
                            break;
                        case 1:
                            PngBitmapDecoder png = new PngBitmapDecoder(ms, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
                            CoverPicture = png.Frames[0];
                            break;
                    }
                }
    
            }
            //---读取v2 Frame string内容
            private string GetFrameStrContent(byte[] source, int start, int length)
            {
                if (source[start + 1] == 255 && source[start + 2] == 254)
                {
                    return Encoding.Unicode.GetString(source, start + 3, length - 3);
                }
                if (source[start + 1] == 254 && source[start + 2] == 255)
                {
                    return Encoding.BigEndianUnicode.GetString(source, start + 3, length - 3);
                }
    
                return Encoding.Default.GetString(source, start + 1, length - 1);
            }
            //---根据V2TagFrameIds,找出FrameId在mp3infos的index
            private int GetV2TagFrameIdIndex(string FrameId)
            {
                for (int i = 0; i < V2TagFrameIds.Length; i++)
                {
                    if (string.Compare(V2TagFrameIds[i], FrameId) == 0)
                    {
                        return i;
                    }
                }
                return -1;
            }
            //---读取v2tag frame 信息
            private List<(string frameid, int start, int length)> GetV2TagFrameInfo(byte[] FrameData)
            {
                int n = 0;
                List<(string frameid, int length, int start)> _frames = new List<(string frameid, int length, int start)>();
                while (n < FrameData.Length - 10)
                {
                    int _length = FrameData[n + 4] << 24 | FrameData[n + 5] << 16 | FrameData[n + 6] << 8 | FrameData[n + 7];
                    if (_length > 0)
                    {
                        _frames.Add((Encoding.Default.GetString(FrameData, n, 4), n, _length + 10));
                        n += _length;
    
                    }
                    n += 10;
                }
                return _frames;
            }
            //---判断 id3v2标志是否存在,并计算大小
            private int GetV2TagFrameLength(FileStream fs)
            {
                fs.Seek(0, SeekOrigin.Begin);
                byte[] _head = new byte[V2TagHeaderLength];
                fs.Read(_head, 0, _head.Length);
                if (string.Compare(Encoding.Default.GetString(_head, 0, 3), V2TagSymbol) == 0)
                {
                    return _head[6] << 21 | _head[7] << 14 | _head[8] << 7 | _head[9];
                }
                return 0;
            }
            //---读取id3v1 Tag 信息
            private void GetV1TagInfo(FileStream fs)
            {
                //取得ascii编码的字符串截止到 0 的数据长度
                Func<byte[], int, int, int> GetStringDataLength = (source, start, length) =>
                   {
                       for (int i = 0; i < length; i++)
                       {
                           if (source[start + i] == 0)
                           {
                               return i;
                           }
                       }
                       return length;
                   };
    
                byte[] _v1Tag = new byte[V1TagLength];
                fs.Seek(-_v1Tag.Length, SeekOrigin.End);
                fs.Read(_v1Tag, 0, _v1Tag.Length);
                if (string.Compare(Encoding.Default.GetString(_v1Tag, V1TagStruct[0], V1TagStruct[1]), V1TagSymbol) == 0)
                {
                    for (int i = 0; i < 5; i++)
                    {
                        Mp3Infos[i][2] = Encoding.Default.GetString(_v1Tag, V1TagStruct[(i + 1) * 2],
                            GetStringDataLength(_v1Tag, V1TagStruct[(i + 1) * 2], V1TagStruct[(i + 1) * 2 + 1]));
    
                    }
                    Mp3Infos[5][2] = _v1Tag[V1TagStruct[12]].ToString();
                }
            }
            //---填充id3v2Tag Frame 标志
            private void FillV2TagFrameIds()
            {
                V2TagFrameIds = new string[]{
                    "TIT2","TPE1","TALB","TYER","COMM","TCON",
                    "TPE2","TCOM","TPE3","TPE4","TRCK","TCOP"
                };
            }
            //---填充Mp3infos
            private void FillMp3Infos()
            {
    
                Mp3Infos.Add(new string[] { "歌名", "", "" });
                Mp3Infos.Add(new string[] { "表演", "", "" });
                Mp3Infos.Add(new string[] { "专辑", "", "" });
                Mp3Infos.Add(new string[] { "年份", "", "" });
                Mp3Infos.Add(new string[] { "备注", "", "" });
                Mp3Infos.Add(new string[] { "种类", "", "" });
                //以下为id3v2tag增加
                Mp3Infos.Add(new string[] { "乐队", "", "" });
                Mp3Infos.Add(new string[] { "作曲", "", "" });
                Mp3Infos.Add(new string[] { "指挥", "", "" });
                Mp3Infos.Add(new string[] { "重编", "", "" });
                Mp3Infos.Add(new string[] { "音轨", "", "" });
                Mp3Infos.Add(new string[] { "版权", "", "" });
    
                //以下为mp3数据头
                Mp3Infos.Add(new string[] { "Mpeg", "", "" });
                Mp3Infos.Add(new string[] { "Layer", "", "" });
                Mp3Infos.Add(new string[] { "波特率", "", "" });
                Mp3Infos.Add(new string[] { "频率", "", "" });
                Mp3Infos.Add(new string[] { "声道", "", "" });
            }
            //填充mp3数据头的数据表
            private void FillHeader()
            {
                Mpeg = new string[] { "MPEG 2.5", "Reserved", "MPEG 2", "MPEG 1" };
                Layer = new string[] { "Reserved", "Layer III", "Layer II", "Layer I" };
                Bitrate = new string[]
                {
                    "free","8","16","24","32","40","48","56","64","80","96","112","128","144","160","bad",
                    "free","8","16","24","32","40","48","56","64","80","96","112","128","144","160","bad",
                    "free","32","48","56","64","80","96","112","128","144","160","176","192","224","256","bad",
    
                    "free","0","0","0","0","0","0","0","0","0","0","0","0","0","0","bad",
                    "free","0","0","0","0","0","0","0","0","0","0","0","0","0","0","bad",
                    "free","0","0","0","0","0","0","0","0","0","0","0","0","0","0","bad",
    
                    "free","8","16","24","32","40","48","56","64","80","96","112","128","144","160","bad",
                    "free","8","16","24","32","40","48","56","64","80","96","112","128","144","160","bad",
                    "free","32","48","56","64","80","96","112","128","144","160","176","192","224","256","bad",
    
                    "free","32","40","48","56","64","80","96","112","128","160","192","224","256","320","bad",
                    "free","32","48","56","64","80","96","112","128","160","192","224","256","320","384","bad",
                    "free","32","64","96","128","160","192","224","256","288","320","352","384","416","448","bad",
    
                };
    
                Hz = new string[]
                {
                    "11025","12000","8000","Reserved",
                    "0","0","0","Reserved",
                    "22050","24000","16000","Reserved",
                    "44100","48000","32000","Reserved"
                };
                /*“联合立体声模式”是音频编码的立体声模式之一。联合立体声模式充分利用左右声道的相似之处,
                 * 对于左右声道的相同部分不再重复编码,减少了数据的浪费,这样就可以做到在较低的位率下表现更丰富的细节。
                 * 对于左右声道差异不大的音频来说,联合立体声编码模式通常在较低的位率下就可以得到不错的效果。
                 * 而“立体声模式”则使用两个相互独立的声道进行编码,因此它需要较多的位率,但它的左右声道的分离度较高,
                 * 通常使用在位率较高的场合,用于高质量的音频编码。
                 */
                Channel = new string[] { "立体声", "联合立体声", "双声道", "单声道" };
            }
            //---填充音乐类型表
            private void FillGenres()
            {
                string[] str = File.ReadAllText(GenreFile).Split(new char[] { (char)13, (char)10, '.' }, StringSplitOptions.RemoveEmptyEntries);
                Genres = new string[str.Length / 2];
                for (int i = 1; i < str.Length; i += 2)
                {
                    Genres[(i - 1) / 2] = str[i];
                }
            }
            //---填充 Id3v1 数据结构
            private void FillV1TagStruct()
            {
                //symbol
                V1TagStruct[0] = 0;//start pos
                V1TagStruct[1] = 3;//length
                //song title
                V1TagStruct[2] = 3;
                V1TagStruct[3] = 30;
                //artist
                V1TagStruct[4] = 33;
                V1TagStruct[5] = 30;
                //album
                V1TagStruct[6] = 63;
                V1TagStruct[7] = 30;
                //year
                V1TagStruct[8] = 93;
                V1TagStruct[9] = 4;
                //comment
                V1TagStruct[10] = 97;
                V1TagStruct[11] = 30;
                //genre
                V1TagStruct[12] = 127;
                V1TagStruct[13] = 1;
            }
        }
    }
    View Code
    //mp3genre.txt
          0.Blues
          1.Classic Rock
          2.Country
          3.Dance
          4.Disco
          5.Funk
          6.Grunge
          7.Hip-Hop
          8.Jazz
          9.Metal
         10.New Age
         11.Oldies
         12.Other
         13.Pop
         14.R&B
         15.Rap
         16.Reggae
         17.Rock
         18.Techno
         19.Industrial
         20.Alternative
         21.Ska
         22.Death Metal
         23.Pranks
         24.Soundtrack
         25.Euro-Techno
         26.Ambient
         27.Trip-Hop
         28.Vocal
         29.Jazz+Funk
         30.Fusion
         31.Trance
         32.Classical
         33.Instrumental
         34.Acid
         35.House
         36.Game
         37.Sound Clip
         38.Gospel
         39.Noise
         40.AlternRock
         41.Bass
         42.Soul
         43.Punk
         44.Space
         45.Meditative
         46.Instrumental Pop
         47.Instrumental Rock
         48.Ethnic
         49.Gothic
         50.Darkwave
         51.Techno-Industrial
         52.Electronic
         53.Pop-Folk
         54.Eurodance
         55.Dream
         56.Southern Rock
         57.Comedy
         58.Cult
         59.Gangsta
         60.Top 40
         61.Christian Rap
         62.Pop/Funk
         63.Jungle
         64.Native American
         65.Cabaret
         66.New Wave
         67.Psychadelic
         68.Rave
         69.Showtunes
         70.Trailer
         71.Lo-Fi
         72.Tribal
         73.Acid Punk
         74.Acid Jazz
         75.Polka
         76.Retro
         77.Musical
         78.Rock & Roll
         79.Hard Rock
         80.Folk
         81.Folk-Rock
         82.National Folk
         83.Swing
         84.Fast Fusion
         85.Bebob
         86.Latin
         87.Revival
         88.Celtic
         89.Bluegrass
         90.Avantgarde
         91.Gothic Rock
         92.Progressive Rock
         93.Psychedelic Rock
         94.Symphonic Rock
         95.Slow Rock
         96.Big Band
         97.Chorus
         98.Easy Listening
         99.Acoustic
        100.Humour
        101.Speech
        102.Chanson
        103.Opera
        104.Chamber Music
        105.Sonata
        106.Symphony
        107.Booty Bass
        108.Primus
        109.Porn Groove
        110.Satire
        111.Slow Jam
        112.Club
        113.Tango
        114.Samba
        115.Folklore
        116.Ballad
        117.Power Ballad
        118.Rhythmic Soul
        119.Freestyle
        120.Duet
        121.Punk Rock
        122.Drum Solo
        123.Acapella
        124.Euro-House
        125.Dance Hall
    View Code
  • 相关阅读:
    TCP/IP笔记 一.综述
    Makefile的规则
    u盘安装ubuntu10.04 server.txt
    浅谈数据库技术,磁盘冗余阵列,IP分配,ECC内存,ADO,DAO,JDBC
    cocos2d-js 热更新具体解释(一)
    C#一个托付的样例
    JAVA学习之 异常处理机制
    阿里巴巴校招内推简历筛选方案
    《凑硬币》 动态规划算法入门
    android 读取xml
  • 原文地址:https://www.cnblogs.com/leemano/p/6545443.html
Copyright © 2011-2022 走看看