public void Dispose()
 {
     _encoder?.Dispose();
     _oggStream?.Dispose();
     _replayGainExport?.Dispose();
 }
Beispiel #2
0
        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 unsafe AudioMetadata ReadMetadata(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))
                        {
                            decoder.HeaderIn(vorbisComment, packet);

                            if (packet.PacketNumber == 1)
                                return new VorbisCommentToMetadataAdapter(vorbisComment);
                        }
                    } 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();
            }
        }