Skip to content
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

GLAME Butterworth Lowpass/Highpass (Lv2 versions) generate damaged audio #5767

Closed
JohannesLorenz opened this issue Nov 4, 2020 · 14 comments
Closed
Labels

Comments

@JohannesLorenz
Copy link
Contributor

Bug Summary

GLAME Butterwort Lowpass and Highpass (Lv2 versions) generate damaged audio in many cases. LADSPA versions work. Lv2 versions work in Audio. Conclusion: LMMS Lv2 implementation is broken.

Thanks to @IanCaio for reporting!

Steps to reproduce

Turn off speakers. Then use the effect and play any audio through them.

Expected behavior

Normal filter output.

Actual behavior

Corrupted audio. Can cause ear or speaker damage.

Affected LMMS versions

Master only.

@zonkmachine
Copy link
Member

Got a backtrace

Logs

Click to expand

Thread 13 "Mixer::fifoWrit" received signal SIGFPE, Arithmetic exception.
[Switching to Thread 0x7fffc55bc700 (LWP 18867)]
iir_process_buffer_1s_5 (iirf=, iirf=, gt=, numSampsToProcess=32, outdata=0x555559f752b0, indata=0x555559f751c0)
at ./util/iir.h:243
243 ./util/iir.h: No such file or directory.
(gdb) bt full
#0 iir_process_buffer_1s_5
(iirf=, iirf=, gt=, numSampsToProcess=32, outdata=0x555559f752b0, indata=0x555559f751c0) at ./util/iir.h:243
pos = 0
plugin_data =
cutoff = 0.112575002
resonance =
input = 0x555559f751c0
output = 0x555559f752b0
iirf =
gt = 0x555559f46f20
sample_rate =
#1 runButtlow_iir (instance=, sample_count=32) at plugins/butterworth-swh.lv2/plugin.c:210
plugin_data =
cutoff = 0.112575002
resonance =
input = 0x555559f751c0
output = 0x555559f752b0
iirf =
gt = 0x555559f46f20
sample_rate =
#2 0x0000555555837f99 in lilv_instance_run(LilvInstance*, uint32_t) (instance=0x555559ecc4b0, sample_count=32) at /usr/include/lilv-0/lilv/lilv.h:1704
#3 0x0000555555839536 in Lv2Proc::run(short) (this=0x55555992bbc0, frames=32) at /home/zonkmachine/builds/lmms/src/core/lv2/Lv2Proc.cpp:328
#4 0x000055555582f703 in Lv2ControlBase::run(short) (this=0x7ffff2b30c08, frames=32) at /home/zonkmachine/builds/lmms/src/core/lv2/Lv2ControlBase.cpp:148
c = std::unique_ptr = {get() = 0x55555992bbc0}
__for_range =
std::vector of length 2, capacity 2 = {std::unique_ptr = {get() = 0x55555992bbc0}, std::unique_ptr = {get() = 0x555559e6b620}}
__for_begin = std::unique_ptr = {get() = 0x55555992bbc0}
__for_end = std::unique_ptr = {get() = 0x20}
#5 0x00007fffc41fec30 in Lv2Effect::processAudioBuffer(std::array<float, 2ul>, short) (this=0x7ffff2b30660, buf=0x7ffff2ab0260, frames=32)
at /home/zonkmachine/builds/lmms/plugins/Lv2Effect/Lv2Effect.cpp:79
outSum = 4.6355743843815749e-310
corrupt = 85
d = 0
w = 0
#6 0x000055555578c898 in EffectChain::processAudioBuffer(std::array<float, 2ul>
, short, bool)
(this=0x5555599ed230, _buf=0x7ffff2ab0260, _frames=32, hasInputNoise=false) at /home/zonkmachine/builds/lmms/src/core/EffectChain.cpp:199
it = 0x555559f91558
moreEffects = false
#7 0x0000555555824dc2 in AudioPort::processEffects() (this=0x7ffff2aa5990) at /home/zonkmachine/builds/lmms/src/core/audio/AudioPort.cpp:97
more = false
#8 0x000055555582570a in AudioPort::doProcessing() (this=0x7ffff2aa5990) at /home/zonkmachine/builds/lmms/src/core/audio/AudioPort.cpp:222
fpp = 32
me = false
#9 0x00005555557a2a6d in ThreadableJob::process() (this=0x7ffff2aa5990) at /home/zonkmachine/builds/lmms/include/ThreadableJob.h:74
expected = ThreadableJob::ProcessingState::Queued
#10 0x00005555557c32a3 in MixerWorkerThread::JobQueue::run() (this=0x555555ae0e00 MixerWorkerThread::globalJobQueue)
at /home/zonkmachine/builds/lmms/src/core/MixerWorkerThread.cpp:84
job = 0x7ffff2aa5990
i = 2
processedJob = true
#11 0x00005555557c3533 in MixerWorkerThread::startAndWaitForJobs() () at /home/zonkmachine/builds/lmms/src/core/MixerWorkerThread.cpp:157
--Type for more, q to quit, c to continue without paging--
#12 0x00005555557bae66 in Mixer::renderNextBuffer() (this=0x7fffec0032a0) at /home/zonkmachine/builds/lmms/src/core/Mixer.cpp:470
last_metro_pos = { = {m_ticks = -1, static s_ticksPerBar = 192}, m_timeLine = 0x0, m_currentFrame = 0, m_jumped = false}
song = 0x555555fba400
currentPlayMode = Song::Mode_PlayPattern
p = { = {m_ticks = 158, static s_ticksPerBar = 192}, m_timeLine = 0x5555596bfb90, m_currentFrame = 43.5, m_jumped = false}
playModeSupportsMetronome = true
it_rem = {i = 0x7fffa80025f0}
fxMixer = 0x555555fd5d40
#13 0x00005555557bd79d in Mixer::fifoWriter::run() (this=0x555558f279c0) at /home/zonkmachine/builds/lmms/src/core/Mixer.cpp:1274
buffer = 0x7fffa8004ee0
b = 0x555555e88430
frames = 32
#14 0x00007ffff65179d2 in QThreadPrivate::start(void*) (arg=0x555558f279c0) at thread/qthread_unix.cpp:361
thr = 0x555558f279c0
data =
__clframe =
{__cancel_routine = 0x7ffff6517040 QThreadPrivate::finish(void*), __cancel_arg = 0x555558f279c0, __do_it = 1, __cancel_type = }
#15 0x00007ffff7f8e609 in start_thread (arg=) at pthread_create.c:477
ret =
pd =
unwind_buf =
{cancel_jmp_buf = {{jmp_buf = {140736504514304, 4034648486250114803, 140737488345390, 140737488345391, 140737488345584, 140736504512256, -4034528328156090637, -4034630867549458701}, mask_was_saved = 0}}, priv = {pad = {0x0, 0x0, 0x0, 0x0}, data = {prev = 0x0, cleanup = 0x0, canceltype = 0}}}
not_first_call = 0
#16 0x00007ffff618d293 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
(gdb)

