/// <summary> /// Initializes a new instance of the <see cref="MonkeysAudio"/> class. /// </summary> /// <param name="path">The path.</param> public MonkeysAudio(string path) { using (FileStream stream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read)) { // Skip ID3v2 tag int tmpID3v2TagSize = ID3v2.GetTagSize(stream); int tmpID3v1TagSize = ID3v1.GetTagSize(stream); int tmpAPEv2TagSize = APEv2.GetTagSize(stream); stream.Seek(tmpID3v2TagSize, SeekOrigin.Begin); byte[] identifier = stream.Read(4); if (ByteUtils.Compare(identifier, MAC_IDENTIFIER, 4) == false) { throw new InvalidDataException("Invalid Monkey's Audio file"); } byte[] buf = stream.Read(4); _version = buf[0] + (buf[1] << 8); int blocksPerFrame; int finalBlocks; if (_version >= 3980 && _version <= 3990) { buf = stream.Read(4); int descriptorLength = buf[0] + (buf[1] << 8) + (buf[2] << 16) + (buf[3] << 24); stream.Seek(descriptorLength - 12, SeekOrigin.Current); // skip DESCRIPTOR buf = stream.Read(4); _compressionLevel = buf[0] + (buf[1] << 8); blocksPerFrame = stream.ReadInt32LittleEndian(); finalBlocks = stream.ReadInt32LittleEndian(); _frames = stream.ReadInt32LittleEndian(); buf = stream.Read(4); // skip bits per sample _channels = buf[2] + (buf[3] << 8); _frequency = stream.ReadInt32LittleEndian(); } else if (_version <= 3970) { // TODO: This section needs work _compressionLevel = buf[2] + (buf[3] << 8); buf = stream.Read(24); // skip format flags _channels = buf[2] + (buf[3] << 8); _frequency = buf[4] + (buf[5] << 8) + (buf[6] << 16) + (buf[7] << 32); if (_version >= 3950) { blocksPerFrame = 73728 * 4; } else if (_version >= 3900 || (_version >= 3800 && _compressionLevel == COMPRESSION_LEVEL_EXTRA_HIGH)) { blocksPerFrame = 73728; } else { blocksPerFrame = 9216; } // TODO: This is definitely f****d up finalBlocks = buf[0] + (buf[1] << 8) + (buf[2] << 16) + (buf[3] << 24); _frames = buf[0] + (buf[1] << 8) + (buf[2] << 16) + (buf[3] << 24); } else { throw new NotImplementedException(string.Format("MAC {0:0.00} not supported", _version / 1000.0)); } long totalBlocks = ((_frames - 1) * blocksPerFrame) + finalBlocks; long totalSize = stream.Length - stream.Position - tmpAPEv2TagSize - tmpID3v1TagSize; _totalSeconds = totalBlocks / (decimal)_frequency; _bitrate = totalSize / (_totalSeconds * 125.0m); } }
private readonly int _channels = 2; // TODO /// <summary> /// Initializes a new instance of the <see cref="Musepack"/> class. /// </summary> /// <param name="path">The path of the file.</param> public Musepack(string path) { using (FileStream stream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read)) { // Skip ID3v2 tag int tmpID3v2TagSize = ID3v2.GetTagSize(stream); int tmpID3v1TagSize = ID3v1.GetTagSize(stream); int tmpAPEv2TagSize = APEv2.GetTagSize(stream); stream.Seek(tmpID3v2TagSize, SeekOrigin.Begin); _streamVersion = 0; byte[] byteArray = stream.Read(32); int[] integerArray = new int[8]; for (int i = 0; i < 8; i++) { integerArray[i] = (byteArray[i * 4]) + (byteArray[i * 4 + 1] << 8) + (byteArray[i * 4 + 2] << 16) + (byteArray[i * 4 + 3] << 24); } // Size TODO - ignore Lyrics3 long audioDataLength = stream.Length - tmpID3v2TagSize - tmpID3v1TagSize - tmpAPEv2TagSize; // Stream version if (integerArray[0] == STREAM_VERSION_70_ID) { _streamVersion = 7; } else if (integerArray[0] == STREAM_VERSION_71_ID) { _streamVersion = 7.1m; } else { switch ((byteArray[1] % 32) / 2) { case 3: _streamVersion = 4; break; case 7: _streamVersion = 5; break; case 11: _streamVersion = 6; break; } } if (_streamVersion == 0) { throw new InvalidDataException("Unrecognized MPC stream"); } // Sample rate _frequency = _sampleRates[byteArray[10] & 0x03]; // Channels if (_streamVersion == 7 || _streamVersion == 7.1m) { if ((byteArray[11] % 128) < 64) { _mode = "Stereo"; } else { _mode = "Joint Stereo"; } } else { if ((byteArray[2] % 128) == 0) { _mode = "Stereo"; } else { _mode = "Joint Stereo"; } } // Frames if (_streamVersion == 4) { _frames = integerArray[1] >> 16; } else { _frames = integerArray[1]; } _totalSeconds = _frames * 1152 / (decimal)_frequency; _bitrate = (audioDataLength / _totalSeconds) / 125.0m; } }
private void CalculateBitrate(Stream stream, CInterestedFrames InterestedFrames) { int totalTagSize = ID3v2.GetTagSize(stream); totalTagSize += ID3v1.GetTagSize(stream); totalTagSize += APEv2.GetTagSize(stream); Int64 audioLength = stream.Length - totalTagSize; _bitrate = 0; _isVBR = null; _frames = 0; _totalSeconds = 0; String step = ""; try { int BR, Padding; int FrameSize; int TotalBR = 0; int FrameOffset = 0; //Int64 TagOffset = 0; bool bTrusting = true; bool ignoreall = false; Byte[] FH = new Byte[4]; bool mPerfect = true; stream.Position = _headerOffset; // if (_headerOffset > 0) // { // TagOffset = _headerOffset; // } int offset = 0; int frameCount = 0; int FirstBR = 0; int audioDataSize = (int)(stream.Length - _headerOffset); Byte[] audioData = new Byte[audioDataSize]; //Int64 startoffset = stream.Position; int BufLen = stream.Read(audioData, 0, audioDataSize); while (offset < BufLen - 16 && !ignoreall) { bool reservedlayer = false; // Find FrameSync if (FindFrameSync(FH, audioData, BufLen, ref FrameOffset, ref offset, ref mPerfect, ref ignoreall, ref bTrusting, ref reservedlayer)) { FrameOffset = 0; int bitrateIndex = FH[2] >> 4; if (bitrateIndex <= 0 || bitrateIndex >= 15) { offset -= 3; continue; } Padding = (FH[2] >> 1) & 0x01; BR = GetBitrate(_mpegVersion, _mpegLayer, bitrateIndex); if (BR == 0 || BR % 8 != 0) { offset -= 3; continue; } //step = "last good frame @ " + String(startoffset + offset - 4) + ", frame " + // String(_frames + 1); // todo: put back later /*if (InterestedFrames != NULL) * { * if (((_frames + 1) * _samplesperframe / (float)_Frequency) * 75.0 >= InterestedFrames->CurrentFrame()) * { * if (_frames == 0 || InterestedFrames->NoAccomodation) * { * InterestedFrames->SetCurrentByteOffset(startoffset + offset - 4); * InterestedFrames->SetCurrentFrameOffset(_frames); * } * InterestedFrames->SetCurrentByteEndOffset(startoffset + offset - 4); * InterestedFrames->Cur += 1; * } * else * { * InterestedFrames->SetCurrentByteOffset(startoffset + offset - 4); * InterestedFrames->SetCurrentFrameOffset(_frames); * } * }*/ if (_isVBR != true) { if (TotalBR == 0) { FirstBR = BR; } else if (BR != FirstBR) { _isVBR = true; } } TotalBR += BR; FrameSize = (int)(BR * _frameSizeConst + Padding * _paddingSizeConst); offset += FrameSize - 4; frameCount++; } }// end while if (frameCount == 0) { throw new InvalidDataException(String.Format("No frames found in {0}", _fileName)); } _frames = frameCount; if (_isVBR == null) { _bitrate = FirstBR; _isVBR = false; } else { _bitrate = TotalBR / _frames; } if (_bitrate == 0) { throw new InvalidDataException(String.Format("Error determining bitrate: {0}", _fileName)); } _totalSeconds = (audioLength / 125.0m) / _bitrate; } catch (Exception ex) { throw new Exception(String.Format("Error calculating bitrate; {0}", step), ex); } }
/// <summary> /// Initializes a new instance of the <see cref="Flac"/> class. /// </summary> /// <param name="path">The path of the file.</param> public Flac(string path) { try { using (FileStream stream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read)) { // Skip ID3v2 tag int tmpID3v2TagSize = ID3v2.GetTagSize(stream); int tmpID3v1TagSize = ID3v1.GetTagSize(stream); int tmpAPEv2TagSize = APEv2.GetTagSize(stream); stream.Seek(tmpID3v2TagSize, SeekOrigin.Begin); // Read flac marker byte[] flacMarker = new Byte[4]; stream.Read(flacMarker, 0, 4); if (ByteUtils.Compare(flacMarker, FLAC_MARKER) == false) { throw new InvalidDataException("No header found"); } // skip frame header and stuff we're not interested in stream.Seek(14, SeekOrigin.Current); byte[] buf = stream.Read(8); _frequency = (buf[0] << 12) + (buf[1] << 4) + (buf[2] >> 4); _channels = ((buf[2] >> 1) & 0x03) + 1; _samples = ((buf[3] & 0x0F) << 32) + (buf[4] << 24) + (buf[5] << 16) + (buf[6] << 8) + buf[7]; _totalSeconds = _samples / (decimal)_frequency; // Find first sync // TODO: There's probably a better way to do this.. also an embedded PICTURE might // cause a false sync. Not high priority since it will only cause a slight error // in bitrate calculation if a false sync is found. int c = stream.ReadByte(); // keep as ReadByte while (c != -1) { if (c == 0xFF) { c = stream.ReadByte(); // keep as ReadByte if (c >= 0xF8 && c <= 0xFB) { break; } } else { c = stream.ReadByte(); // keep as ReadByte } } if (c == -1) { throw new InvalidDataException("No sync found"); } long startaudio = stream.Position; long totalsize = stream.Length - startaudio - tmpAPEv2TagSize - tmpID3v1TagSize; _bitrate = totalsize / (_totalSeconds * 125); } } catch (InvalidDataException ex) { throw new InvalidDataException(String.Format("Cannot read FLAC file '{0}'", path), ex); } }