Files
ichni_Creator_Studio/Assets/NLayer/Decoder/ID3Frame.cs
2025-07-12 18:27:10 +08:00

206 lines
6.3 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NLayer.Decoder
{
class ID3Frame : FrameBase
{
internal static ID3Frame TrySync(uint syncMark)
{
if ((syncMark & 0xFFFFFF00U) == 0x49443300)
{
return new ID3Frame { _version = 2 };
}
if ((syncMark & 0xFFFFFF00U) == 0x54414700)
{
if ((syncMark & 0xFF) == 0x2B)
{
return new ID3Frame { _version = 1 };
}
else
{
return new ID3Frame { _version = 0 };
}
}
return null;
}
int _version;
ID3Frame()
{
}
protected override int Validate()
{
switch (_version)
{
case 2:
// v2, yay!
var buf = new byte[7];
if (Read(3, buf) == 7)
{
byte flagsMask;
switch (buf[0])
{
case 2:
flagsMask = 0x3F;
break;
case 3:
flagsMask = 0x1F;
break;
case 4:
flagsMask = 0x0F;
break;
default:
return -1;
}
// ignore the flags (we don't need them for the validation)
// get the size (7 bits per byte [MSB cleared])
var size = (buf[3] << 21)
| (buf[4] << 14)
| (buf[5] << 7)
| (buf[6]);
// finally, check to make sure that all the right bits are cleared
if (!(((buf[2] & flagsMask) | (buf[3] & 0x80) | (buf[4] & 0x80) | (buf[5] & 0x80) | (buf[6] & 0x80)) != 0 || buf[1] == 0xFF))
{
return size + 10; // don't forget the sync, flag & size bytes!
}
}
break;
case 1:
return 227 + 128;
case 0:
return 128;
}
return -1;
}
internal override void Parse()
{
// assume we have to process it now or else... we can still read the whole frame, so no biggie
switch (_version)
{
case 2:
ParseV2();
break;
case 1:
ParseV1Enh();
break;
case 0:
ParseV1(3);
break;
}
}
void ParseV1(int offset)
{
//var buffer = new byte[125];
//if (Read(offset, buffer) == 125)
//{
// // v1 tags use ASCII encoding... For now we'll use the built-in encoding, but for Win8 we'll have to build our own.
// var encoding = Encoding.ASCII;
//
// // title (30)
// Title = encoding.GetString(buffer, 0, 30);
//
// // artist (30)
// Artist = encoding.GetString(buffer, 30, 30);
//
// // album (30)
// Album = encoding.GetString(buffer, 60, 30);
//
// // year (4)
// Year = encoding.GetString(buffer, 90, 30);
//
// // comment (30)*
// Comment = encoding.GetString(buffer, 94, 30);
//
// if (buffer[122] == 0)
// {
// // track (1)*
// Track = (int)buffer[123];
// }
//
// // genre (1)
// // ignore for now
//
// // * if byte 29 of comment is 0, track is byte 30. Otherwise, track is unknown.
//}
}
void ParseV1Enh()
{
ParseV1(230);
//var buffer = new byte[223];
//if (Read(4, buffer) == 223)
//{
// // v1 tags use ASCII encoding... For now we'll use the built-in encoding, but for Win8 we'll have to build our own.
// var encoding = Encoding.ASCII;
//
// // title (60)
// Title += encoding.GetString(buffer, 0, 60);
//
// // artist (60)
// Artist += encoding.GetString(buffer, 60, 60);
//
// // album (60)
// Album += encoding.GetString(buffer, 120, 60);
//
// // speed (1)
// //var speed = buffer[180];
//
// // genre (30)
// Genre = encoding.GetString(buffer, 181, 30);
//
// // start-time (6)
// // 211
//
// // end-time (6)
// // 217
//}
}
void ParseV2()
{
// v2 is much more complicated than v1... don't worry about it for now
// look for any merged frames, as well
}
internal int Version
{
get
{
if (_version == 0) return 1;
return _version;
}
}
//internal string Title { get; private set; }
//internal string Artist { get; private set; }
//internal string Album { get; private set; }
//internal string Year { get; private set; }
//internal string Comment { get; private set; }
//internal int Track { get; private set; }
//internal string Genre { get; private set; }
// speed
//public TimeSpan StartTime { get; private set; }
//public TimeSpan EndTime { get; private set; }
internal void Merge(ID3Frame newFrame)
{
// just save off the frame for parsing later
}
}
}