8000 Improve Dynamic Range (DR) of converters by dmitrykos · Pull Request #1041 · PortAudio/portaudio · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Improve Dynamic Range (DR) of converters #1041

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

dmitrykos
Copy link
Collaborator
@dmitrykos dmitrykos commented Jun 11, 2025

Improves Dynamic Range (DR) of converters.

Currently, at this stage, DR of 8-bit is improved. For example Float32 to 8-bit converters got around 8+ dB DR improvement:

=== Combined dynamic range (src->dest->float32) ===
Key: Noise amplitude in dBfs, X - fail (either above failed or dest->float32 failed)
{{{
in|  out:      f32     i32     i24     i16      i8     ui8
 f32          -inf  -180.6  -138.5   -79.5   -39.5   -39.4
 i32        -144.5  -144.5     X     -85.9   -40.1   -39.4
 i24        -138.5  -138.5  -138.5   -86.1   -39.4   -39.5
 i16         -84.8   -84.8   -84.8   -84.8   -39.8   -39.7
  i8         -36.6   -36.6   -36.6   -36.6   -36.6   -36.6
 ui8         -36.4   -36.4   -36.4   -36.4   -36.4   -36.4
}}}

Dithered variant was improved too by modifying the way the dithered noise is applied. Before we truncated sample by 1 bit to add space for a dither noise. With this approach valid audio data info was truncated and we were getting an explicit dither noise. But, if there is no initial truncation and dither noise is added then we effectively mix all valid audio data with noise first and truncate it afterwards - this approach increases DR by at least 1 dB in case of 8-bit converters (will work similarly for other formats).

New approach on example of Int32_To_Int8_Dither converter:

dither = PaUtil_Generate16BitTriangularDither( ditherGenerator );

/* truncate to 24-bit, add dither, truncate resulting 24-bit value to 8-bit */
*dest = (signed char) ((((*src) >> 8) + dither) >> 16);

Here we truncate 32-bit sample to 24-bit to add some gap for calculations, add dither and only then truncate to final 8-bits.

I can further extend this PR to other formats and cleanup and re-factor existing code, which in some places is incorrect, in order to get maximum DR for all converters. All implementations will be commented, so that we will no longer have unexplained calculations and conversions. The quality of audio output of PA will definitely improve.

Awaiting comments.

@dmitrykos dmitrykos self-assigned this Jun 11, 2025
@dmitrykos dmitrykos added the src-common Common sources in /src/common label Jun 11, 2025
@philburk
Copy link
Collaborator

@dmitrykos - Please hold off on changes to pa_converters until we finish #1034.
That code is rapidly changing.
I have added a new QA test that measures the effectiveness of the dithering.
I have also added code that prevents numeric wraparound and other problems.

@dmitrykos
Copy link
Collaborator Author
dmitrykos commented Jun 12, 2025

I have also added code that prevents numeric wraparound and other problems.

@philburk I see, I did not notice that work. Regarding temp = ((temp >> 1) + dither); approach, please refer my implementation proposal in this PR. For all conversions from Int32 to Int16, Int8 and their unsigned versions we could first truncate to 24 bits, then add dither and then truncate to the final size (wrapround will not happen because we will have 8 bits available for this math). With this approach DR is higher than doing (temp >> 1).

I can later adopt this PR or cancel it depending on the amount of changes in your earlier PR, so will wait until you finish #1034.

@RossBencina
Copy link
Collaborator

Mea culpa #1043

@dmitrykos
Copy link
Collaborator Author

@RossBencina I commented regarding scaling in #1042 and reasoned why 0x80 would be better.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
src-common Common sources in /src/common
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants
0