Zulko / pianoputer

Use your computer keyboard as a "piano".
http://zulko.github.io/blog/2014/03/29/soundstretching-and-pitch-shifting-in-python/
Other
324 stars 92 forks source link

PYGAME 2 , SDL2: fix mixer errors, mixer.init(..., allowchanges=0) #861 #17

Closed yoyoberenguer closed 3 years ago

yoyoberenguer commented 3 years ago

When starting the program with PYGAME 2.00 version, I had the following exception:

Traceback (most recent call last): File "C:\Users\yoann\AppData\Local\Programs\Python\Python36\lib\site-packages\pygame\sndarray.py", line 94, in make_sound return numpysnd.make_sound(array) AttributeError: 'NoneType' object has no attribute 'make_sound'

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "pianoputer.py", line 129, in main() File "pianoputer.py", line 103, in main key_sound = dict(zip(keys, sounds)) File "C:\Users\yoann\AppData\Local\Programs\Python\Python36\lib\site-packages\pygame\sndarray.py", line 97, in make_sound return numpysnd.make_sound(array) File "C:\Users\yoann\AppData\Local\Programs\Python\Python36\lib\site-packages\pygame_numpysndarray.py", line 74, in make_sound return mixer.Sound(array=array) ValueError: Array must be 2-dimensional for stereo mixer

This issue is related to PYGAME case : SDL2: fix mixer errors, mixer.init(..., allowchanges=0) #861

Suggestion to solve this issue (for both version of the program)


for single track sound


if int(pygame.version.ver[0]) >= 2:
    pygame.mixer.init(fps, -16, 1, 2048, allowedchanges=0)
else:
  pygame.mixer.init(fps, -16, 1, 2048)

for stereo sound


if int(pygame.version.ver[0]) >= 2:
    pygame.mixer.init(fps, -16, 2, 2048, allowedchanges=0)
else:
    pygame.mixer.init(fps, -16, 2, 2048)
spacether commented 3 years ago

@yoyoberenguer can you try using the 2.0.0 version of pianoputer and verify that this issue is fixed? When I load in mono and stereo wavs into v2.0.0 I do not get the error in this issue so I think that this is fixed. If I don't hear from you in the next week or two I will close this issue because I can't replicate it.

yoyoberenguer commented 3 years ago

@spacether, Good day to you. First nice job on the last version 2.0.0 of pianoputer, it looks so much better.

I can confirm the issue persist with pygame version 2.0 (I am attaching the screenshots proving it and also the resolution that will make your life easier) Here is the exception raised when loading (python 3.8 and pygame 2.0) CapturePython38

Here is the resolution (python 3.8 and pygame 2.0) CapturePython38_NoError

Resolution : pygame.mixer.init(framerate_hz, BITS_32BIT, channels, allowedchanges=0)

Bear in mind that allowedchanges has been implemented recently in pygame and some older version will not recognized this statement. In order to have a retro compatibility with odler version, you will have to implement some sort of pygame.version detection and change accordingly (pianoputer won't throw an exception when using older version of pygame < 2.0)

Also I didn't have time to look into the code but I noticed a bug in the method get_audio_data

    try:
        channels = len(audio_data[0])
    except TypeError:
        channels = 1
    return audio_data, framerate_hz, channels

For a single track, the numpy.ndarray will by shape e.g (31728, ) and for a stereo (31728, 2) The channel number is always referenced by the index 1 of the array (only for stereo or above) such as : channels = audio_data[1] index 0 is the samples data length Your code above will always revert to a mono track and will never detect a stereo sound (and this explained why you could not replicate the issue).


def is_valid_array(array_)->bool:

    # DETERMINE IF THE ARRAY IS MONO OR STEREO AND RETURN TRUE IF VALID 

    # check the shape of an array
    if hasatttr(array_, 'shape'):
        if len(array_.shape) == 1: return True  # mono sound
        elif len(array_.shape) == 2:
            if array_.shape[1] <=2: return True # stereo sound
            else: return False
        else: return False  # more than 2 channel not implemented yet
    else: return False  # here Attribute Error, certainly not an ndarray type
spacether commented 3 years ago

Thank you for the explanation. What OS are you using? Is this happening for stereo and mono files? On MacOS I am unable to reproduce the issue. On Windows10Pro I can reproduce the issue for mono files.

Good point about channels > 2, I should handle that use case.

spacether commented 3 years ago

Very weird, we are initializing the mixer with 1 channel for the mono wav file but on:

spacether commented 3 years ago

I have filed a pygame bug on this at https://github.com/pygame/pygame/issues/2417 Edit: and I just closed the bug because passing in your suggested allowedchanges=0 solves it

spacether commented 3 years ago

A fix has been submitted for this issue at https://github.com/Zulko/pianoputer/pull/22

spacether commented 3 years ago

@yoyoberenguer thank you for submitting this problem and letting us know how to fix it! With v2.0.1 this issue should be resolved On WIndows10Pro I ran the tests and verified that generating 1, 2, and 4 channel wav files works and that we no longer get this exception. If this problem is still occurring can you re-open this issue?