[issue4913] wave.py writes 16 bit sample files of half the correct duration

Alex Robinson report at bugs.python.org
Mon Jan 12 05:07:20 CET 2009


Alex Robinson <alex_python_org at tranzoa.com> added the comment:

Oh golly. I was confused. For some reason I was thinking
"writesamples()" when using "writeframes()".

So the current code reads ok. Which makes this "bug" a request for
writesamples() and readsamples() to be added to wave.py. They would
shield sleep deprived saps from the .wav file data frame format. :)


Here are python2.4-ish versions written for outside wave.py. Combos of 8
and 16 bit samples, mone and stereo, are tested. I did not test the
32-bit sample logic.

Sample values are expected to be +-32767 or +-128 ints (or +-2.x gig if
32-bit).


def readsamples(wf, nframes) :
    """ Read an array of number-of-channels normalized int sample
arrays. """

    wav = wf.readframes(nframes)

    if    wf.getsampwidth() == 4 :
        wav = struct.unpack("<%ul" % (len(wav) / 4), wav)
    elif  wf.getsampwidth() == 2 :
        wav = struct.unpack("<%uh" % (len(wav) / 2), wav)
    else :
        wav = struct.unpack("%uB"  %  len(wav),      wav)
        wav = [ s - 128 for s in wav ]

    nc  = wf.getnchannels()
    if  nc > 1  :
        wavs    = []
        for i in xrange(nc) :
            wavs.append([ wav[si] for si in xrange(0, len(wav), nc) ])
        pass
    else :
        wavs    = [ wav ]

    return(wavs)



def writesamples(wf, wavs) :
    """
        Write samples to the wave file.
        'wavs' looks like this:
               [ left_channel_samples,  right_channel_samples ]
            or [ left_channel_samples                         ]
            or   mono_samples
        This routine calls setnchannels() from information about 'wavs'
length.
    """

    if  wavs :
        if  len(wavs) not in [ 1, 2, 4 ] :
            wavs    = [ wavs, wv ]

        wf.setnchannels(len(wavs))

        if  len(wavs)   > 1 :
            wav         = []
            for w in zip(*wavs):
                wav    += w
            pass
        else :
            wav         = wavs[0]

        if    wf.getsampwidth() == 4 :
            ws  = array.array('l', [ s       for s in wav ])
        elif  wf.getsampwidth() == 2 :
            ws  = array.array('h', [ s       for s in wav ])
        else :
            ws  = array.array('B', [ s + 128 for s in wav ])

        ws  = ws.tostring()

        wf.writeframes(ws)

    pass

# end of code to edit and insert in wave.py

----------
type: behavior -> feature request

_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue4913>
_______________________________________


More information about the Python-bugs-list mailing list