@@ -346,16 +346,24 @@ HRESULT WasapiPlayer::feed(unsigned char* data, unsigned int size,
346346 return true ;
347347 };
348348
349+ bool shouldInsertSilentFrame = false ;
349350 if (isTrimmingLeadingSilence) {
350- size_t silenceSize = SilenceDetect::getLeadingSilenceSize (&format, data, size);
351+ // If data is null, treat the whole chunk as silence.
352+ size_t silenceSize = data ? SilenceDetect::getLeadingSilenceSize (&format, data, size) : size;
351353 if (silenceSize >= size) {
352354 // The whole chunk is silence. Continue checking for silence in the next chunk.
353355 remainingFrames = 0 ;
354356 } else {
355357 // Silence ends in this chunk. Skip the silence and continue.
356358 data += silenceSize;
357- remainingFrames = (size - silenceSize) / format.nBlockAlign ;
359+ size -= silenceSize;
360+ remainingFrames = size / format.nBlockAlign ;
358361 isTrimmingLeadingSilence = false ; // Stop checking for silence
362+
363+ // Signals to insert one silent frame before the trimmed audio in this chunk.
364+ // Not doing so may cause the beginning of the audio to be chopped off.
365+ // See: https://github.com/nvaccess/nvda/discussions/17697
366+ shouldInsertSilentFrame = true ;
359367 }
360368 }
361369
@@ -407,14 +415,30 @@ HRESULT WasapiPlayer::feed(unsigned char* data, unsigned int size,
407415 }
408416 }
409417 // We might have more frames than will fit in the buffer. Send what we can.
418+ // If we need to insert a silent frame, the frame counts towards the total frame count,
419+ // but does not count towards the total byte count, as it's not in the provided data buffer.
420+ if (shouldInsertSilentFrame) {
421+ remainingFrames++;
422+ }
410423 const UINT32 sendFrames = std::min (remainingFrames,
411424 bufferFrames - paddingFrames);
412- const UINT32 sendBytes = sendFrames * format.nBlockAlign ;
425+ const UINT32 sendBytes = (sendFrames - (shouldInsertSilentFrame ? 1 : 0 ))
426+ * format.nBlockAlign ;
413427 BYTE * buffer;
414428 hr = render->GetBuffer (sendFrames, &buffer);
415429 if (FAILED (hr)) {
416430 return hr;
417431 }
432+ if (shouldInsertSilentFrame) {
433+ // If needed, insert one frame of silence at the beginning
434+ if (format.wFormatTag == WAVE_FORMAT_PCM && format.wBitsPerSample == 8 ) {
435+ memset (buffer, 0x80 , format.nBlockAlign );
436+ } else {
437+ memset (buffer, 0 , format.nBlockAlign );
438+ }
439+ buffer += format.nBlockAlign ;
440+ shouldInsertSilentFrame = false ;
441+ }
418442 if (data) {
419443 memcpy (buffer, data, sendBytes);
420444 hr = render->ReleaseBuffer (sendFrames, 0 );
0 commit comments