Quefumas / gensound

Pythonic audio processing and generation framework
Apache License 2.0
81 stars 6 forks source link

Crash when realising ADSR #31

Closed ali1234 closed 1 year ago

ali1234 commented 2 years ago

Not sure what is happening here. It only happens if the sample rate is 22050. 44100 and 11025 both work. Rounding error somewhere?

Code:

from gensound import *

if __name__ == '__main__':
    snd = Sine(duration=0.1e3) * ADSR(attack=0.01e3, decay=0.01e3, sustain=0.25, release=0.01e3)
    snd.realise(sample_rate=22050)

Trace:

Traceback (most recent call last):
  File "test.py", line 5, in <module>
    snd.realise(sample_rate=22050)
  File "venv/lib/python3.8/site-packages/gensound/signals.py", line 47, in realise
    transform.realise(audio=audio)
  File "venv/lib/python3.8/site-packages/gensound/transforms.py", line 550, in realise
    audio.audio[:,:length_start] *= env_start.flatten(audio.sample_rate)
ValueError: operands could not be broadcast together with shapes (1,441) (440,) (1,441) 
ali1234 commented 2 years ago

If I specify the ADSR timings as integer (number of samples), then the crash does not happen.

Quefumas commented 2 years ago

Thanks for discovering this and letting me know! This should be fixed now.

Yes, this is due to bad rounding, which was always expected to cause an issue at some point. Here, a duration of 0.01e3 in sample rate 22050 results in a non-integer number of samples, which gensound can handle by itself. However, this ADSR uses two curves of duration 0.01e3 (for attack and then decay). If we compute the total duration before converting to number of samples (addition before rounding), we get one sample more than if we convert first, then concatenate (rounding then adding).