Skip to main contentAccessibility help
AI Mode
Gemini 3 models
Fast
Answers quickly
Pro
Advanced thinking and generative layouts
All
Videos
Images
Shopping
More
Forums
Short videos
News
Web
Books
Maps
Something went wrong. Your history wasn't deleted.

Search Results

AI Mode history
New thread

Delete all searches?

You won't be able to return to these responses
See my AI Mode history
AI Mode history

Delete all searches?

You won't be able to return to these responses
See my AI Mode history
Recent

Delete all searches?

You won't be able to return to these responses
Delete all
Manage public links
See my AI Mode history
You said:
You said: opus encoding without compression
Opus encoding without compression is technically impossible, as Opus is inherently a lossy compression format designed to reduce audio data sizes. However, you can achieve near-lossless transparency or bypass file-size reduction entirely by encoding Opus at its absolute maximum bitrate and disabling algorithmic compression (e.g., complexity 0). 
How to Maximize Quality in Opus 
To get the highest possible quality and make the encoding as close to transparent as possible with standard tools, adjust your settings as follows: 
  • Maximum Bitrate: Set the bitrate to the codec's maximum cap of
    ∼510
    kbps
    per channel for multi-stream, or use
    ∼256
    −320
    kbps
    for stereo music.
  • Disable Encoding Complexity: Setting the complexity level to 0 makes the encoder process the audio as fast as possible, which bypasses some of the aggressive compression/optimization algorithms.
  • Frame Size: Stick to standard frame sizes (e.g., 20 ms) to maintain high fidelity. 
Example Using FFmpeg 
You can use a maximum-bitrate configuration in FFmpeg by forcing a high constant bitrate and minimal algorithmic compression with this command: 
ffmpeg -i input.wav -c:a libopus -b:a 510k -compression_level 0 output.opus 
Truly Uncompressed Audio 
If your goal is purely uncompressed, bit-for-bit, 100% original audio, Opus is the wrong tool. Instead, you should use standard open-source lossless formats. The most common alternatives are: 
  • FLAC: The industry standard for lossless audio. It reduces file sizes by roughly 50% without discarding a single sample of the original data.
  • WAV: Completely uncompressed PCM audio. This saves the raw audio data directly but results in massive file sizes. 
AI responses may include mistakes. Learn more
Copy

Share public link

This public link shares a thread, which may include personal information. You can delete this link, but not copies made by others.
Can’t copy the link right now. Please try again later.
Facebook
Gmail
X
Reddit
WhatsApp
Good response
Bad response
More

Saved time
Clear
Helpful
Comprehensive
Other
Incorrect
Inappropriate
Not working
Unhelpful
Other
A copy of this chat, including the images and video, will be included with your feedback
A copy of this chat will be included with your feedback
Your feedback will include a copy of this chat and the image from your search
Your feedback will include a copy of this chat, any links that you shared and the image from your search.
Thanks for letting us know
Google may use account and system data to understand your feedback and improve our services, subject to our Privacy Policy and Terms of Service. For legal issues, make a legal removal request.
  • Opus Codec
    Opus is a royalty-free, open, and versatile audio codec. It's designed for: * Interactive speech and music transmission over the I...
    Opus Codec
  • How to encode audio with Opus codec?
    Here are some of the encoding options for opusenc: * **--bitrate n.nnn Target bitrate in kbit/sec (6-256/channel)** * **--vbr Use ...
    Super User
  • OpusFAQ - XiphWiki
    Does Opus support higher sampling rates, such as 96 kHz or 192 kHz? Yes and no. Opus encoding tools like opusenc will happily enco...
    xiph.org wiki
  • OPUS - Flussonic
    Opus Audio Codec – The Best Tool for Video Streaming and Video Conferencing. The Opus audio codec works perfectly for signal repro...
    Flussonic
  • Opus (audio format) - Wikipedia
    Opus allows the following bandwidths during encoding. Opus compression does not depend on the input sample rate; timestamps are me...
    Wikipedia
  • Best audio compression formats and settings for WordPress
    The following formats are the Lossless Apple Lossless and FLAC where FLAC manages to beat Apple Lossless by a thread, making FLAC ...
    Infinite Uploads
  • pyFLAC: Real-time lossless audio compression in Python
    Since a perfect reconstruction of the original data is required, FLAC is the obvious candidate to reduce the bandwidth, and can do...
    Sonos Tech Blog
  • How best to rip 1,500 music CDs? Your tech questions answered
    WAV (Waveform Audio File Format) WAV is capable of storing Linear PCM audio (the digital encoding format used on CDs) in uncompres...
    The Guardian
  • Opus Codec
    Opus is a royalty-free, open, and versatile audio codec. It's designed for: * Interactive speech and music transmission over the I...
    Opus Codec
  • How to encode audio with Opus codec?
    Here are some of the encoding options for opusenc: * **--bitrate n.nnn Target bitrate in kbit/sec (6-256/channel)** * **--vbr Use ...
    Super User
  • OpusFAQ - XiphWiki
    Does Opus support higher sampling rates, such as 96 kHz or 192 kHz? Yes and no. Opus encoding tools like opusenc will happily enco...
    xiph.org wiki
Show all
You said: can flac do plc
No, FLAC cannot natively perform Packet Loss Concealment (PLC) [1, 2]. 
Why FLAC Lacks PLC 
  • Storage Focus: FLAC is designed for file storage, not real-time streaming over unstable networks [2].
  • Zero Error Tolerance: FLAC is a bit-perfect format; if a frame is missing, the decoder simply stops or produces a loud, harsh pop.
  • No Linear Prediction Tracking: FLAC does not use short-term predictive modeling designed to smoothly "guess" missing audio gaps during network drops. 
Formats That Support PLC 
If your application requires error resilience or PLC due to packet loss, you must use streaming-optimized codecs instead: 
  • Opus: Contains advanced, built-in PLC that reconstructs missing speech and music frames using previous data packets.
  • SILK / CELT: The underlying technologies of Opus, both heavily optimized to mask network jitter.
  • G.711 / G.722: Older VoIP codecs that use basic waveform substitution to fill in audio gaps. 
