Closed fungos closed 5 years ago
Thanks for the report. With that code you posted, you are initializing a mal_context
, but you're passing in nullptr
as the context argument for mal_device_init()
. In this case the device will always be using the default backend and not the one you specified when you initialized the context. To fix this, pass &context
as the first argument to mal_device_init()
. I think this will help narrow down which backends work and which don't. It's especially surprising that SDL and OpenAL would both exhibit the same crackling behaviour...
Another common cause of crackling is not using a large enough buffer. Try setting one of the following config variables like the code below. Perhaps try setting these to something huge for testing just to eliminate it so we can narrow it down a bit.
config.bufferSizeInMilliseconds = 100;
or
config.bufferSizeInFrames = 4096;
Also, this doesn't affect anything in practice, but this part is unnecessary (line 67):
device.format = decoder.outputFormat;
device.channels = decoder.outputChannels;
device.sampleRate = decoder.outputSampleRate;
I was able to take a listen to your sample files, and that doesn't sound characteristic of an undersized buffer. It actually sounds more like a format conversion error or something... Could you add the following lines to your test program, just before the call the mal_device_start()
and report the output?
printf("DECODER: %s / %d / %d\n", mal_get_format_name(decoder.outputFormat), decoder.outputChannels, decoder.outputSampleRate);
printf("DEVICE: %s / %d / %d / %s\n", mal_get_format_name(device.internalFormat), device.internalChannels, device.internalSampleRate, mal_get_backend_name(device.pContext->backend));
I'm wondering if mini_al is not converting the data between the decoder and the device properly...
Thanks.
The issue is with the PulseAudio backend, the others worked with exception to OSS that failed initialization.
DECODER: 32-bit IEEE Floating Point / 2 / 44100
DEVICE: 16-bit Signed Integer / 2 / 44100 / PulseAudio
I've also tried to tweak the config parameters you suggested with a bunch of different values in both directions and no perceptive change in the output.
Output for each backend differs on device format: SDL and ALSA : DEVICE: 32-bit IEEE Floating Point / 2 / 44100 OpenAL and PulseAudio: DEVICE: 16-bit Signed Integer / 2 / 44100
OpenAL is impacted (slowdown and cracking) by bufferSizeInFrames less than 2Kb. This does not happen with SDL or ALSA. The same for bufferSizeInMilliseconds with OpenAL only.
Thanks a lot for that. That narrows it down a lot. I'm suspecting it's a bug with the f32-to-s16 conversion, but the weird thing is that my automated tests didn't report an error when I tried it the other day. Will investigate.
Yes the OpenAL backend is very high latency and was only intended as an emergency backend for unsupported platforms, but I'll be removing it soonish.
I went ahead and ran your sample program with the same compiler options and the same input file and just to be difficult I've been unable to reproduce the problem... All works fine here. I have, however, pushed an update to the dev branch that adds some debug output, so would you be able to run that program against the PulseAudio backend again and post the output? It'll spam a bunch of messages originating from the callback. I only need the first bit of the output and just a small sample of the looped output from the callback.
By the way, mini_al explicitly disables OSS on Linux. It's only enabled for FreeBSD and DragonFly BSD.
Here my output:
[mini_al] Endian: LE
[mini_al] SSE2: YES
[mini_al] AVX2: NO
[mini_al] AVX512F: NO
[mini_al] NEON: NO
[PulseAudio] attr: maxlength=123200, tlength=123200, prebuf=-1, minreq=61600, fragsize=61600; bufferSizeInFrames=30800
[PulseAudio] actual attr: maxlength=123200, tlength=123200, prebuf=61604, minreq=61600, fragsize=61600; pDevice->bufferSizeInFrames=30800
[PulseAudio] Audio interne Stéréo analogique (Playback)
Format: 32-bit IEEE Floating Point -> 16-bit Signed Integer
Channels: 2 -> 2
Sample Rate: 44100 -> 44100
Using backend: PulseAudio
DECODER: 32-bit IEEE Floating Point / 2 / 44100
DEVICE: 16-bit Signed Integer / 2 / 44100 / PulseAudio
[PulseAudio] write_callback: sizeInBytes=123200
bytesToReadFromClient=65472, framesToReadFromClient=16368
bytesToReadFromClient=57728, framesToReadFromClient=14432
[PulseAudio] write_callback: sizeInBytes=61636
bytesToReadFromClient=61636, framesToReadFromClient=15409
[PulseAudio] write_callback: sizeInBytes=61600
bytesToReadFromClient=61600, framesToReadFromClient=15400
[PulseAudio] write_callback: sizeInBytes=61600
bytesToReadFromClient=61600, framesToReadFromClient=15400
[PulseAudio] write_callback: sizeInBytes=61600
bytesToReadFromClient=61600, framesToReadFromClient=15400
...
To anyone whose listening, has anybody else out there experienced this issue? This is so frustrating because that all looks normal. In fact it looks identical to my test, except with different buffer sizes (yours still look fine, though).
I made a few code changes yesterday - I assume the audio output sounded exactly the same with no improvements?
I expect it won't make any difference, but could you try compiling with #define MAL_NO_SSE2
and see how that goes?
No difference at all with MAL_NO_SSE2
.
EDIT: Sorry, I had another change with it.
So frustrating! If it's not a hassle, would you be able to capture the output like you did the first time, only with MAL_NO_SSE2
? I just want to see if it sounds characteristic of certain types of errors. I have no idea what would cause this... The fact that it sounds different with MAL_NO_SSE2
means it must be something with mini_al, but what???
There is it: https://mega.nz/#!8MVhUY5Q!WCGd7SiBAslsHMnwMoAY-DMIEsAqgD0-H6WBWG3V6aI I can't hear any difference. Watch out your volume.
I've pushed some more debug output updates to the dev branch. Could you give that a quick run and post the output?
Mine looks like the following: Pretty much identical:
[mini_al] Endian: LE
[mini_al] SSE2: NO
[mini_al] AVX2: NO
[mini_al] AVX512F: NO
[mini_al] NEON: NO
[PulseAudio] attr: maxlength=4400, tlength=4400, prebuf=-1, minreq=2200, fragsize=2200; bufferSizeInFrames=1100
[PulseAudio] actual attr: maxlength=4400, tlength=4400, prebuf=2204, minreq=2200, fragsize=2200; pDevice->bufferSizeInFrames=1100
[PulseAudio] Built-in Audio Analogue Stereo (Playback)
Format: 32-bit IEEE Floating Point -> 16-bit Signed Integer
Channels: 2 -> 2
Sample Rate: 44100 -> 44100
Conversion:
Pre Format Conversion: NO
Post Format Conversion: YES
Channel Routing: NO
SRC: NO
Channel Routing at Start: NO
Passthrough: NO
Using backend: PulseAudio
DECODER: 32-bit IEEE Floating Point / 2 / 44100
DEVICE: 16-bit Signed Integer / 2 / 44100 / PulseAudio
[PulseAudio] write_callback: sizeInBytes=4400
bytesToReadFromClient=4400, framesToReadFromClient=1100
[PulseAudio] write_callback: sizeInBytes=4400
bytesToReadFromClient=4400, framesToReadFromClient=1100
[PulseAudio] write_callback: sizeInBytes=4400
bytesToReadFromClient=4400, framesToReadFromClient=1100
Press Enter to quit...[PulseAudio] write_callback: sizeInBytes=4400
bytesToReadFromClient=4400, framesToReadFromClient=1100
[PulseAudio] write_callback: sizeInBytes=4400
bytesToReadFromClient=4400, framesToReadFromClient=1100
[PulseAudio] write_callback: sizeInBytes=3872
bytesToReadFromClient=3872, framesToReadFromClient=968
[PulseAudio] write_callback: sizeInBytes=4400
bytesToReadFromClient=4400, framesToReadFromClient=1100
[mini_al] Endian: LE
[mini_al] SSE2: NO
[mini_al] AVX2: NO
[mini_al] AVX512F: NO
[mini_al] NEON: NO
[PulseAudio] attr: maxlength=4800, tlength=4800, prebuf=-1, minreq=2400, fragsize=2400; bufferSizeInFrames=1200
[PulseAudio] actual attr: maxlength=4800, tlength=4800, prebuf=2404, minreq=2400, fragsize=2400; pDevice->bufferSizeInFrames=1200
[PulseAudio] Audio interne Stéréo analogique (Playback)
Format: 32-bit IEEE Floating Point -> 16-bit Signed Integer
Channels: 2 -> 2
Sample Rate: 44100 -> 48000
Conversion:
Pre Format Conversion: YES
Post Format Conversion: YES
Channel Routing: NO
SRC: YES
Channel Routing at Start: NO
Passthrough: NO
Using backend: PulseAudio
DECODER: 32-bit IEEE Floating Point / 2 / 44100
DEVICE: 16-bit Signed Integer / 2 / 48000 / PulseAudio
[PulseAudio] write_callback: sizeInBytes=4800
bytesToReadFromClient=4800, framesToReadFromClient=1200
[PulseAudio] write_callback: sizeInBytes=2408
bytesToReadFromClient=2408, framesToReadFromClient=602
[PulseAudio] write_callback: sizeInBytes=2424
bytesToReadFromClient=2424, framesToReadFromClient=606
I've just noticed it changed my output sample rate to 48000. I'm pretty sure I didn't change anything.
Yeah it's the same as mine (except for how your PulseAudio server changed sample rates between runs?). Does it work on a different device by the way (it's no problem if you don't have another device to test on - just trying to think about different possibilities)?
It works on my wireless headset! wt..? This is really weird and annoying, why this would make any difference?
[mini_al] Endian: LE
[mini_al] SSE2: NO
[mini_al] AVX2: NO
[mini_al] AVX512F: NO
[mini_al] NEON: NO
[PulseAudio] attr: maxlength=4400, tlength=4400, prebuf=-1, minreq=2200, fragsize=2200; bufferSizeInFrames=1100
[PulseAudio] actual attr: maxlength=4400, tlength=4400, prebuf=2204, minreq=2200, fragsize=2200; pDevice->bufferSizeInFrames=1100
[PulseAudio] Wireless Stereo Headset Stéréo analogique (Playback)
Format: 32-bit IEEE Floating Point -> 16-bit Signed Integer
Channels: 2 -> 2
Sample Rate: 44100 -> 44100
Conversion:
Pre Format Conversion: NO
Post Format Conversion: YES
Channel Routing: NO
SRC: NO
Channel Routing at Start: NO
Passthrough: NO
Using backend: PulseAudio
DECODER: 32-bit IEEE Floating Point / 2 / 44100
DEVICE: 16-bit Signed Integer / 2 / 44100 / PulseAudio
[PulseAudio] write_callback: sizeInBytes=4400
bytesToReadFromClient=4400, framesToReadFromClient=1100
[PulseAudio] write_callback: sizeInBytes=2216
bytesToReadFromClient=2216, framesToReadFromClient=554
[PulseAudio] write_callback: sizeInBytes=3172
bytesToReadFromClient=3172, framesToReadFromClient=793
Tested with my output in both devices simultaneous and no cracking at all. But if I change to the internal analogic, there it is again.
$ lspci
01:00.1 Audio device: NVIDIA Corporation GK104 HDMI Audio Controller (rev a1)
$ lsmod | grep snd
snd_usb_audio 155648 2
snd_usbmidi_lib 28672 1 snd_usb_audio
snd_rawmidi 28672 1 snd_usbmidi_lib
snd_seq_device 16384 1 snd_rawmidi
snd_hda_codec_hdmi 49152 1
snd_hda_codec_realtek 73728 1
snd_hda_codec_generic 69632 1 snd_hda_codec_realtek
snd_hda_intel 36864 4
snd_hda_codec 106496 4 snd_hda_intel,snd_hda_codec_hdmi,snd_hda_codec_generic,snd_hda_codec_realtek
snd_hda_core 65536 5 snd_hda_intel,snd_hda_codec,snd_hda_codec_hdmi,snd_hda_codec_generic,snd_hda_codec_realtek
snd_hwdep 16384 2 snd_hda_codec,snd_usb_audio
snd_pcm 90112 5 snd_hda_intel,snd_hda_codec,snd_usb_audio,snd_hda_core,snd_hda_codec_hdmi
snd_timer 28672 1 snd_pcm
snd 77824 24 snd_hda_intel,snd_hwdep,snd_hda_codec,snd_usb_audio,snd_timer,snd_rawmidi,snd_hda_codec_hdmi,snd_hda_codec_generic,snd_usbmidi_lib,snd_seq_device,snd_hda_codec_realtek,snd_pcm
soundcore 16384 1 snd
usbcore 212992 9 usbhid,snd_usb_audio,usb_storage,ehci_hcd,ohci_pci,snd_usbmidi_lib,uas,ohci_hcd,ehci_pci
$ aplay --list-devices
**** List of PLAYBACK Hardware Devices ****
card 0: SB [HDA ATI SB], device 0: ALC887-VD Analog [ALC887-VD Analog]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 0: SB [HDA ATI SB], device 1: ALC887-VD Digital [ALC887-VD Digital]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: NVidia [HDA NVidia], device 3: HDMI 0 [HDMI 0]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: NVidia [HDA NVidia], device 7: HDMI 1 [HDMI 1]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: NVidia [HDA NVidia], device 8: HDMI 2 [HDMI 2]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: NVidia [HDA NVidia], device 9: HDMI 3 [HDMI 3]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 2: Headset [Wireless Stereo Headset], device 0: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0
You know what... I think I've experienced this issue before... If it's not a hassle for you, could you try this fix from the Arch wiki: https://wiki.archlinux.org/index.php/PulseAudio/Troubleshooting#Glitches,_skips_or_crackling
The "tsched=0" thing is something that I could have sworn I've done in the past which fixed a problem... Also look at the "Static noise when using headphones" section.
You got it, this fixes the issue! It is weird the explanation "Timer-based scheduling may expose issues in some ALSA drivers" as mini_al using ALSA backed worked perfectly.
I would suggest adding this link somewhere in the source near the pulseaudio backend and maybe try to identify the issue in someway and give a warning.
I noted that Pre Format Conversion
and SRC
were YES
before, and now they are NO
. That may be useful as a way to try detect the issue when using PulseAudio.
The thing is, this is something I experienced over a year ago (hence why I didn't initially think of it) and it's still not fixed... I'm just wondering what mini_al is doing differently to other software. Why is other software working, and what are they doing differently?
Anyway I'm glad that's working for you now! I'm going to leave this open for the time being to remind me to look into this further and see if I can work around it because this is kind of a serious problem. In the meantime I've added a note to the documentation at the top of mini_al in case this happens again.
Thanks for going through all the hassle of testing that stuff!
I think I am experiencing the same bug on Ubuntu 18.04. The workaround from the ArchWiki works for me too. If you need any data/logs, let me know.
Thanks for the report. I'd be interested to know what hardware you're using, but otherwise I'm not sure what I can do about this one. I'll need to look at how other libraries are using Pulse for some ideas I think.
The dev_0.9 branch has a refactor of the PulseAudio backend which I'm hoping may fix this. I'm not 100% sure if it's entirely fixed, but definitely I'm not reproducing it on a fresh Antergos install (based on Arch). I'm going to go ahead and close this issue, but I'm leaving the comment in the code file.
Hi, I'm having a incredibly bad cracking with anything played trough mini_al.
The code adapted from the sample with a few tweaks to chose the backend (copied from another issue here): https://gist.github.com/fungos/7fa6fb159f8fd260ed5aca17b1c0bc5c In this gist there is the link for the input mp3 sample and the output recorded from another device, as if I try to record directly from the pulseaudio sink, the sound is perfect.
I've tried with SDL, OpenAL, PluseAudio, ALSA and OSS backends, all these have the same issue. I don't have any issue at all playing any audio in this desktop with any other software, so I imagine it must be related to some mis-configuration initializing mini_al or some initialization internally.
I want to replace BASS audio in a game port I'm doing, and mini_al sounded ideal for the job, I hope to be able to figure this problem :)
Thanks