@JohannesLorenz
Copy link
Contributor Author

@zonkmachine Many thanks for the backtrace! Is line 243 in iir.h for you

gt->coeff[0][3]*iirf[0].oring[1] +

this one? (I think frame can tell you what code line gdb meant)

@LostRobotMusic LostRobotMusic changed the title GLAME Butterwort Lowpass/Highpass (Lv2 versions) generate damaged audio GLAME Butterworth Lowpass/Highpass (Lv2 versions) generate damaged audio Nov 5, 2020
@zonkmachine
Copy link
Member

Upstream issue that could be related: swh/lv2#2

@zonkmachine
Copy link
Member

this one? (I think frame can tell you what code line gdb meant)

Yes. https:/swh/lv2/blob/master/util/iir.h#L243

(gdb) frame
#0  iir_process_buffer_1s_5 (iirf=<optimized out>, iirf=<optimized out>, gt=<optimized out>, numSampsToProcess=256, outdata=0x55555a0960c0, 
    indata=0x5555598f77d0) at ./util/iir.h:243
243	in ./util/iir.h

@zonkmachine
Copy link
Member

I also got a different crash with the same test. Just adding a GLAME Butterworth Lowpass filter to the default project 3osc and hitting the test key. This second case was from swh-lv2 master.

Logs

Click to expand
Thread 13 "Mixer::fifoWrit" received signal SIGFPE, Arithmetic exception.
[Switching to Thread 0x7fffbd5ad700 (LWP 94108)]
0x00007fffebd148ba in runButtlow_iir () from /home/zonkmachine/.lv2/butterworth-swh.lv2/plugin-Linux.so
(gdb) bt full
#0  0x00007fffebd148ba in runButtlow_iir () at /home/zonkmachine/.lv2/butterworth-swh.lv2/plugin-Linux.so
#1  0x000055555583af31 in lilv_instance_run(LilvInstance*, uint32_t) (instance=0x55555a0092c0, sample_count=256) at /usr/include/lilv-0/lilv/lilv.h:1704
#2  0x000055555583c4ce in Lv2Proc::run(short) (this=0x555559f94250, frames=256) at /home/zonkmachine/builds/lmms/src/core/lv2/Lv2Proc.cpp:328
#3  0x000055555583269b in Lv2ControlBase::run(short) (this=0x7ffff2b20c08, frames=256) at /home/zonkmachine/builds/lmms/src/core/lv2/Lv2ControlBase.cpp:148
        c = std::unique_ptr = {get() = 0x555559f94250}
        __for_range = 
            std::vector of length 2, capacity 2 = {std::unique_ptr = {get() = 0x555559f94250}, std::unique_ptr = {get() = 0x55555964b8f0}}
        __for_begin = std::unique_ptr = {get() = 0x555559f94250}
        __for_end = std::unique_ptr = {get() = 0x20}
#4  0x00007fffbcc50c30 in Lv2Effect::processAudioBuffer(std::array*, short) (this=0x7ffff2b20660, buf=0x7ffff2a61860, frames=256)
    at /home/zonkmachine/builds/lmms/plugins/Lv2Effect/Lv2Effect.cpp:79
        outSum = 4.6355744483413371e-310
        corrupt = 85
        d = 0
        w = 0
#5  0x000055555578f880 in EffectChain::processAudioBuffer(std::array*, short, bool)
    (this=0x555559b10a70, _buf=0x7ffff2a61860, _frames=256, hasInputNoise=false) at /home/zonkmachine/builds/lmms/src/core/EffectChain.cpp:199
        it = 0x55555a0cd638
        moreEffects = false
#6  0x0000555555827d5a in AudioPort::processEffects() (this=0x7ffff2aa5990) at /home/zonkmachine/builds/lmms/src/core/audio/AudioPort.cpp:97
        more = false
#7  0x00005555558286a2 in AudioPort::doProcessing() (this=0x7ffff2aa5990) at /home/zonkmachine/builds/lmms/src/core/audio/AudioPort.cpp:222
        fpp = 256
        me = false
#8  0x00005555557a5a05 in ThreadableJob::process() (this=0x7ffff2aa5990) at /home/zonkmachine/builds/lmms/include/ThreadableJob.h:74
        expected = ThreadableJob::ProcessingState::Queued
#9  0x00005555557c623b in MixerWorkerThread::JobQueue::run() (this=0x555555ae5e00 )
    at /home/zonkmachine/builds/lmms/src/core/MixerWorkerThread.cpp:84
        job = 0x7ffff2aa5990
        i = 2
        processedJob = true
#10 0x00005555557c64cb in MixerWorkerThread::startAndWaitForJobs() () at /home/zonkmachine/builds/lmms/src/core/MixerWorkerThread.cpp:157
#11 0x00005555557bddfe in Mixer::renderNextBuffer() (this=0x7fffec0032a0) at /home/zonkmachine/builds/lmms/src/core/Mixer.cpp:470
        last_metro_pos = { = {m_ticks = -1, static s_ticksPerBar = 192}, m_timeLine = 0x0, m_currentFrame = 0, m_jumped = false}
        song = 0x555555e82170
        currentPlayMode = Song::Mode_None
        p = { = {m_ticks = 0, static s_ticksPerBar = 192}, m_timeLine = 0x0, m_currentFrame = 0, m_jumped = true}
        playModeSupportsMetronome = false
        it_rem = {i = 0x7fffa80025f0}
        fxMixer = 0x7fffc4016060
#12 0x00005555557c0735 in Mixer::fifoWriter::run() (this=0x555558ff3230) at /home/zonkmachine/builds/lmms/src/core/Mixer.cpp:1274
        buffer = 0x7fffa8004a50
        b = 0x555555fbca40
        frames = 256

@zonkmachine
Copy link
Member

zonkmachine commented Nov 6, 2020

I don't get the crash on swh-lv2 when I build it from master. I think this could have been fixed partially fixed here:
swh/ladspa@9b14f62#diff-4d52d75153dc4f15d3f8f421bc7cffe265863c6d8e3ddd3a2990f6635e83c070

It still hit us with crap data though, only no infinite number. I've disabled checking for nan on my build for now but we have some printf() statements in there still.

[New Thread 0x7fffc53ca700 (LWP 62495)]
Bad data, clearing buffer. frame: 0: value -nan
Bad data, clearing buffer. frame: 0: value -nan
Bad data, clearing buffer. frame: 0: value -nan
...

@JohannesLorenz
Copy link
Contributor Author

Does it work with different resonance values? Does valgrind detect anything, like an uninitialized read?

@zonkmachine
Copy link
Member

I can't use valgrind. My computer is much too weak to work with it in a meaningful way. My attempts with different filter settings has so far been inconclusive.

@JohannesLorenz
Copy link
Contributor Author

It works for me with dummy audio backend. Maybe --smc-check=all --error-limit=no and --leak-check=no can bring you speedups, too.

If it doesn't work I can try valgrinding it, too.

@zonkmachine
Copy link
Member

You mean somehting like this? If data output from valgrind rendering an lmms project is what you want I can let it run over night. You will have to give me the commands though.

$ valgrind --smc-check=all --error-limit=no --leak-check=no ./lmms render -o .test.wav ~/Documents/lmms/projects/glame.mmpz 
==102993== Memcheck, a memory error detector
==102993== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==102993== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==102993== Command: ./lmms render -o .test.wav /home/zonkmachine/Documents/lmms/projects/glame.mmpz
==102993== 
*** WEAK-JACK: initializing
*** WEAK-JACK: OK. (0)
Notice: could not set realtime priority.
Lv2 plugin SUMMARY: 287 of 329  loaded in 119548 msecs.
For details about not loaded plugins, please set
  environment variable "LMMS_LV2_DEBUG" to nonempty.
Loading project...
Done
|-----------------------------                     |     56%   \  Bad data, clearing buffer. frame: 37: value inf
|-----------------------------                     |     56%   |  
...
Bad data, clearing buffer. frame: 0: value -nan
Bad data, clearing buffer. frame: 0: value -nan
...
PERFLOG |       Project Render | 87.02user, 1.27system 146.38elapsed
|--------------------------------------------------|    100%   \  
==102993== 
==102993== HEAP SUMMARY:
==102993==     in use at exit: 470,899 bytes in 1,536 blocks
==102993==   total heap usage: 1,915,921 allocs, 1,914,385 frees, 144,110,033 bytes allocated
==102993== 
==102993== For a detailed leak analysis, rerun with: --leak-check=full
==102993== 
==102993== For lists of detected and suppressed errors, rerun with: -s
==102993== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 8 from 4)

@JohannesLorenz
Copy link
Contributor Author

If there were no lines starting with "==" between the start and "Bad data", then it already means there were no memory errors. 😢

@zonkmachine
Copy link
Member

As I understand it the ladspa and lv2 versions are supposed to be pretty much the same, right? When comparing the two there are differences. This specific example when applied to the Butterworth issue didn't make a difference but I think it's enough to suggest that the issue probably is in swh-lv2 for now as the other plugins just seem to work. I'm looking for where the filter coefficients are initialized to 0 but haven't found that place yet.

https:/swh/ladspa/blob/0c94d096a2202c83dcb89b5b66bd6047cb0e98c7/util/iir.c#L86-L92

void free_iir_stage(iir_stage_t *gt){
	int i;
	for(i=0;i<gt->availst;i++)
		if (gt->coeff[i]) free(gt->coeff[i]);
	if (gt->coeff) free(gt->coeff);
	if (gt) free(gt);
}

https:/swh/lv2/blob/1aa77e5f443b16c5802beef5d5dc0d6075113d89/util/iir.c#L85-L91

void free_iir_stage(iir_stage_t *gt){
	int i;
	for(i=0;i<gt->availst;i++)
		free(gt->coeff[i]);
	free(gt->coeff);
	free(gt);
}

@JohannesLorenz
Copy link
Contributor Author

It's a good idea to compare LADSPA and LV2, but I can't find any difference from the sources that could be relevant. I still think it's a bug in our LV2 interface (maybe because this is a mono effect, and we are somehow routing the mono output in a wrong way to the LMMS stereo).

@PhysSong
Copy link
Member

PhysSong commented Nov 12, 2020

I found what's going wrong: the cutoff port has sampleRate hint, but it seems like LMMS ignores it. Unlike LV2 case, LMMS uses the correct hint for LADSPA plugins.
As a result of this, the plugin will read too low cutoff frequency and behave wrongly.
@JohannesLorenz I think you should check for some port properties in Lv2Ports::Meta::get() at least LV2_CORE__sampleRate and probably LV2_PORT_PROPS__logarithmic.

JohannesLorenz added a commit to JohannesLorenz/lmms that referenced this issue Nov 12, 2020
This multiplies port's min/max value with the processing sample rate
that is used for the plugin. This fixes damaged audio in GLAME
Butterworth High-/Lowpass from LMMS#5767.
IanCaio pushed a commit to IanCaio/lmms that referenced this issue Mar 28, 2021
This multiplies port's min/max value with the processing sample rate
that is used for the plugin. This fixes damaged audio in GLAME
Butterworth High-/Lowpass from LMMS#5767.
sdasda7777 pushed a commit to sdasda7777/lmms that referenced this issue Jun 28, 2022
This multiplies port's min/max value with the processing sample rate
that is used for the plugin. This fixes damaged audio in GLAME
Butterworth High-/Lowpass from LMMS#5767.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants