Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Underruns & cracking noises #330

Open
TheDaChicken opened this issue Oct 8, 2023 · 13 comments
Open

Underruns & cracking noises #330

TheDaChicken opened this issue Oct 8, 2023 · 13 comments
Labels

Comments

@TheDaChicken
Copy link

I am getting: Underruns / cracking noises.
Here is a video: https://youtu.be/XMswC9g92ZY
I could send anything like IQ recording etc of any type in the process.

Here is my code model:

  • Getting SDR samples of complex
  • Resampling to NRSC5's constant SAMPLE_RATE
  • Converting to uint8_t for nrsc5.
  • Passing it into nrsc5_pipe_samples_cu8

This is what I am doing for converting from float to uint8_t:

void IQConverterFUC::Process(const DataBuffer<std::complex<float>> &input, DataBuffer<uint8_t> &output)
{
    output.SetSize(input.GetSize() * 2);
    for (int i = 0; i < input.GetSize(); ++i)
    {
        auto I = static_cast<uint8_t>((input[i].real() * 128.0f) + 127.4f);
        auto Q = static_cast<uint8_t>((input[i].imag() * 128.0f) + 127.4f);
        output[2 * i] = I;
        output[2 * i + 1] = Q;
    }
}
@argilo argilo added the bug label Oct 8, 2023
@argilo
Copy link
Collaborator

argilo commented Oct 8, 2023

I would guess that this has the same root cause as #261 (and closely related #177).

@argilo
Copy link
Collaborator

argilo commented Oct 8, 2023

Basically, the library needs to implement proper buffering & delay, and when given input samples it should produce output samples at a fixed ratio. It will be a fair amount of work to get it all right, which is why I haven't taken a stab at it yet.

@TheDaChicken
Copy link
Author

TheDaChicken commented Oct 9, 2023

That would be helpful. I am using PortAudio and PortAudio LOVES to grab samples before they are available. Even just exposing some stuff related to buffering could help.

@TheDaChicken
Copy link
Author

Plus another thing I was thinking about:

Should buffering be implemented in client code or be implemented in the API? The API can just expose stuff related to buffering like latency etc. That way buffering can be managed in any way needed.

@argilo
Copy link
Collaborator

argilo commented Oct 13, 2023

The client code could do some additional buffering of its own if it really needs to, but there will have to be some buffering on the API side to get the latency correct and allow things like analog blending.

@TheDaChicken
Copy link
Author

The client code could do some additional buffering of its own if it really needs to, but there will have to be some buffering on the API side to get the latency correct and allow things like analog blending.

The reason i asked that question is because my program does the analog "blending" itself since it's not implemented in nrsc5. There is no way for me to tell any latency. Plus, the amount of silence I have to add for no-blending feels kind of weird.

@TheDaChicken
Copy link
Author

I want to make your life easier because you may not have much free time.

@TheDaChicken
Copy link
Author

TheDaChicken commented Nov 20, 2023

I want to make your life easier because you may not have much free time.

Should I try to make my own implementation? What's best idea here?

@argilo
Copy link
Collaborator

argilo commented Nov 20, 2023

You're welcome to take a crack at it. I don't have any immediate plans to work on this.

@TheDaChicken
Copy link
Author

TheDaChicken commented Nov 24, 2023

Okay here is what I got out of: 1017s.pdf. PDU contains latency Common Delay Per Stream Delay. That's all I could understand.

latency gives the burst range that HDRadio could give bla bla.

I created a simple buffer that just starts outputting frames after latency. I removed the start silence. It cuts out twice or three times at the start. After that, it is already a big improvement apparently. I had a few clickly noises while I was coding this. Afterward, I didn't hear it anymore.

@FoxxMD
Copy link

FoxxMD commented Dec 18, 2023

@TheDaChicken have you made any more progress? I'm interested in getting this fixed as well...

@TheDaChicken
Copy link
Author

TheDaChicken commented Dec 18, 2023

@TheDaChicken have you made any more progress? I'm interested in getting this fixed as well...

I have made some progress. Still working on it. I made something but it outputs fixed packets at a variable rate...

There are so many things that makes this hard. For example, being accurate. Analog bending would be based on whatever is buffered from some average rate that was calculated in the buffer. Which I guess is fine???

@TheDaChicken
Copy link
Author

TheDaChicken commented Apr 21, 2024

@argilo

Okay, I am trying again pinging since I have a few ideas about solving the problem and it depends.

I did a lot of more testing. Delaying output to output at a fixed ratio would require more delay than a normal receiver. Since there is no easy way of outputting at a fixed ratio since it would require sleeping on another thread, not always accurate, etc unless the library is missing another way to grab packets more quickly. Delaying packets based on maximum latency results in good buffering anyway.

Icecast does a similar thing. It first sends a lot (gives a lot to buffer) and then slows down to "real-time"

Here is what I am proposing:

  • nrsc5_reset_buffer This resets the delay
  • Only allow one channel at a time through callback to ensure the audio is buffered before playback.
  • A function that passes a pointer to some sort of struct. This struct will store context about the buffer. This allows to grab audio from a blocking/non-blocking function instead of a callback to ensure proper buffering on main.c or users using the library. That also makes it possible to open many channels if somehow playing back 2 channels is something the user wants However, this wouldn't be the greatest idea when adding support for FM I would assume in the library.

I think the 3rd one is the best idea.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants