/// <summary> /// Construct from file info; parse ID3 tags from stream and calculate where the audio must be /// </summary> /// <param name="fileinfo"></param> public MP3FileData(FileInfo fileinfo) { _sourceFileInfo = fileinfo; // create an empty frame model, to use if we don't parse anything better TagModel tagModel = new TagModel(); // don't know how big the audio is until we've parsed the tags UInt32 audioNumBytes; using( FileStream sourceStream = fileinfo.Open( FileMode.Open, FileAccess.Read, FileShare.Read ) ) { // all the header calculations use UInt32; // this guarantees all the file offsets we have to deal with fit in a UInt32 if( sourceStream.Length > UInt32.MaxValue ) throw new InvalidAudioFrameException( "MP3 file can't be bigger than 4gb" ); // in the absence of any recognised tags, // audio starts at the start _audioStart = 0; // audio is entire file length audioNumBytes = (UInt32)sourceStream.Length; // try to read an ID3v1 block. // If ID3v2 block exists, its values overwrite these // Otherwise, if ID3V1 block exists, its values are used // The audio is anything that's left after all the tags are excluded. try { ID3v1 id3v1 = new ID3v1(); id3v1.Deserialize( sourceStream ); // fill in ID3v2 block from the ID3v1 data tagModel = id3v1.FrameModel; // audio is shorter by the length of the id3v1 tag audioNumBytes -= ID3v1.TagLength; } catch( TagNotFoundException ) { // ignore "no ID3v1 block" // everything else isn't caught here, and throws out to the caller } try { sourceStream.Seek( 0, SeekOrigin.Begin ); tagModel = TagManager.Deserialize( sourceStream ); // audio starts after the tag _audioStart = (uint)sourceStream.Position; // audio is shorter by the length of the id3v2 tag audioNumBytes -= _audioStart; } catch( TagNotFoundException ) { // ignore "no ID3v2 block" // everything else isn't caught here, and throws out to the caller } // create a taghandler to hold the tagmodel we've parsed, if any _tagHandler = new TagHandler( tagModel ); } // closes sourceStream // save the location of the audio in the original file // passing in audio size and id3 length tag (if any) to help with bitrate calculations _audio = new AudioFile( fileinfo, _audioStart, audioNumBytes, _tagHandler.Length ); _audioReplaced = false; }
/// <summary> /// append or overwrite ID3v1 tag at the end of the audio /// </summary> /// <param name="stream"></param> public void WriteID3v1( Stream stream ) { ID3v1 v1tag = new ID3v1(); v1tag.FrameModel = TagModel; stream.Seek(_audioStart + _audio.NumPayloadBytes, SeekOrigin.Begin); v1tag.Write(stream); }