Banging wave files together (was Re: project)

Jeff Epler jepler at unpythonic.net
Sun Oct 3 21:58:39 CEST 2004


Two parts of your problem are trivial (choose 10 items from 100 items;
compute all 3628800 permutations of 10 items) and two parts are a little
harder (user interface, and audio file reading/writing).  Finally,
depending on the length of the audio files and their format, you might
be surprised at the amount of storage required.  For instance, if each
audio file is a 10-second uncompressed .WAV file at something like 1.5
megabits per second (16-bit, stereo, 44100Hz sample rate), you're looking
at 6 terabytes of .WAV file as output.

Here's a commandline program that takes identical-format wav files on
the commandline and does what you ask for.  "-n" to change the number of
files in the permutation, "-p" to change the output file prefix.

import sys, random, wave, getopt, os

# Permute adapted from Python Cookbook recipe
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66463
def permute(alist, blist=[]):
    if not len(alist): yield blist[:]
    for i in range(len(alist)):
        blist.append(alist.pop(i))
        for j in permute(alist, blist):
            yield j
        alist.insert(i, blist.pop())

def fact(n):
    if n == 0: return 1
    return fact(n-1)

def concatenate(dest, src):
    o = wave.open(dest, "w")
    i = wave.open(src[0], "r")
    o.setparams(i.getparams())
    for s in src:
        i = wave.open(s, "r")
        while 1:
            frames = i.readframes(1000)
            if not frames: break
            o.writeframesraw(frames)
    o.close()

def main(args):
    n = 10
    p = "out_"
    opts, files = getopt.getopt(args, "n:p:")
    for k, v in opts:
        if k == "-n":
            n = int(v)
        elif k == "-p":
            p = v

    allfiles = sys.argv[1:]
    files = random.sample(files, n)
    fmt = "%s%%0%dd.wav" % (p, len(str(fact(n))))
    for i, p in enumerate(permute(files)):
        concatenate(fmt % i, p)
        print "%s: %s" % (fmt % i, [os.path.basename(f) for f in p])

if __name__ == '__main__':
    main(sys.argv[1:])
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 196 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/python-list/attachments/20041003/8ccd2782/attachment.pgp>


More information about the Python-list mailing list