public Mp3Reader(FileInfo file) { _file = file; _fileStream = new FileStream(file.FullName, FileMode.Open, FileAccess.Read, FileShare.Read, 65536); // Analyze keyframes data AnalyzeKeyFrames(); _firstFrame = true; // Process ID3v2 header if present ProcessID3v2Header(); // Create file metadata object _fileMeta = CreateFileMeta(); // MP3 header is length of 32 bits, that is, 4 bytes // Read further if there's still data if (_fileStream.Length - _fileStream.Position > 4) { // Look to next frame SearchNextFrame(); // Save position long pos = _fileStream.Position; // Read header... // Data in MP3 file goes header-data-header-data...header-data Mp3Header header = ReadHeader(); // Set position _fileStream.Position = pos; // Check header if (header != null) { CheckValidHeader(header); } else { throw new NotSupportedException("No initial header found."); } } }
/// <summary> /// Check if the file can be played back with Flash. Supported sample rates are 44KHz, 22KHz, 11KHz and 5.5KHz /// </summary> /// <param name="header"></param> private void CheckValidHeader(Mp3Header header) { switch (header.SampleRate) { case 44100: case 22050: case 11025: case 5513: // Supported sample rate break; default: throw new NotSupportedException("Unsupported sample rate: " + header.SampleRate); } }
public bool HasMoreTags() { Mp3Header header = null; while (header == null && (_fileStream.Length - _fileStream.Position) > 4) { try { byte[] buffer = new byte[4]; _fileStream.Read(buffer, 0, 4); header = new Mp3Header(buffer); } catch (IOException ex) { log.Error("MP3Reader HasMoreTags", ex); break; } catch (Exception) { SearchNextFrame(); } } if (header == null) { return(false); } if (header.FrameSize == 0) { // TODO find better solution how to deal with broken files... // See APPSERVER-62 for details return(false); } if (_fileStream.Position + header.FrameSize - 4 > _fileStream.Length) { // Last frame is incomplete _fileStream.Position = _fileStream.Length; return(false); } _fileStream.Position = _fileStream.Position - 4; return(true); }
private Mp3Header ReadHeader() { Mp3Header header = null; while (header == null && (_fileStream.Length - _fileStream.Position) > 4) { try { byte[] buffer = new byte[4]; _fileStream.Read(buffer, 0, 4); header = new Mp3Header(buffer); } catch (IOException ex) { log.Error("MP3Reader ReadTag", ex); break; } catch (Exception) { SearchNextFrame(); } } return(header); }
public KeyFrameMeta AnalyzeKeyFrames() { lock (_syncLock) { if (_frameMeta != null) { return(_frameMeta); } #if !NET_1_1 List <long> positionList = new List <long>(); List <double> timestampList = new List <double>(); #else ArrayList positionList = new ArrayList(); ArrayList timestampList = new ArrayList(); #endif _dataRate = 0; long rate = 0; int count = 0; long origPos = _fileStream.Position; double time = 0; _fileStream.Position = 0; ProcessID3v2Header(); SearchNextFrame(); while (this.HasMoreTags()) { Mp3Header header = ReadHeader(); if (header == null) { // No more tags break; } if (header.FrameSize == 0) { // TODO find better solution how to deal with broken files... // See APPSERVER-62 for details break; } long pos = _fileStream.Position - 4; if (pos + header.FrameSize > _fileStream.Length) { // Last frame is incomplete break; } positionList.Add(pos); timestampList.Add(time); rate += header.BitRate / 1000; time += header.FrameDuration; _fileStream.Position = pos + header.FrameSize; count++; } // restore the pos _fileStream.Position = origPos; _duration = (long)time; _dataRate = (int)(rate / count); #if !NET_1_1 _posTimeMap = new Dictionary <long, double>(); #else _posTimeMap = new Hashtable(); #endif _frameMeta = new KeyFrameMeta(); _frameMeta.Duration = _duration; _frameMeta.Positions = new long[positionList.Count]; _frameMeta.Timestamps = new int[timestampList.Count]; _frameMeta.AudioOnly = true; for (int i = 0; i < _frameMeta.Positions.Length; i++) { _frameMeta.Positions[i] = (int)positionList[i]; _frameMeta.Timestamps[i] = (int)timestampList[i]; _posTimeMap.Add(positionList[i], timestampList[i]); } return(_frameMeta); } }
public ITag ReadTag() { lock (_syncLock) { if (_firstFrame) { // Return file metadata as first tag. _firstFrame = false; return(_fileMeta); } Mp3Header header = ReadHeader(); if (header == null) { return(null); } int frameSize = header.FrameSize; if (frameSize == 0) { // TODO find better solution how to deal with broken files... // See APPSERVER-62 for details return(null); } if (_fileStream.Position + frameSize - 4 > _fileStream.Length) { // Last frame is incomplete _fileStream.Position = _fileStream.Length; return(null); } _tag = new Tag(IOConstants.TYPE_AUDIO, (int)_currentTime, frameSize + 1, null, _prevSize); _prevSize = frameSize + 1; _currentTime += header.FrameDuration; byte[] buffer = new byte[_tag.BodySize]; //ByteBuffer body = ByteBuffer.Allocate(_tag.BodySize); byte tagType = (byte)((IOConstants.FLAG_FORMAT_MP3 << 4) | (IOConstants.FLAG_SIZE_16_BIT << 1)); switch (header.SampleRate) { case 44100: tagType |= (byte)(IOConstants.FLAG_RATE_44_KHZ << 2); break; case 22050: tagType |= (byte)(IOConstants.FLAG_RATE_22_KHZ << 2); break; case 11025: tagType |= (byte)(IOConstants.FLAG_RATE_11_KHZ << 2); break; default: tagType |= (byte)(IOConstants.FLAG_RATE_5_5_KHZ << 2); break; } tagType |= (header.IsStereo ? IOConstants.FLAG_TYPE_STEREO : IOConstants.FLAG_TYPE_MONO); /* * body.Put(tagType); * body.PutInt(header.Data); * byte[] buffer = new byte[frameSize - 4]; * _fileStream.Read(buffer, 0, buffer.Length); * body.Put(buffer); * body.Flip(); * _tag.Body = body.ToArray(); */ buffer[0] = tagType; Array.Copy(header.Data, 0, buffer, 1, 4); _fileStream.Read(buffer, 5, frameSize - 4); _tag.Body = buffer; return(_tag); } }