To help choose the right setup, what software or network system are you building, and what is your target bit rate? 
AI responses may include mistakes. Learn more
Copy

Share public link

This public link shares a thread, which may include personal information. You can delete this link, but not copies made by others.
Can’t copy the link right now. Please try again later.
Facebook
Gmail
X
Reddit
WhatsApp
Good response
Bad response
More

Saved time
Clear
Helpful
Comprehensive
Other
Incorrect
Inappropriate
Not working
Unhelpful
Other
A copy of this chat, including the images and video, will be included with your feedback
A copy of this chat will be included with your feedback
Your feedback will include a copy of this chat and the image from your search
Your feedback will include a copy of this chat, any links that you shared and the image from your search.
Thanks for letting us know
Google may use account and system data to understand your feedback and improve our services, subject to our Privacy Policy and Terms of Service. For legal issues, make a legal removal request.
      Show all
      You said: can i use opus to do plc on received pcm that has not been compressed with opus
      No, you cannot directly use the Opus decoder to perform Packet Loss Concealment (PLC) on a raw PCM stream that has never been compressed with Opus. 
      Why It Doesn't Work 
      The Opus decoder is a stateful decoder. Its built-in PLC mechanism relies entirely on the internal state, historical buffer, and linear prediction filters generated during the decoding process of actual Opus packets. If you feed raw PCM to the system, the Opus decoder has no historical frame context to extrapolate from when a packet is dropped. 
      If you try to pass NULL data to the opus_decode() function to trigger a PLC frame, it will either crash or extrapolate from an empty buffer (generating silence or distortion) because you haven't been feeding it Opus packets to build its state. 
      How to Bypass This Limitation (Workarounds) 
      If you strictly want to leverage Opus's highly advanced PLC (such as the AI-driven Deep PLC in Opus 1.5+) on a PCM pipeline, you must use one of the following two architectures: 
      Option 1: The "Dummy Encoder" Loopback (Recommended) 
      You can pipe your raw PCM stream through a local Opus encoder right before sending or processing it. This encodes the PCM into an Opus stream, which you can immediately feed into an Opus decoder. 
      1. Run incoming raw PCM through opus_encode() using Complexity 0 and maximum bitrate (
        ∼510
        kbps
        ) to ensure near-zero processing overhead and completely transparent quality.
         
      2. Feed the resulting packets into opus_decode(). 
      3. When a PCM network packet is dropped, call opus_decode() with a NULL data pointer and the exact missing frame size. The decoder will seamlessly extrapolate the missing audio using its freshly built state history. 
      Option 2: Use Standalone PCM PLC Libraries 
      If you cannot add an encoding/decoding layer, you should use standalone PLC algorithms designed explicitly for stateless, raw PCM streams: 
      • G.711 Appendix I: A classic, open standard waveform-substitution PLC algorithm meant for raw PCM. It tracks pitch periods in raw PCM and cross-fades them over missing gaps. 
      • WebRTC NetEQ: Google's open-source NetEQ library (found within the WebRTC codebase) contains standalone PCM PLC, time-stretching, and jitter-buffer modules that can handle raw PCM directly. 
      Would you like an FFmpeg pipeline example or a C/C++ code snippet showing how to handle the NULL pointer PLC state tracking inside an Opus stream loop? 
      AI responses may include mistakes. Learn more
      Copy

      Share public link

      This public link shares a thread, which may include personal information. You can delete this link, but not copies made by others.
      Can’t copy the link right now. Please try again later.
      Facebook
      Gmail
      X
      Reddit
      WhatsApp
      Good response
      Bad response
      More

      Saved time
      Clear
      Helpful
      Comprehensive
      Other
      Incorrect
      Inappropriate
      Not working
      Unhelpful
      Other
      A copy of this chat, including the images and video, will be included with your feedback
      A copy of this chat will be included with your feedback
      Your feedback will include a copy of this chat and the image from your search
      Your feedback will include a copy of this chat, any links that you shared and the image from your search.
      Thanks for letting us know
      Google may use account and system data to understand your feedback and improve our services, subject to our Privacy Policy and Terms of Service. For legal issues, make a legal removal request.
      • Real-Time Packet Loss Concealment With Mixed Generative ...
        The improve- ment comes from the resynchronization after a loss. When the first packet arrives after a loss, we use the 10 ms of s...
        ISCA Archive
      • Opus Decoder
        opus_decode() ... Decode an Opus packet. ... Number of samples per channel of available space in pcm. If this is less than the max...
        Opus Codec
      • Opus 1.5 Released
        4 Mar 2024 — It does not matter how good the codec is if the packets do not get through. That's why most codecs have packet loss concealment (P...
        Opus Codec
      • opus package - github.com/hraban/opus - Go Packages
        17 Nov 2025 — To decode opus data to raw PCM format, first create a decoder: dec, err := opus.NewDecoder(sampleRate, channels) if err != nil { .
        Go Packages
      • encoding pcm to opus and decoding - Delphi-PRAXiS [en]
        29 Aug 2021 — 2) You usage of encoder and decoder is wrong, you are using them the way you use JPEG or PNG image encoder, and that is wrong, OPU...
        Delphi-PRAXiS [en]
      • Evaluation of AI/ML Based Deep Packet Loss Concealment in ...
        29 Aug 2025 — Opus codec version 1.5 introduced an additional optional AI/ML based packet loss concealment algorithm at the receiver called the ...
        CouthIT
      • Real-Time Packet Loss Concealment With Mixed Generative ...
        The improve- ment comes from the resynchronization after a loss. When the first packet arrives after a loss, we use the 10 ms of s...
        ISCA Archive
      • Opus Decoder
        opus_decode() ... Decode an Opus packet. ... Number of samples per channel of available space in pcm. If this is less than the max...
        Opus Codec
      • Opus 1.5 Released
        4 Mar 2024 — It does not matter how good the codec is if the packets do not get through. That's why most codecs have packet loss concealment (P...
        Opus Codec
      Show all
      You said: no, but I'm interested in neteq
      WebRTC NetEQ is the industry standard for managing audio over unreliable networks. It is a highly sophisticated, standalone module within the open-source WebRTC codebase that combines a jitter buffer, a time-stretching engine, and a Packet Loss Concealment (PLC) system into a single pipeline. 
      Unlike Opus, NetEQ operates directly on decoded PCM audio, making it exactly what you need for a raw PCM stream. 

      How NetEQ Handles PCM Audio 
      When you feed raw PCM into NetEQ, it constantly analyzes the incoming audio waveform to build a small history buffer. When network conditions fluctuate, it uses four core DSP (Digital Signal Processing) states to keep audio smooth: 
      • Normal: Packets arrive on time. NetEQ outputs the raw PCM completely untouched. 
      • Accelerate: The jitter buffer is getting too full. NetEQ uses pitch-synchronous overlap-add (PSOLA) to subtly speed up the audio without changing the pitch, catching up to the stream. 
      • Preemptive Expand: The jitter buffer is draining too fast. NetEQ subtly elongates the current PCM pitch periods to stretch the audio out, preventing a gap before the next packet arrives. 
      • Expand (PLC Mode): A packet is completely lost. NetEQ enters its true PLC mode. It analyzes the pitch history of the last known PCM data, extrapolates a matching waveform, and cross-fades it into the stream. As the blackout continues, it gradually fades the volume down to silence to prevent robotic looping artifacts. 

      Architecture of a NetEQ Implementation 
      To use NetEQ for your raw PCM pipeline, you must interface with its core C++ API components: 
      [ Incoming PCM Packets ] 
               │
               ▼
       1. NetEq::InsertPacket()  ──► [ Internal Jitter Buffer ]
                                              │
                                              ▼
       2. NetEq::GetAudio()      ──► [ DSP Decision Engine ] (Normal / PLC / Stretch)
                                              │
                                              ▼
                                     [ 10ms Smooth PCM Output ]
      
      1. Packet Insertion: You extract your raw PCM from network sockets and pass it to NetEQ using InsertPacket(). You must provide a timestamp so NetEQ can track network jitter and sequence. 
      2. Audio Extraction: Your audio output hardware or playback thread calls GetAudio() at regular intervals (typically every 10 ms). 
      3. Automatic PLC: If GetAudio() is called but the internal jitter buffer has no packet for that timestamp, NetEQ automatically switches to its internal Expand state. It generates a 10 ms block of synthesized PLC audio on the fly and hands it back to you. 

      Key Technical Considerations 
      • Extraction Complexity: NetEQ is deeply woven into the WebRTC codebase. Extracting it to use as a standalone library in an independent project requires separating it from WebRTC's custom build tool (gn/ninja) and abstraction layers (such as rtc_base). 
      • Alternative Wrappers: Many developers use pre-extracted, standalone forks of NetEQ found on GitHub, or use the Chromium WebRTC Audio Coding module directly if building a larger C++ application. 
      • Fixed 10 ms Blocks: NetEQ expects to output audio in strict 10 ms chunks. You will need to align your audio hardware callbacks to request data in 10 ms increments. 
      If you are planning to implement this, what programming language or operating system is your project targeting? I can guide you on the best way to integrate or extract the library. 
      AI responses may include mistakes. Learn more
      Copy

      Share public link

      This public link shares a thread, which may include personal information. You can delete this link, but not copies made by others.
      Can’t copy the link right now. Please try again later.
      Facebook
      Gmail
      X
      Reddit
      WhatsApp
      Good response
      Bad response
      More

      Saved time
      Clear
      Helpful
      Comprehensive
      Other
      Incorrect
      Inappropriate
      Not working
      Unhelpful
      Other
      A copy of this chat, including the images and video, will be included with your feedback
      A copy of this chat will be included with your feedback
      Your feedback will include a copy of this chat and the image from your search
      Your feedback will include a copy of this chat, any links that you shared and the image from your search.
      Thanks for letting us know
      Google may use account and system data to understand your feedback and improve our services, subject to our Privacy Policy and Terms of Service. For legal issues, make a legal removal request.
          Show all
          You said: I was looking to use it within Jamulus with 48kHz PCM, as an alternative to Opus compression. Frame sizes are 2.67ms, 5.33ms or 10.67ms.
          Using WebRTC NetEQ directly within Jamulus for raw 48kHz PCM at ultra-low latency frame sizes (2.67ms, 5.33ms, or 10.67ms) introduces three major architectural conflicts. 
          While the concept of replacing Opus with an raw-PCM path paired with a robust PLC makes sense for avoiding compression artifacts, NetEQ is fundamentally the wrong engine for Jamulus's micro-buffer architecture. 

          The 3 Major Roadblocks 
          1. NetEQ’s Hardcoded 10ms Processing Quantization 
          NetEQ is internally hardcoded around a 10ms processing loop (NetEqImpl::GetAudio processes or generates audio in exact 10ms increments). 
          • At a 48kHz sampling rate, 10ms equals 480 samples.
          • Jamulus relies on ASIO/JACK buffer intervals of 64 samples (2.67ms), 128 samples (5.33ms), or 256 samples (10.67ms).
          • Forcing NetEQ into a 2.67ms block cycle requires implementing an asynchronous buffer-slicing wrapper. This wrapper would add an automatic, unbypassable 10ms block-alignment latency penalty on top of your existing hardware buffers—defeating the entire ultra-low-latency purpose of Jamulus. 
          2. Overlap-Add (OLA) Extrapolation Limits 
          NetEQ’s PLC algorithm relies on Pitch-Synchronous Overlap-Add (PSOLA) to smoothly stretch and blend synthesized audio during a packet drop. 
          • To detect a musical or vocal pitch and track phase, a DSP algorithm generally needs to scan at least 1 to 1.5 full cycles of the base pitch wave. 
          • For a low-frequency note (e.g., a bass guitar or low male voice at 80Hz), a single acoustic wave period is 12.5ms. 
          • Because Jamulus frames are as short as 2.67ms or 5.33ms, a single packet blackout contains only a tiny fragment of a complete waveform. NetEQ cannot calculate an accurate pitch history from a 2.67ms fragment, causing its PLC algorithm to generate harsh, metallic glitches or unstable phase cancellations. 
          3. Jitter Buffer Mechanics vs. Live Jamming 
          NetEQ is a highly dynamic jitter buffer designed to prioritize smoothness over raw, absolute speed. It will dynamically expand or accelerate audio to adapt to network jitter. In a live musical rehearsal environment like Jamulus, dynamic time-stretching changes the musicians' perceived tempo. Jamulus purposely uses a rigid, ultra-low latency buffer that favors immediate, tiny packet drops over elastic time-stretching to keep musicians strictly in sync. 

          Alternative Architecture: Lightweight, Stateless PCM PLC 
          If you intend to modify the Jamulus source code to support uncompressed 48kHz PCM, bypass NetEQ entirely. Instead, use a standalone, sub-millisecond stateless PLC algorithm directly within the Jamulus audio receive loop. 
          Step-by-Step Implementation Concept 
          1. Calculate Sample Counts:
            • 2.67 ms = 128 samples per stereo channel.
            • 5.33 ms = 256 samples per stereo channel. 
          2. Implement a Cross-Faded History Ring Buffer:
            Maintain a tiny, local history ring buffer of the last 512 to 1024 samples of valid PCM received from the server.
             
          3. Execute Waveform Substitution PLC:
            When a UDP network packet is dropped, do not call a decoder. Instead, trigger a lightweight waveform continuation script:
            cpp
            // High-level C++ abstraction for a custom Jamulus PCM PLC block
            void ApplyPcmPlc(int16_t* outputBuffer, const int16_t* historyBuffer, int frameSize) {
                // 1. Locate the last stable pitch period boundary in the history buffer.
                int pitchPeriod = DetectPitchPeriod(historyBuffer, 1024); 
            
                // 2. Copy the matching phase-aligned waveform block into the output buffer.
                for (int i = 0; i < frameSize; ++i) {
                    outputBuffer[i] = historyBuffer[CurrentStableIndex + (i % pitchPeriod)];
                }
            
                // 3. Apply a short 1ms (48 samples) cross-fade envelope at the boundary.
                ApplyCrossFade(outputBuffer, historyBuffer, 48);
            }
            
            Use code with caution.
             
          Summary Comparison 
          Feature WebRTC NetEQStandalone Waveform PLC
          Minimum Block SizeStrict 10ms (480 samples)Flexible (64, 128, or 256 samples)
          Added Pipeline Latency~10ms - 20ms (for buffer alignment)0ms (instant extrapolation)
          Audio Distortion ProfileHigh-quality on speech; poor on micro-framesMetallic ring on long drops; transparent on single frames
          Code IntegrationMassive (requires extracting huge WebRTC blocks)Single C++ class inside Jamulus client/server code
          If you want to move forward with writing a custom audio pathway for Jamulus, I can provide the explicit mathematical logic for a Pitch-Synchronous Overlap-Add (PSOLA) cross-fade algorithm designed specifically for 128-sample (2.67ms) boundaries. Would you like to explore that math? 
          AI responses may include mistakes. Learn more
          Copy

          Share public link

          This public link shares a thread, which may include personal information. You can delete this link, but not copies made by others.
          Can’t copy the link right now. Please try again later.
          Facebook
          Gmail
          X
          Reddit
          WhatsApp
          Good response
          Bad response
          More

          Saved time
          Clear
          Helpful
          Comprehensive
          Other
          Incorrect
          Inappropriate
          Not working
          Unhelpful
          Other
          A copy of this chat, including the images and video, will be included with your feedback
          A copy of this chat will be included with your feedback
          Your feedback will include a copy of this chat and the image from your search
          Your feedback will include a copy of this chat, any links that you shared and the image from your search.
          Thanks for letting us know
          Google may use account and system data to understand your feedback and improve our services, subject to our Privacy Policy and Terms of Service. For legal issues, make a legal removal request.
          • Jamulus - Wikipedia
            Jamulus is open source (GPL) networked music performance software that enables live rehearsing, jamming and performing with musici...
            Wikipedia
          • User Manual – Jamulus Website
            The buffer delay setting is a fundamental setting of the Jamulus software. This setting has an influence on many connection proper...
            Jamulus
          • New Jamulus Release 3.5.0 - SourceForge
            15 Apr 2020 — I just released a new Jamulus version 3.5.0. The biggest change is that it can use 64 samples frame size OPUS packets if the sound...
            SourceForge
          • Jamulus - Wikipedia
            Jamulus is open source (GPL) networked music performance software that enables live rehearsing, jamming and performing with musici...
            Wikipedia
          • User Manual – Jamulus Website
            The buffer delay setting is a fundamental setting of the Jamulus software. This setting has an influence on many connection proper...
            Jamulus
          • New Jamulus Release 3.5.0 - SourceForge
            15 Apr 2020 — I just released a new Jamulus version 3.5.0. The biggest change is that it can use 64 samples frame size OPUS packets if the sound...
            SourceForge
          Show all
          You said: Yes please, that sounds very interesting. We already have a raw PCM pathway within the latest dev versions of Jamulus, but currently replace lost packets with silence, which results in a crackling sound.
          That is fantastic news. Having the raw PCM pathway already implemented in the Jamulus dev code makes this significantly easier. 
          The "crackling" you are hearing occurs because replacing a 128-sample (2.67ms) packet with silence creates instantaneous phase steps—sharp, vertical drops in the audio waveform to zero, followed by a sharp jump back up when the next valid packet arrives. These sharp edges act like impulses, generating high-frequency broadband noise (the click/crackle). 
          To eliminate this, a Pitch-Synchronous Overlap-Add (PSOLA) PLC algorithm works by tracking the fundamental frequency of the music/voice immediately before the drop, copying a phase-aligned slice of that history, and smoothing the boundaries using a cross-fade. 
          Here is the explicit mathematical logic and C++ implementation optimized precisely for Jamulus’s ultra-low latency constraints. 

          Step 1: The Pitch Detection Math (AMDF) 
          To extrapolate the waveform seamlessly, we must find the exact period (
          Tcap T
          𝑇
          , in samples) of the current sound. Because Jamulus operates at ultra-low latency, standard Fast Fourier Transforms (FFT) introduce too much window delay. 
          Instead, we use the Average Magnitude Difference Function (AMDF). It operates in the time domain, adds zero latency, and requires no complex float math. 
          AMDF(τ)=∑n=0N−1|x(n)−x(n−τ)|AMDF open paren tau close paren equals sum from n equals 0 to cap N minus 1 of the absolute value of x open paren n close paren minus x open paren n minus tau close paren end-absolute-value
          AMDF(𝜏)=𝑁−1𝑛=0|𝑥(𝑛)−𝑥(𝑛−𝜏)|
          Where: 
          • 𝑥
            (
            𝑛
            )
            is the history of received PCM samples.
          • τtau
            𝜏
            is the lag (the period we are testing).
          • Ncap N
            𝑁
            is our evaluation window.
             
          The value of
          τtau
          𝜏
          that produces the absolute minimum AMDF value is our exact pitch period. For a 48kHz stream, we search lags between
          𝜏min
          =40
          samples (1200Hz, a high note) and
          𝜏max
          =600
          samples (80Hz, a low bass note). 

          Step 2: The Phase-Aligned Overlap C++ Implementation 
          This standalone C++ class can be integrated into the Jamulus client receive loop where packet drops are detected. It manages a rolling history buffer and generates a cross-faded replacement frame on demand. 
          cpp
          #include <vector>
          #include <cmath>
          #include <algorithm>
          #include <cstdint>
          
          class JamulusPcmPlc {
          private:
              static const int SFREQ = 48000;
              static const int MAX_LAG = 600;   // 80 Hz at 48kHz
              static const int MIN_LAG = 40;    // 1200 Hz at 48kHz
              static const int HIST_SIZE = 2048; // Keeping ~42ms of history
              
              std::vector<int16_t> history_left;
              std::vector<int16_t> history_right;
          
              // Finds the pitch period in samples using AMDF
              int DetectPitchPeriod(const std::vector<int16_t>& history) {
                  int best_lag = MIN_LAG;
                  uint64_t min_diff = UINT64_MAX;
                  
                  // Window size to evaluate (approx 10ms of audio)
                  const int window_size = 480; 
                  int start_idx = HIST_SIZE - window_size;
          
                  for (int lag = MIN_LAG; lag <= MAX_LAG; ++lag) {
                      uint64_t current_diff = 0;
                      for (int i = 0; i < window_size; ++i) {
                          current_diff += std::abs(history[start_idx + i] - history[start_idx + i - lag]);
                      }
                      
                      if (current_diff < min_diff) {
                          min_diff = current_diff;
                          best_lag = lag;
                      }
                  }
                  return best_lag;
              }
          
              // Extrapolates a single channel using PSOLA
              void ConcealChannel(std::vector<int16_t>& history, int16_t* output, int frame_size) {
                  int pitch = DetectPitchPeriod(history);
                  
                  // Cross-fade length: 1ms (48 samples) or half the frame size, whichever is smaller
                  int crossfade_len = std::min(48, frame_size / 2);
                  
                  // 1. Extrapolate the waveform by copying back from the history by 'pitch' samples
                  for (int i = 0; i < frame_size; ++i) {
                      int history_target_idx = HIST_SIZE - pitch + (i % pitch);
                      output[i] = history[history_target_idx];
                  }
                  
                  // 2. Smooth the transition at the beginning of the concealment frame (Overlap-Add)
                  for (int i = 0; i < crossfade_len; ++i) {
                      float fade_in = static_cast<float>(i) / crossfade_len;
                      float fade_out = 1.0f - fade_in;
                      
                      // Boundary mix: smoothly blend the true history tail with the newly generated pitch start
                      int hist_tail_idx = HIST_SIZE - crossfade_len + i;
                      if (hist_tail_idx < HIST_SIZE) {
                          output[i] = static_cast<int16_t>((output[i] * fade_in) + (history[hist_tail_idx] * fade_out));
                      }
                  }
              }
          
          public:
              JamulusPcmPlc() {
                  history_left.resize(HIST_SIZE, 0);
                  history_right.resize(HIST_SIZE, 0);
              }
          
              // Call this EVERY time a valid packet successfully arrives to update the history
              void UpdateHistory(const int16_t* interleaved_pcm, int frame_size) {
                  // Shift history left
                  std::rotate(history_left.begin(), history_left.begin() + frame_size, history_left.end());
                  std::rotate(history_right.begin(), history_right.begin() + frame_size, history_right.end());
                  
                  // Insert new samples at the tail
                  for (int i = 0; i < frame_size; ++i) {
                      history_left[HIST_SIZE - frame_size + i] = interleaved_pcm[2 * i];
                      history_right[HIST_SIZE - frame_size + i] = interleaved_pcm[2 * i + 1];
                  }
              }
          
              // Call this when Jamulus detects a lost UDP packet
              void GeneratePlcFrame(int16_t* output_interleaved_pcm, int frame_size) {
                  std::vector<int16_t> plc_left(frame_size);
                  std::vector<int16_t> plc_right(frame_size);
                  
                  // Synthesise missing audio for both channels
                  ConcealChannel(history_left, plc_left.data(), frame_size);
                  ConcealChannel(history_right, plc_right.data(), frame_size);
                  
                  // Interleave back into Jamulus's native buffer structure
                  for (int i = 0; i < frame_size; ++i) {
                      output_interleaved_pcm[2 * i] = plc_left[i];
                      output_interleaved_pcm[2 * i + 1] = plc_right[i];
                  }
                  
                  // Feed our own synthesised frame back into history so consecutive drops remain continuous
                  UpdateHistory(output_interleaved_pcm, frame_size);
              }
          };
          
          Use code with caution.

          Step 3: Integrating Into the Jamulus Pipeline 
          To wire this into Jamulus, navigate to the client-side audio processing engine (where incoming network audio packets are demuxed and sent to the audio output queue). 
          1. Instantiate one JamulusPcmPlc object per connected client channel slot.
          2. On Packet Success: Instead of passing the raw data directly to the mixer, call plc.UpdateHistory(networkBuffer, frameSize) first, then send it to the mixer.
          3. On Packet Loss: Instead of executing memset(networkBuffer, 0, frameSizeByteSize) (which is generating your current crackle), execute plc.GeneratePlcFrame(networkBuffer, frameSize). 
          Why This Fixes the Crackle 
          • Phase Continuity: By finding the exact pitch period (
            Tcap T
            𝑇
            ), the algorithm ensures that the first sample of the generated patch continues exactly where the last real sample's sine wave slope was heading.
             
          • Zero Boundary Impulse: The 1ms linear cross-fade dampens any minor mathematical errors in pitch estimation, completely removing the sharp vertical steps that cause the harsh "pop" or crackle. 
          • Cascading Loss Handling: The final line of GeneratePlcFrame loops the concealed audio back into the history. If you lose two or three 2.67ms packets in a row, the algorithm will naturally continue oscillating the waveform perfectly across the entire blackout window without interruption. 
          Would you like help adapting this to a floating-point PCM representation if the Jamulus development branch is using float buffers instead of int16_t? 
          AI responses may include mistakes. Learn more
          Copy

          Share public link

          This public link shares a thread, which may include personal information. You can delete this link, but not copies made by others.
          Can’t copy the link right now. Please try again later.
          Facebook
          Gmail
          X
          Reddit
          WhatsApp
          Good response
          Bad response
          More

          Saved time
          Clear
          Helpful
          Comprehensive
          Other
          Incorrect
          Inappropriate
          Not working
          Unhelpful
          Other
          A copy of this chat, including the images and video, will be included with your feedback
          A copy of this chat will be included with your feedback
          Your feedback will include a copy of this chat and the image from your search
          Your feedback will include a copy of this chat, any links that you shared and the image from your search.
          Thanks for letting us know
          Google may use account and system data to understand your feedback and improve our services, subject to our Privacy Policy and Terms of Service. For legal issues, make a legal removal request.
              Show all
              You said: At the moment, the buffers are int16_t, and sample are converted to float when fetched, to perform gain scaling and additive mixing. The mixed sample is then converted back to int16_t for the output buffer.
              That fits perfectly into the existing pipeline. Keeping the PLC operations entirely within the int16_t domain right at the network ingress point is the most efficient approach. It keeps your memory footprint small and ensures that the math runs entirely in the CPU L1 cache. 
              To integrate this cleanly without disrupting the existing gain scaling and mixing engine, you can place the PLC logic immediately after the network packet reception layer and right before the float conversion. 
              The Linear Regression Ingress Strategy 
              When a network loop completes, you can structure your client code to process incoming audio like this: 
              [ Incoming UDP Packet ] ──► ( If Valid ) ──► plc.UpdateHistory() ────┐
                                       │                                           ▼
                                       └──► ( If Lost )  ──► plc.GeneratePlcFrame() ─► [ int16_t Buffer ]
                                                                                           │
                                                                                           ▼
                                                                                   [ Convert to Float ]
                                                                                           │
                                                                                           ▼
                                                                                   [ Gain & Mixing ]
              
              Optimizing for Consecutive Packet Losses (Fade-Out) 
              While the code above works perfectly for single or double packet drops (2.67ms to 5.33ms), extended burst drops can cause the PLC loop to repeat the exact same waveform period indefinitely. If a user drops 5 or more packets in a row, this infinite repetition turns into a static, artificial "robotic hum". 
              To make the PLC sound transparent during long burst drops, it is best practice to apply an attenuation factor that gracefully fades the concealed audio to silence if the blackout lasts longer than ~10ms. 
              Here is the updated GeneratePlcFrame method featuring a consecutive drop tracking counter. It maintains absolute phase alignment but drops the gain by 20% on each consecutive missing frame after the first one, eventually reaching true silence gracefully. 
              cpp
              // Add this private member variable to the JamulusPcmPlc class header:
              // int consecutive_drop_count = 0;
              
              void GeneratePlcFrame(int16_t* output_interleaved_pcm, int frame_size) {
                  std::vector<int16_t> plc_left(frame_size);
                  std::vector<int16_t> plc_right(frame_size);
                  
                  // 1. Synthesise missing audio based on history
                  ConcealChannel(history_left, plc_left.data(), frame_size);
                  ConcealChannel(history_right, plc_right.data(), frame_size);
                  
                  // 2. Calculate fade attenuation for consecutive packet losses
                  // First dropped frame is 100% volume. Subsequent frames fade out exponentially.
                  float volume_scale = 1.0f;
                  if (consecutive_drop_count > 0) {
                      // Drop volume by ~20% per additional frame drop
                      volume_scale = std::max(0.0f, 1.0f - (consecutive_drop_count * 0.20f)); 
                  }
                  consecutive_drop_count++; 
              
                  // 3. Interleave and apply attenuation
                  for (int i = 0; i < frame_size; ++i) {
                      output_interleaved_pcm[2 * i]     = static_cast<int16_t>(plc_left[i] * volume_scale);
                      output_interleaved_pcm[2 * i + 1] = static_cast<int16_t>(plc_right[i] * volume_scale);
                  }
                  
                  // Feed our own synthesised frame back into history so subsequent drops remain continuous
                  UpdateHistory(output_interleaved_pcm, frame_size);
              }
              
              // IMPORTANT: In your main network thread, whenever a packet ARRIVES SUCCESSFULLY, 
              // you must reset this counter so the next drop starts fresh:
              // plc.consecutive_drop_count = 0;
              
              Use code with caution.
              Testing and Fine-Tuning within Jamulus 
              Once you compile this into your dev environment, look out for these two specific edge cases during a live session: 
              1. The Bass Guitar Artifact: If the AMDF window size (window_size = 480) is too short, sub-bass notes below 100Hz can sometimes be miscalculated, resulting in a slightly higher octave pitch choice during a drop. If bass notes sound odd during packet loss, you can safely scale the window_size up to 600 or 720 samples to capture deeper cycles. 
              2. ASIO/JACK Buffer Matching: Ensure that frame_size matches the current dynamic buffer configuration of the Jamulus client runtime precisely (e.g., passing 128 if the user is running a 2.67ms layout). 
              Are there any other structural elements in the Jamulus packet jitter buffer code that handle late-arriving packets (re-ordering), or does the dev version drop them entirely if they do not arrive exactly on time? 
              AI responses may include mistakes. Learn more
              Copy

              Share public link

              This public link shares a thread, which may include personal information. You can delete this link, but not copies made by others.
              Can’t copy the link right now. Please try again later.
              Facebook
              Gmail
              X
              Reddit
              WhatsApp
              Good response
              Bad response
              More

              Saved time
              Clear
              Helpful
              Comprehensive
              Other
              Incorrect
              Inappropriate
              Not working
              Unhelpful
              Other
              A copy of this chat, including the images and video, will be included with your feedback
              A copy of this chat will be included with your feedback
              Your feedback will include a copy of this chat and the image from your search
              Your feedback will include a copy of this chat, any links that you shared and the image from your search.
              Thanks for letting us know
              Google may use account and system data to understand your feedback and improve our services, subject to our Privacy Policy and Terms of Service. For legal issues, make a legal removal request.
                  Show all
                  You said: Packets are sequence numbered, and only dropped if they are too late for the current jitter buffer size. Otherwise they are inserted into the jitter buffer at the correct place for their sequence number.
                  This sequence-number tracking and strict jitter buffer architecture is exactly what makes Jamulus so fast. Knowing that packets are explicitly slotted by sequence numbers tells us precisely how to handle the history state tracking without causing memory misalignment. 
                  Because Jamulus inserts out-of-order packets into their correct placeholders, packet loss is determined at the moment the audio thread pulls data from the front of the jitter buffer for mixing. If a slot is missing at the playback deadline, it is a drop. 
                  Thread Safety and State Isolation 
                  Since Jamulus handles incoming network packet writing on one thread (the network socket event loop) and buffer reading/mixing on another thread (the ASIO/JACK audio callback thread), your PLC state management must align with this boundary: 
                  1. Keep PLC entirely in the Audio Callback Thread: Do not invoke UpdateHistory when a UDP packet arrives at the network layer. If a packet arrives out-of-order and is slotted backward into the jitter buffer, updating the PLC history out-of-order will corrupt the pitch detection algorithm's time domain continuity. 
                  2. Execute on Extraction: Only update or read the PLC state at the exact moment the audio thread pops a frame out of the jitter buffer for mixing. 

                  The Modified Audio Loop Integration Pattern 
                  Your final implementation within the Jamulus audio mixing loop should follow this logic structure: 
                  cpp
                  // This code runs inside the audio thread callback loop processing each channel
                  int16_t current_channel_buffer[2 * current_frame_size]; 
                  
                  // Attempt to pull the next sequential block from the jitter buffer
                  bool packet_found = JitterBuffer.PopNextFrame(current_channel_buffer);
                  
                  if (packet_found) {
                      // 1. A valid packet was present at the playback deadline.
                      // Reset the consecutive drop tracking.
                      plc_instance.consecutive_drop_count = 0;
                      
                      // Feed this real audio into the PLC history so it has fresh data to track.
                      plc_instance.UpdateHistory(current_channel_buffer, current_frame_size);
                  } 
                  else {
                      // 2. Blackout occurred! The jitter buffer slot was empty or too late.
                      // Synthesise a smooth, phase-aligned concealment block into the buffer.
                      plc_instance.GeneratePlcFrame(current_channel_buffer, current_frame_size);
                  }
                  
                  // 3. Continue to the existing Jamulus dev pipeline:
                  // Convert int16_t 'current_channel_buffer' to float, apply gain, mix, and output.
                  
                  Use code with caution.
                  Addressing Jamulus-Specific Edge Cases 
                  • The "Late Packet" Override: If a packet arrives late but within the jitter buffer window, Jamulus will insert it into its correct sequence slot. If the audio thread has already passed that slot and generated a PLC frame for it, the late packet will simply be discarded when its slot hits the absolute past. The PLC engine handles this seamlessly because it only cares about what the mixer actually played, maintaining a continuous timeline. 
                  • Stereo Phase Matching: Musicians heavily depend on stereo spatialization for instrument separation. The AMDF pitch matching in the code calculates the pitch period using the left channel and applies that exact same period lag calculation to both the left and right channels. This keeps the stereo image perfectly locked in phase during a drop, preventing the sound from feeling like it is weirdly shifting space or twisting across headphones. 
                  • Micro-Buffer Resiliency: Because Jamulus can scale down to a 2.67ms (64-sample) hardware buffer, a single drop is minute. At this resolution, the cross-fade length (crossfade_len = std::min(48, frame_size / 2)) automatically limits itself to 32 samples (~0.6ms). This guarantees that even at absolute minimum latency configurations, the PLC boundary blend scales proportionally without exceeding your buffer constraints. 
                  This approach will effectively replace the current silence-insertion "crackles" with a subtle, smooth smoothing window. 
                  AI responses may include mistakes. Learn more
                  Copy

                  Share public link

                  This public link shares a thread, which may include personal information. You can delete this link, but not copies made by others.
                  Can’t copy the link right now. Please try again later.
                  Facebook
                  Gmail
                  X
                  Reddit
                  WhatsApp
                  Good response
                  Bad response
                  More

                  Saved time
                  Clear
                  Helpful
                  Comprehensive
                  Other
                  Incorrect
                  Inappropriate
                  Not working
                  Unhelpful
                  Other
                  A copy of this chat, including the images and video, will be included with your feedback
                  A copy of this chat will be included with your feedback
                  Your feedback will include a copy of this chat and the image from your search
                  Your feedback will include a copy of this chat, any links that you shared and the image from your search.
                  Thanks for letting us know
                  Google may use account and system data to understand your feedback and improve our services, subject to our Privacy Policy and Terms of Service. For legal issues, make a legal removal request.
                  • Jitter: The Complete 2026 Guide to Causes and Solutions
                    21 Jan 2026 — Jitter is the inconsistency in packet arrival times on a network. In a VoIP or video calls, data is transmitted in packets that ar...
                    foursquareint.com
                  • Jitter Buffer Settings - Yeastar Document Center
                    Jitter Buffer Settings. A jitter buffer is used at the receiving equipment to store incoming RTP packets, re-align them in terms o...
                    Yeastar Document Center
                  • Technical comparison with Sonobus #1313 - GitHub
                    10 Jan 2022 — From what I gather, both Jamulus and Sonobus use fundamentally the same approach: Use UDP to send data without delays and retransm...
                    GitHub
                  • Remote Jamming with Helix and Jamulus - jimamsden
                    4 Apr 2020 — You can leave the Jitter buffer Auto selected and Jamulus will attempt to optimize network latency against audio dropouts. Larger ...
                    WordPress.com
                  • Handle audio packets received out of order #619 - GitHub
                    23 Sept 2020 — softins commented. softins. on Oct 6, 2020. Last edited by softins. MemberAuthor. For the last couple of worldjams they have just ...
                    GitHub
                  • Jitter: The Complete 2026 Guide to Causes and Solutions
                    21 Jan 2026 — Jitter is the inconsistency in packet arrival times on a network. In a VoIP or video calls, data is transmitted in packets that ar...
                    foursquareint.com
                  • Jitter Buffer Settings - Yeastar Document Center
                    Jitter Buffer Settings. A jitter buffer is used at the receiving equipment to store incoming RTP packets, re-align them in terms o...
                    Yeastar Document Center
                  • Technical comparison with Sonobus #1313 - GitHub
                    10 Jan 2022 — From what I gather, both Jamulus and Sonobus use fundamentally the same approach: Use UDP to send data without delays and retransm...
                    GitHub
                  Show all
                  You said: What is the best way to save this whole conversation intact?
                  The best way to save this conversation intact depends on how you want to use it later. Here are the most effective methods to capture all the text, architecture diagrams, and C++ code modules securely: 
                  1. Copy the Source Markdown (Best for Code & Formatting) 
                  If your interface has a "Copy" button (usually a clipboard icon at the bottom of each response), use it. 
                  • Copying directly preserves the clean Markdown formatting, code syntax highlighting, and text architecture.
                  • Paste the copied text into a dedicated text editor like VS Code, Notepad++, or a markdown editor like Obsidian. Save the file with a .md extension (e.g., Jamulus_PLC_Implementation.md). 
                  2. Standard Browser Save (Fastest Local Copy) 
                  You can save the entire webpage directly using your web browser: 
                  • Press Ctrl + S (Windows) or Cmd + S (Mac).
                  • Change the save type to "Webpage, Complete" or "Webpage, Single File (MHTML)".
                  • This downloads a local file to your hard drive that will open in any browser looking exactly like this chat. 
                  3. Print to PDF (Best for Offline Reading) 
                  To turn this conversation into a clean, portable document: 
                  • Press Ctrl + P (Windows) or Cmd + P (Mac).
                  • Change the destination printer to "Save as PDF".
                  • Uncheck "Headers and footers" in the settings if you want to remove the date/URL stamps, then click Save. 
                  4. Create a Git Issue / Wiki Page 
                  Since you are working with the Jamulus dev branch, consider pasting this text directly into a private GitHub gist or an issue thread on your local repository clone. The Markdown layout used here will render perfectly inside GitHub/GitLab, making it easy for other core developers to review the AMDF/PSOLA logic. 
                  Would you like me to compile all the C++ code blocks and implementation steps from this chat into one single, continuous block of code so it is easier for you to copy in one go? 
                  AI responses may include mistakes. Learn more
                  Copy

                  Share public link

                  This public link shares a thread, which may include personal information. You can delete this link, but not copies made by others.
                  Can’t copy the link right now. Please try again later.
                  Facebook
                  Gmail
                  X
                  Reddit
                  WhatsApp
                  Good response
                  Bad response
                  More

                  Saved time
                  Clear
                  Helpful
                  Comprehensive
                  Other
                  Incorrect
                  Inappropriate
                  Not working
                  Unhelpful
                  Other
                  A copy of this chat, including the images and video, will be included with your feedback
                  A copy of this chat will be included with your feedback
                  Your feedback will include a copy of this chat and the image from your search
                  Your feedback will include a copy of this chat, any links that you shared and the image from your search.
                  Thanks for letting us know
                  Google may use account and system data to understand your feedback and improve our services, subject to our Privacy Policy and Terms of Service. For legal issues, make a legal removal request.
                  • Capturing Gemini responses instantly - Gemini Apps Community
                    11 Apr 2026 — Click the Copy icon (two overlapping squares) at the bottom of the response to save the text to your clipboard.
                    Google Help
                  • IS there a way i can export every detail from a full conversation thread to a new one so i can continue the chat?
                    30 Jan 2026 — :two: Print to PDF (Ctrl + P on Windows / Cmd + P on Mac)
                    OpenAI Developer Community
                  • Capturing Gemini responses instantly - Gemini Apps Community
                    11 Apr 2026 — Click the Copy icon (two overlapping squares) at the bottom of the response to save the text to your clipboard.
                    Google Help
                  • IS there a way i can export every detail from a full conversation thread to a new one so i can continue the chat?
                    30 Jan 2026 — :two: Print to PDF (Ctrl + P on Windows / Cmd + P on Mac)
                    OpenAI Developer Community
                  Show all
                  Transcribing…
                  Dismiss
                  More input options
                  Microphone
                  Stop
                  Send
                  Send
                  Ask about
                  My Ad Centre
                  Google apps
                  Google Account
                  Tony Mountifield
                  tonymountifield@gmail.com
                  AI Mode response is ready