Ok, so I have a problem playing some sound files properly on Macs with 2.5
or 2.6
I am using the macports version of pygame 1.9.1 and python 2.5

The issue is some of the wav files I have created in audacity have an odd
number of
Frames. Of course since these are 16bit mono PCM files  they should be even,
but
these files work fine using pygame in Ubuntu. I have found that the problem
lies in
_numpysndarray.py  particularly in _array_samples:

def _array_samples(sound, raw):
    # Info is a (freq, format, stereo) tuple
    info = mixer.get_init ()
    if not info:
        raise pygame.error("Mixer not initialized")
    fmtbytes = (abs (info[1]) & 0xff) >> 3
    channels = info[2]
    if raw:
        data = sound.get_buffer ().raw
    else:
        data = sound.get_buffer ()

    shape = (len (data) // fmtbytes, )
    if channels > 1:
        shape = (shape[0] // channels, channels)

    # mixer.init () does not support different formats from the ones below,
    # so MSB/LSB stuff is silently ignored.
    typecode = { 8 : numpy.uint8,   # AUDIO_U8
                 16 : numpy.uint16, # AUDIO_U16 / AUDIO_U16SYS
                 -8 : numpy.int8,   # AUDIO_S8
                 -16 : numpy.int16  # AUDUI_S16 / AUDIO_S16SYS
                 }[info[1]]

    array = numpy.fromstring (data, typecode)
    array.shape = shape
    return array

the line
array = numpy.fromstring (data, typecode)
gives the following error:
ValueError: string size must be a multiple of element size

As these these are 16 bit values the size should be even, though some wave
files have
an extra byte at the end that needs to be dropped. Somehow the odd file work
in
Linux still, but crap out in osX. I think this odd frame size problem could
be easily
solved by just dropping the last odd frame.

def _array_samples(sound, raw):
    # Info is a (freq, format, stereo) tuple
    info = mixer.get_init ()
    if not info:
        raise pygame.error("Mixer not initialized")
    fmtbytes = (abs (info[1]) & 0xff) >> 3
    channels = info[2]
    if raw:
        data = sound.get_buffer ().raw
    else:
        data = sound.get_buffer ()

    shape = (len (data) // fmtbytes, )
    if channels > 1:
        shape = (shape[0] // channels, channels)

    # mixer.init () does not support different formats from the ones below,
    # so MSB/LSB stuff is silently ignored.
    typecode = { 8 : numpy.uint8,   # AUDIO_U8
                 16 : numpy.uint16, # AUDIO_U16 / AUDIO_U16SYS
                 -8 : numpy.int8,   # AUDIO_S8
                 -16 : numpy.int16  # AUDUI_S16 / AUDIO_S16SYS
                 }[info[1]]
    dl=len(data)
    if(dl%2==1):
        dl=dl-1
    array = numpy.fromstring (data[:dl], typecode)
    array.shape = shape
    return array


I've tried this modification locally, and it indeed works for odd and even
frames.
Since odd frames seem to work on some systems but not others, I think this
change should be added. Anyways, it solved my headaches and I thought I'd
share.

Reply via email to