Skip to content

Output 32-bit float samples to preserve dynamic range and prevent clipping#59

Open
Falcosoft wants to merge 4 commits intonukeykt:masterfrom
Falcosoft:master
Open

Output 32-bit float samples to preserve dynamic range and prevent clipping#59
Falcosoft wants to merge 4 commits intonukeykt:masterfrom
Falcosoft:master

Conversation

@Falcosoft
Copy link
Copy Markdown
Contributor

Added '-af' option to output 32-bit float samples in order to preserve dynamic range and prevent clipping at the same time.

…pping

Added '-af' option to output 32-bit float samples in order to preserve dynamic range and prevent clipping at the same time.
Comment thread src/mcu.cpp Outdated
else if (sample_buffer_float)
{
const float divRec = 1 / 32768.0f;
sample[0] >>= 14;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be no need for bit shift if you divide for 2147483648.0 instead, and you could also keep more precision

Copy link
Copy Markdown
Contributor Author

@Falcosoft Falcosoft Apr 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HI,
If you inspect sample[0] and sample[1] at that place you will notice that if you right shift with 13 you will get samples that has a granularity of 2 if you right shift with 12 you will get a granularity of 4 and so on. So currently with right shift 14 you get the maximum resolution. So you will not get more resolution with fewer right shifts.
Moreover the float resolution is not infinite. By dividing with 2^31 you will get less precise results than with exact right shifts and then dividing with 2^15 since 1 / 2^15 and its multiplicands can be exactly represented in 32-bit float.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense, thanks for the explanation!

Copy link
Copy Markdown
Contributor Author

@Falcosoft Falcosoft Apr 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi,
Actually you were right in the sense that the 2 shifts can be skipped and the result is the same. So no more precision, but somewhat better performance. You do not have to divide by 2147483648.0 but only 536870912.0.

So overall this produces the same numbers as the current code:

    const float divRec = 1 / 536870912.0f;
    sample_buffer[sample_write_ptr + 0] = sample[0] * divRec;
    sample_buffer[sample_write_ptr + 1] = sample[1] * divRec;     

    sample_write_ptr = (sample_write_ptr + 2) % audio_buffer_size;

Comment thread src/mcu.cpp
}

if (audioFormat == AudioFormat::FLOAT32 && !isBufferSet)
{
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this flag would be not needed if you move the pageSize,pageNum set to inside the else if (!strcmp(argv[i], "-af")) if case?

Copy link
Copy Markdown
Contributor Author

@Falcosoft Falcosoft Apr 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case the argument order would be mandatory otherwise at
(!strcmp(argv[i], "-af")) you cannot know if -ab is set before, not set at all or only will be set after -af.
The if (audioFormat == AudioFormat::FLOAT32 && !isBufferSet) check is added to make sure that only change the dafault if -ab is not set manually.
But correct me if I'm wrong, maybe I overlook something.

It significantly improves the consistency of audio output (less pauses, crackles) when the emulator is used together with other programs.  Tested with Win10 x64, Win7 x64, WinXP x86.
@jcmoyer jcmoyer mentioned this pull request May 2, 2024
jcmoyer added a commit to jcmoyer/Nuked-SC55 that referenced this pull request May 9, 2024
Sample conversion implementation by @Falcosoft

Upstream PR: nukeykt#59
jcmoyer added a commit to jcmoyer/Nuked-SC55 that referenced this pull request May 13, 2024
Sample conversion implementation by @Falcosoft

Upstream PR: nukeykt#59
jcmoyer added a commit to jcmoyer/Nuked-SC55 that referenced this pull request May 24, 2024
Sample conversion implementation by @Falcosoft

Upstream PR: nukeykt#59
jcmoyer added a commit to jcmoyer/Nuked-SC55 that referenced this pull request May 25, 2024
Sample conversion implementation by @Falcosoft

Upstream PR: nukeykt#59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants