Cannot prevent audio from aliasing when LÖVE has to resample

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
User avatar
SeekingExpansion
Prole
Posts: 6
Joined: Mon Aug 05, 2019 6:35 am

Cannot prevent audio from aliasing when LÖVE has to resample

Post by SeekingExpansion » Mon Aug 05, 2019 6:43 am

I'm working with Sound Data buffers and Queueable Sources.

I noticed that Audio may result with aliasing not present in the source Sound Data if the specified sampling rate in the Queueable Source doesn't match the sampling rate of the Audio Output Device. Because of that, I wanted to make my program get the selected output device's sampling rate, but apparently there's not a way to make LÖVE tell my code what default sampling rate is going to be used. Doesn't matter whether my chosen sampling rate is higher or lower than that of the sound device, noticeable aliasing will appear if the two sampling rates are close but not the same.

Should I report or ask-for-feature this on the issue tracker?


I made a little program with LÖVE that plays back the original Super Mario World's Celesta instrument sample, at 32kHz.
I should be able to play back the sample up to the G8 note without terrible aliasing just ruining the quality.
However, if I set my PC's default audio format to a sampling rate that doesn't match my program's sampling rate, horrible aliasing appears even from notes in octave 7.
Octave 9 should in every case be very aliased as expected with this sample played back around this sampling rate.

Unexpected aliasing appears only when the default audio drivers sampling rate is not the same as the queueable source's sampling rate.

I attached to this post .love(v11.2) files so you can test it for yourselves.
Are you getting the same problem that I get?
Attachments
48kHz SMW Celesta.love
(4.03 KiB) Downloaded 65 times
32kHz SMW Celesta.love
(4.03 KiB) Downloaded 68 times
44.1kHz SMW Celesta.love
(4.03 KiB) Downloaded 58 times
Last edited by SeekingExpansion on Wed Aug 07, 2019 4:23 am, edited 1 time in total.

User avatar
pgimeno
Party member
Posts: 1945
Joined: Sun Oct 18, 2015 2:58 pm
Location: Valencia, ES

Re: Cannot prevent audio from aliasing when LÖVE has to resample

Post by pgimeno » Mon Aug 05, 2019 1:32 pm

I don't notice any aliasing with PulseAudio. The latency is awful though but I think that's expected with that driver.

User avatar
zorg
Party member
Posts: 2754
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Cannot prevent audio from aliasing when LÖVE has to resample

Post by zorg » Mon Aug 05, 2019 1:38 pm

I'm at work atm, but i can test it tomorrow; i'll edit this post then.

Edit: So, i tested it out and he 32kHz version, as should be obvious, aliases above 15kHz, or around the 8th octave; the 48kHz version only does it above octave 9, and it's only really noticeable near the last 4-5 notes, as far as i can hear.

(Using a SoundBlaster X-Fi Elite Pro with 24 bit depth and 48kHz sampling rate)

Now bear in mind that i'm mostly talking about the main frequency of your sample, since harmonics/overtones could be reflected on Nyquist even before those notes, it's just not too distracting.

If anything, interpolation's not something that would fix this, i don't think; you'd need to dynamically lowpass/highshelf filter the sound (per-"voice") in a way that the higher your selected playback frequency is, the more you'd need to cut off from your sample (effectively reducing the harmonics to ultimately near-sine-wave-like qualitites the higher the playback pitch is... and even a simple sine will alias above Nyquist, of course...) - as a relevant aside, the sounds used by windows' horrid default midi driver are multi-sampled in that, if you open a midi file in something like OpenMPT, you can see that for one midi instrument, there are multiple samples used depending on the pitch of the sound. it's a very simplistic method of hard-swapping depending on pre-defined ranges (could be linearly mixed for example) but it works; the ones used for the higher octaves have less harmonics so they don't alias.

(You could also pre-process the sample so you'd have multiple versions depending on what pitch you want to play back.)



I must say, this is the first time i saw someone directly implementing their test project in love.run as to completely forego any extra function calls, kudos for that! ^^ (It did make it just a bit harder to parse what was happening though :P)

As for buffer implementations and resampling, from my own experience, you don't necessarily need more than 2 SoundDatas used as buffers, and usually a size of 1024-2048 samplepoints is fine for realtime queueing without any underflow issues.
Last edited by zorg on Wed Aug 07, 2019 10:55 am, edited 3 times in total.
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.

User avatar
raidho36
Party member
Posts: 2000
Joined: Mon Jun 17, 2013 12:00 pm

Re: Cannot prevent audio from aliasing when LÖVE has to resample

Post by raidho36 » Mon Aug 05, 2019 6:08 pm

Aliasing exists on Windows 10 & Realtek audio.

Internally, it's possible to select playback device and obtain such information. For some reason or another, this functionality is not exposed and the audio system is initialized with defaults.

User avatar
SeekingExpansion
Prole
Posts: 6
Joined: Mon Aug 05, 2019 6:35 am

Post by SeekingExpansion » Tue Aug 06, 2019 8:25 pm

raidho36 wrote:
Mon Aug 05, 2019 6:08 pm
Aliasing exists on Windows 10 & Realtek audio.

Internally, it's possible to select playback device and obtain such information. For some reason or another, this functionality is not exposed and the audio system is initialized with defaults.
Thanks for the information. I'm in fact using Realtek. Well, shame on me for thinking my audio drivers wouldn't have any faults. I had a chance to do the test on another computer and got the same aliasing problem, but it had Realtek as well.

I guess it indeed is a drivers problem. I still have my doubts though, I can't seem to be able to replicate the problem with other programs when they are not matching sampling rates with the default sound device. If only I could link LÖVE to ASIO I would be sure it is not a problem caused by LÖVE.

Still, a LÖVE function that returns the default sampling rate is a required feature.
pgimeno wrote:
Mon Aug 05, 2019 1:32 pm
I don't notice any aliasing with PulseAudio. The latency is awful though but I think that's expected with that driver.
Thanks for doing the test!
zorg wrote:
Mon Aug 05, 2019 1:38 pm
So, i tested it out and he 32kHz version, as should be obvious, aliases above 15kHz, or around the 8th octave; the 48kHz version only does it above octave 9, and it's only really noticeable near the last 4-5 notes, as far as i can hear. [...]
Thank you for the elaborated response, but I'm sorry, you didn't address my problem.

User avatar
raidho36
Party member
Posts: 2000
Joined: Mon Jun 17, 2013 12:00 pm

Re: Cannot prevent audio from aliasing when LÖVE has to resample

Post by raidho36 » Tue Aug 06, 2019 9:24 pm

Consider the fact that aliasing always exists and bad frequency mismatch only makes it a little worse. To me this indicates that the root cause isn't in the audio output device, but rather, in audio synthesizer - your code.

Playing around with device frequency does however impacts aliasing threshold. Matching frequencies (or exact multiples) produce best results.

User avatar
SeekingExpansion
Prole
Posts: 6
Joined: Mon Aug 05, 2019 6:35 am

Post by SeekingExpansion » Tue Aug 06, 2019 11:27 pm

raidho36 wrote:
Tue Aug 06, 2019 9:24 pm
Consider the fact that aliasing always exists and bad frequency mismatch only makes it a little worse. To me this indicates that the root cause isn't in the audio output device, but rather, in audio synthesizer - your code.

Playing around with device frequency does however impacts aliasing threshold. Matching frequencies (or exact multiples) produce best results.

If that's the case, then that would mean that I should make my LÖVE program always produce its highest quality audio, meaning that I cannot keep my 32kHz sampling rate because most output devices won't be set to or even support a multiple of this sampling rate.

Can you spot what I'm actually doing wrong? What would be the best solution to prevent quality loss every instance this kind of problem arises?


With this problem I wanted to show that being able to request the default sampling rate from LÖVE, or being able to request LÖVE to let you choose the audio output device would be very nice features.
If neither of those are possible for now, then I'm completely fine ignoring the problem exists.


I should've attached the results of my tests in the beginning to show what the problem was.
I attached some .ogg files to this post in case you want to hear them.
Attachments
Test Results.zip
Audio demos of the notes A#7, B7, C8, C#8 being played in succession with different sampling rate matches.
(266.53 KiB) Downloaded 51 times

User avatar
raidho36
Party member
Posts: 2000
Joined: Mon Jun 17, 2013 12:00 pm

Re: Cannot prevent audio from aliasing when LÖVE has to resample

Post by raidho36 » Wed Aug 07, 2019 12:56 am

It's probably your resampling code. You can try lifting examples from OpenAL code, I didn't hear complaints about its resampler. I checked your code and frankly I have no idea what's that supposed to be. It's probably not realistic to have true 32 khz sampling rate because virtually none of modern hardware supports it. You can however simulate it (excluding aliasing issues) using a simple low-pass filter that cuts off at 32 khz.

LOVE always starts with default audio device. It should pick up whichever is set up in your OS settings, which should also be able to remember edited settings on per-app basis.

If nothing else, you can always ask user to specify desired frequency. It would be appropriate, considering it's a music app.

Also, I suggest you write the code in "conventional" fashion rather than putting everything into a singular love.run function. The way you do it will work but it won't scale very well.

User avatar
SeekingExpansion
Prole
Posts: 6
Joined: Mon Aug 05, 2019 6:35 am

Post by SeekingExpansion » Wed Aug 07, 2019 1:20 am

raidho36 wrote:
Wed Aug 07, 2019 12:56 am
[...] You can try lifting examples from OpenAL code, I didn't hear complaints about its resampler.
Well, for now, I'm going to assume this is a problem caused by OpenAL's resampler, in combination with Realtek; I'm not really going to do any further testing or dig deeper into it.
raidho36 wrote:
Wed Aug 07, 2019 12:56 am
It's probably your resampling code. [...] It's probably not realistic to have true 32 khz sampling rate because virtually none of modern hardware supports it. You can however simulate it (excluding aliasing issues) using a simple low-pass filter that cuts off at 32 khz.

[...]

If nothing else, you can always ask user to specify desired frequency. It would be appropriate, considering it's a music app.
Yes, you're right.

I'm just actually needing to strictly sample at 32kHz, to simulate a certain limitation, and 32kHz lowpass doesn't really do a good job to replicate it.

So yes, I have experimented with many of LÖVE capabilities and limitations, and I'm making my game to fit to that; and of course I know very well about the frustration of a program not providing video and audio options, so I never forget to fill my programs with as many optional configuration options as I can.
Last edited by SeekingExpansion on Sun Aug 25, 2019 8:02 am, edited 1 time in total.

User avatar
zorg
Party member
Posts: 2754
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re:

Post by zorg » Wed Aug 07, 2019 6:47 am

SeekingExpansion wrote:
Tue Aug 06, 2019 8:25 pm
zorg wrote:
Mon Aug 05, 2019 1:38 pm
So, i tested it out and he 32kHz version, as should be obvious, aliases above 15kHz, or around the 8th octave; the 48kHz version only does it above octave 9, and it's only really noticeable near the last 4-5 notes, as far as i can hear. [...]
Thank you for the elaborated response, but I'm sorry, you didn't address my problem.
Well, if the issue was with the realtek driver as raidho mentioned, then yeah, i couldn't have known that. :3

ONe thing i did see you do in your code: you don't necessarily need to have as many separate sounddata objects as internal buffers for a q-source; since the data is copied, not just referenced, you can just use one. (it might be useful to use more in the case of someone wanting to do threaded processing, each thread working on a separate SD object, a separate "timeslice", as it were, possibly boosting processing speed with the caveat of the cross-thread syncing not taking up more time than the individual processes.)

Also, for personal interest, i tried testing the included sample with my DAW of choice, FL studio; i imported it, it was aliasing around the same limits... tested with different interpolation methods; only 512-point sinc interpolation did not alias the highest octave supported (which is one higher than the one in your test projects), anything lower did.
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.

Post Reply

Who is online

Users browsing this forum: No registered users and 13 guests