nvorbis / nvorbis Goto Github PK
View Code? Open in Web Editor NEWC# Ogg Vorbis decoder
License: MIT License
C# Ogg Vorbis decoder
License: MIT License
One of my test files fails to read after it has been parsed once. It works fine in 0.10.4, but the issue started in 0.10.5.
Start to read from the file via VorbisReader ReadSamples() method until it returns 0. Then try seeking to the start of the file using either TimePosition or SamplePosition, then it fails. Other files I have works fine, so I guess there is something special with this file. I have attached it.
I've been trying to speak to someone in the chat on Element to get guidance on merging ogg files.
The example in the Readme doesn't show much.
Am I meant to place the read buffer into the stream? If so, does reading the ogg file have a header to account for?
I see a comment for "// 200MS". Is the read buffer meant to be that way for all samples?
I was stressing out my player NAudio-NVorbis based and I also upgrade NVorbis at the latest version but when I perform lots of seeks during playback it causes a deadlock because of the infinite loop as shown in the screenshot
Assuming that:
granulePos = 79062591
highGranulePos = 79062592
low = 3
lowGranulePos = num1 = 0
dist = num2 = 222
int index = low + (int)(dist * ((granulePos - lowGranulePos) / (float)(highGranulePos - lowGranulePos)));
then
index = 3 + (int)(222*((79062591 - 0) / (79062592 - 0))
should give 224 but at runtime 225 is calculated, casting to double instead float works fine
int index = low + (int)(dist * ((granulePos - lowGranulePos) / (double)(highGranulePos - lowGranulePos)))
NVorbis builds just fine if you add net6.0
to its TargetFrameworks
. Is there any reason this shouldn't be done?
A project that I'm trying to get to build entirely on net6 as a self-challenge depends on NAudio.Vorbis. NAudio recently got net6 builds in 2.1.0-beta.1, and NAudio.Vorbis builds fine in net6 on those as well. I'm not skilled enough at .NET to understand why NAudio.Vorbis builds on net6 without NVorbis building on net6, but my gut tells me here's the best place to ask.
It's very confusing considering that NLayer which is a very similar library developed by the same developers is not this way.
ForwardOnlyPageReader
seems to throw a specific ArgumentException
on the last page for all files, including test files.
Maybe that's why TestApp
doesn't try to use ForwardOnlyStream
?
The fault seems to be incorrect fallthrough logic at:
NVorbis/NVorbis/Ogg/ForwardOnlyPageReader.cs
Lines 35 to 37 in 7ccaee4
return true;
at the end of this block, disobeying the comment, seems to fix it.PageReader
to come up with this fix so I'm doubtful that this fallthrough comment is correct.
I wish for the nuget packages to have a more informative readme.
The nuget package should be using the same readme as the repo to make it as easy as possible for a user to get started with the package.
// try to fill the buffer; drain the last buffer if EOS, resync, bad packet, or parameter change
while (idx < tgt)
{
// if we don't have any more valid data in the current packet, read in the next packet
if (_prevPacketStart == _prevPacketEnd)
{
if (_eosFound)
{
_nextPacketBuf = null;
_prevPacketBuf = null;
// no more samples, so just return
break;
}
if (!ReadNextPacket((idx - offset) / _channels, out var samplePosition))
{
// drain the current packet (the windowing will fade it out)
_prevPacketEnd = _prevPacketStop;
}
// if we need to pick up a position, and the packet had one, apply the position now
if (samplePosition.HasValue && !_hasPosition)
{
_hasPosition = true;
_currentPosition = samplePosition.Value - (_prevPacketEnd - _prevPacketStart) - (idx - offset) / _channels;
}
}
// we read out the valid samples from the previous packet
var copyLen = Math.Min((tgt - idx) / _channels, _prevPacketEnd - _prevPacketStart);
if (copyLen > 0)
{
if (ClipSamples)
{
idx += ClippingCopyBuffer(buffer, idx, copyLen);
}
else
{
idx += CopyBuffer(buffer, idx, copyLen);
}
}
}
Not happen all the time, but when it happen, inside this while loop, while _eosFound is true, but code doesn't enter this if bracket. I don't know how but the _prevPacketEnd is small than _prevPacketStart causing copyLen to be negative value. The loop doesn't exit at all.
I temporarily added an if to check if copyLen is negative and return early to break the loop. No sure if the issue is caused by the ogg file but I cannot provide it due to copy right issue.
WHAT WORKS: Test App project can be set as the Startup project and it plays a sample OGG file.
PROBLEMS: 1) Usage instructions are not even a unit test. 2) The current usage instructions require you to ReadSamples with 4 parameters but current implementation only has 3 parameters. 3) I am not sure that the current usage instructions even plays the sound. It seems to read the file but not actually play anything. 4) The current TestApp project is not a even test project. 5) The only test in the current TestApp project requires a external dependency on a 3rd party application called NAudio . (If you want to show how to utilize NAudio integration, then you should build another test app just for it and take the dependency there.) 6) There is no active test for the ForwardOnlyStream unit that was provided in the TestApp.
I recently upgraded to the latest NAudio/NVorbis and I am now getting some playback synchronization issues with files that used to work.
Some files when decoded get slightly out of sync over time compared to how they should be.
Here is an example file:
https://drive.google.com/file/d/1KnMiL29oW8x9LA1xQtLAj9347AWJdKWt/view?usp=sharing
Here is that ogg decoded to a .wav file using NVorbis:
https://drive.google.com/file/d/1BXXs2OGqWHoqrguVJtlByb2r7_dH9dDg/view?usp=sharing
If you load both the .ogg file and the .wav file into an audio editor (such as Audacity), you will easily be able to see/hear the progressive sync issue.
The .wav was created from the .ogg as follows:
using (var fs = File.OpenRead(fileName)) { using (var waveStream = new VorbisWaveStream(fs)) { WaveFileWriter.CreateWaveFile16(Path.Combine(@"C:\tmp", Path.GetFileNameWithoutExtension(fileName) + ".wav"), waveStream); } }
As I said, this file (and other files I have issues with) worked fine previously. I think I was previously using NAudio.Vorbis 1.2.0.
This issue happens fairly consistently and I get error like the following
System.IO.InvalidDataException
HResult=0x80131501
Message=GranulePos mismatch: Page 3, expected 17088, calculated 16601
@Danielku15, @jjxtra, @ToddBertaOldham
Continuation of #12 in the old repository.
With the exception of Todd, all other submissions no longer apply as of the merge of the rearchitecting branch (the Ogg components, in particular, have been fully re-written), so given Todd's approval in the previous thread I'm going to re-license as MIT.
Since the rewrite with v0.10.0-alpha and up to the most recent version I'm getting IndexOutOfRangeException
s when trying to read a specific OGG file. I tried it with the TestApp
from this repo. This is the stack trace of the exception I'm seeing:
System.IndexOutOfRangeException
HResult=0x80131508
Message=Index was outside the bounds of the array.
Source=NVorbis
StackTrace:
at NVorbis.Ogg.PacketProvider.CreatePacket(Int32& pageIndex, Int32& packetIndex, Boolean advance, Int64 granulePos, Boolean isResync, Boolean isContinued, Int32 packetCount, Int32 pageOverhead) in D:\DEV\NVorbis\NVorbis\Ogg\PacketProvider.cs:line 195
at NVorbis.Ogg.PacketProvider.GetNextPacket(Int32& pageIndex, Int32& packetIndex) in D:\DEV\NVorbis\NVorbis\Ogg\PacketProvider.cs:line 178
at NVorbis.Ogg.PacketProvider.GetNextPacket() in D:\DEV\NVorbis\NVorbis\Ogg\PacketProvider.cs:line 46
at NVorbis.StreamDecoder.DecodeNextPacket(Int32& packetStartindex, Int32& packetValidLength, Int32& packetTotalLength, Boolean& isEndOfStream, Nullable`1& samplePosition, Int32& bitsRead, Int32& bitsRemaining, Int32& containerOverheadBits) in D:\DEV\NVorbis\NVorbis\StreamDecoder.cs:line 464
at NVorbis.StreamDecoder.ReadNextPacket(Int32 bufferedSamples, Nullable`1& samplePosition) in D:\DEV\NVorbis\NVorbis\StreamDecoder.cs:line 414
at NVorbis.StreamDecoder.Read(Single[] buffer, Int32 offset, Int32 count) in D:\DEV\NVorbis\NVorbis\StreamDecoder.cs:line 346
at NVorbis.VorbisReader.ReadSamples(Single[] buffer, Int32 offset, Int32 count) in D:\DEV\NVorbis\NVorbis\VorbisReader.cs:line 342
at TestApp.VorbisWaveStream.Read(Single[] buffer, Int32 offset, Int32 count) in D:\DEV\NVorbis\TestApp\VorbisWaveStream.cs:line 92
at TestApp.VorbisWaveStream.Read(Byte[] buffer, Int32 offset, Int32 count) in D:\DEV\NVorbis\TestApp\VorbisWaveStream.cs:line 79
at NAudio.Wave.WaveOutBuffer.OnDone()
at NAudio.Wave.WaveOutEvent.DoPlayback()
at NAudio.Wave.WaveOutEvent.PlaybackThread()
TestFiles
directory:PS> Invoke-WebRequest https://raw.githubusercontent.com/bert2/DtmfDetection/master/test/integration/testdata/very_short_dtmf_tones.ogg -OutFile .\TestFiles\4test.ogg
TestApp
project to play 4test.ogg
.Expected: TestApp
should exit with success after playing the file.
Actual: TestApp
crashes with the exception shown above.
The crash happens at the end of the file, so maybe the decoder failed to detect the EOF?
Also, I'm not sure whether my file is corrupted or this is a bug in the implementation. But I'm assuming the latter, because the file works without problems when I'm using v0.9.1 by checking out the tag.
Hello!
I've ran into a seeking issue with this .ogg file: SGM_example.zip
Seek to position 678951
vorbRead.SamplePosition = 678951;
If you then call ReadSamples
, it will throw an IndexOutOfRange exception in ClippingCopyBuffer.
I've found that this is due to the var pos = _packetProvider.SeekTo(samplePosition, 1, GetPacketGranules);
in StreamDecoder.cs returning position that's ahead of the samplePosition.
This results in rollForward being negative and _prevPacketStart negative as well, causing the IndexOutOfRange on next read. Unfortunately I'm not sure how to fix this myself, but I hope this helps!
Some files fail with the error in the title when creating a VorbisReader.
The file works in other programs like Audacity and can also be opened with v0.9.1
Still reproducible #32. Wasn't able to save ogg file, but attached with debugger and saved raw buffer. Was able to play it back.
Channels: 1
Bytes per sample: 4
Sample rate: 44100
buffer.dmp
I want to minimise dependencies in my project by utilising framework dependencies wherever possible
To be able to install the package on a modern TFM ie net 6 and have no dependencies.
Accept the additional dependency
n/a
The new 0.10.3 release appears to have a bug that causes an InvalidDataException
to be thrown with the message "Ran out of packets?!" when seeking/setting the sample position. This appears to be a regression in 0.10.3; it did not happen for me in 0.10.2.
Here is a small sample program that easily reproduces the issue for me:
using NVorbis;
namespace NVorbisTest
{
class Program
{
static void Main()
{
VorbisReader reader = new("test.ogg");
while (reader.SamplePosition < reader.TotalSamples)
reader.SamplePosition += reader.Channels;
}
}
}
I have been able to reproduce this easily with every ogg file I've tried, but just in case here is a test.ogg file that I know reproduces this issue consistently for me.
For convenience, here is the stack trace:
System.IO.InvalidDataException: Ran out of packets?!
at NVorbis.Ogg.PacketProvider.FindPacket(Int32 pageIndex, Int64& granulePos, GetPacketGranuleCount getPacketGranuleCount, Boolean isRecursed)
at NVorbis.Ogg.PacketProvider.SeekTo(Int64 granulePos, Int32 preRoll, GetPacketGranuleCount getPacketGranuleCount)
at NVorbis.StreamDecoder.SeekTo(Int64 samplePosition, SeekOrigin seekOrigin)
at NVorbis.StreamDecoder.set_SamplePosition(Int64 value)
at NVorbis.VorbisReader.set_SamplePosition(Int64 value)
at NVorbisTest.Program.Main() in C:\Users\walt\Desktop\NVorbisTest\Program.cs:line 11
Here is an example.ogg file that demonstrates this issue. Simple load it and seek to sample 1:
VorbisReader reader = new("example.ogg");
reader.SamplePosition = 1;
This throws an InvalidOperationException
"Could not read pre-roll packet! Try seeking again prior to reading more samples." in StreamDecoder.cs
line 607.
I have not found any other ogg files with this particlular issue, so I can't be 100% sure it's not an issue with this file, but it does work in NVorbis 0.10.2, so I assume it's a regression bug.
Hello i was getting _prevPacketStart bigger than _prevPacketEnd after a seek in StreamDecoder
it was doing an INFINITE loop
i Changed line 335 operator == to >= and it fixed the issue for me (the result audio is valid)
Seems like I cannot play certain ogg files. The exception reads: "Granule Position was -1 but page has completed packets."
I'm happy to provide the files when this error happens. foobar2000 can read the file just fine.
@diontools
Continuation of #26 in the old repository.
I've released a fixed version for this.
NVorbis is woefully lacking in UTs. More refactoring is required in the low-level decoding logic to properly accomplish unit testing. Other classes "should be" close or already ready. For this issue, we need to accomplish the refactoring and write the unit tests.
This is particularly killing for apps that rely on web streaming (which is the case for me), as it has to fetch all chunks for even a couple of seconds of seeking.
Upon inspecting the source code, it seems that the "TotalSamples" property might be the culprit, which calls the "GetGranuleCount" function, which in turn fetches all the pages.
public long GetGranuleCount()
{
if (_reader == null) throw new ObjectDisposedException(nameof(PacketProvider));
if (!_reader.HasAllPages)
{
// this will force the reader to attempt to read all pages
_reader.GetPage(int.MaxValue, out _, out _, out _, out _, out _, out _);
}
return _reader.MaxGranulePosition.Value;
}
I'll try to look into maybe using some kind of bisection method to seek to the correct position without having to fetch all the pages, but I am in no way an expert in audio processing etc, so any help would be appreciated.
I was trying to concat header with a single ogg page to get FirstGranulePosition ( in this case 0 ) but reading that stream with NVorbis gives more samples than expected. Is there any reason why that happens?
Update.....
I've actually found out the problem. For some reason, Reading too fast from the stream causes it to give more samples.
Debugging ( simulating slow read )
Without Debug ( fast read )
Update....
It might be possible that debug updates some properties as well.
To reproduce, open Tromboon.ogg and seek to sample 23104:
VorbisReader reader = new("Tromboon.ogg");
reader.SamplePosition = 23104;
This throws a IndexOutOfRangeException
in PacketProvider.CreatePacket
(line 210; _reader.GetPagePackets(pageIndex)
returns an array of length 17 but packetIndex
is 23.)
I have been able to reproduce this with multiple unrelated ogg files.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.