public AudioInfo ReadAudioInfo(Stream stream) { using (var reader = new FrameReader(stream)) try { var frameHeader = ReadFrameHeader(reader); // Frame count is found in the optional Xing (most common) or VBRI header var optionalHeader = ReadXingHeader(reader, frameHeader); if (optionalHeader.Incomplete) { optionalHeader = ReadVbriHeader(reader); } return(AudioInfo.CreateForLossy( "MP3", frameHeader.Channels, frameHeader.SampleRate, optionalHeader.FrameCount * frameHeader.SamplesPerFrame, DetermineBitRate(frameHeader, optionalHeader))); } catch (EndOfStreamException e) { // If a frame sync couldn't be located, this isn't an MP3 throw new AudioInvalidException(e.Message); } }
public void BitRateIsSerialized() { var formatter = new BinaryFormatter(); using (var stream = new MemoryStream()) { formatter.Serialize(stream, AudioInfo.CreateForLossy("Test", 2, 44100, 0, 1000)); stream.Position = 0; Assert.Equal(1000, ((AudioInfo)formatter.Deserialize(stream)).BitRate); } }
public AudioInfo ReadAudioInfo(Stream stream) { try { var mp4 = new Mp4Model(stream); mp4.DescendToAtom("moov", "trak", "mdia", "minf", "stbl", "stts"); var stts = new SttsAtom(mp4.ReadAtom(mp4.CurrentAtom)); var sampleCount = stts.PacketCount * stts.PacketSize; mp4.DescendToAtom("moov", "trak", "mdia", "minf", "stbl", "stsd", "mp4a", "esds"); var esds = new EsdsAtom(mp4.ReadAtom(mp4.CurrentAtom)); if (esds.IsAac) { mp4.Reset(); return(AudioInfo.CreateForLossy("AAC", esds.Channels, (int)esds.SampleRate, sampleCount, CalculateBitRate(mp4.GetChildAtomInfo().Single(atom => atom.FourCc.Equals("mdat", StringComparison.Ordinal)).Size, sampleCount, esds.SampleRate))); } // Apple Lossless files have their own atom for storing audio info if (!mp4.DescendToAtom("moov", "trak", "mdia", "minf", "stbl", "stsd", "alac")) { throw new AudioUnsupportedException("Only AAC and ALAC MP4 streams are supported."); } var alac = new AlacAtom(mp4.ReadAtom(mp4.CurrentAtom)); return(AudioInfo.CreateForLossless( "ALAC", alac.Channels, alac.BitsPerSample, (int)alac.SampleRate, sampleCount)); } catch (EndOfStreamException e) { throw new AudioInvalidException(e.Message); } }
public unsafe AudioInfo ReadAudioInfo(Stream stream) { OggStream?oggStream = null; SafeNativeMethods.VorbisCommentInit(out var vorbisComment); #if NETSTANDARD2_0 var buffer = ArrayPool <byte> .Shared.Rent(4096); #else Span <byte> buffer = stackalloc byte[4096]; #endif try { using (var sync = new OggSync()) using (var decoder = new VorbisDecoder()) { OggPage page; do { // Read from the buffer into a page while (!sync.PageOut(out page)) { #if NETSTANDARD2_0 var bytesRead = stream.Read(buffer, 0, buffer.Length); #else var bytesRead = stream.Read(buffer); #endif if (bytesRead == 0) { throw new AudioInvalidException("No Ogg stream was found."); } var nativeBuffer = new Span <byte>(sync.Buffer(bytesRead).ToPointer(), bytesRead); #if NETSTANDARD2_0 buffer.AsSpan().Slice(0, bytesRead).CopyTo(nativeBuffer); #else buffer.Slice(0, bytesRead).CopyTo(nativeBuffer); #endif sync.Wrote(bytesRead); } oggStream ??= new(SafeNativeMethods.OggPageSerialNo(page)); oggStream.PageIn(page); while (oggStream.PacketOut(out var packet)) { if (!SafeNativeMethods.VorbisSynthesisIdHeader(packet)) { throw new AudioUnsupportedException("Not a Vorbis stream."); } decoder.HeaderIn(vorbisComment, packet); var info = decoder.GetInfo(); return(AudioInfo.CreateForLossy( "Vorbis", info.Channels, #if WINDOWS info.Rate, GetFinalGranulePosition(oggStream.SerialNumber, stream), Math.Max(info.BitRateNominal, 0))); #else (int)info.Rate, GetFinalGranulePosition((int)oggStream.SerialNumber, stream), Math.Max((int)info.BitRateNominal, 0)); #endif } } while (!SafeNativeMethods.OggPageEos(page)); throw new AudioInvalidException("The end of the Ogg stream was reached without finding a header."); } } finally { #if NETSTANDARD2_0 ArrayPool <byte> .Shared.Return(buffer); #endif SafeNativeMethods.VorbisCommentClear(ref vorbisComment); oggStream?.Dispose(); } }
public void BitRateNegativeThrowsException() { Assert.Throws <AudioInvalidException>(() => AudioInfo.CreateForLossy("Test", 2, 44100, 0, -1)); }