toaiff.py 2.95 KB
Newer Older
1 2 3 4 5 6 7 8 9
"""Convert "arbitrary" sound files to AIFF (Apple and SGI's audio format).

Input may be compressed.
Uncompressed file type may be AIFF, WAV, VOC, 8SVX, NeXT/Sun, and others.
An exception is raised if the file is not of a recognized type.
Returned filename is either the input filename or a temporary filename;
in the latter case the caller must ensure that it is removed.
Other temporary files used are removed by the function.
"""
10 11 12 13

import os
import tempfile
import pipes
14
import sndhdr
15

16 17
__all__ = ["error", "toaiff"]

18 19
table = {}

20
t = pipes.Template()
21 22 23 24 25 26 27 28 29
t.append('sox -t au - -t aiff -r 8000 -', '--')
table['au'] = t

# XXX The following is actually sub-optimal.
# XXX The HCOM sampling rate can be 22k, 22k/2, 22k/3 or 22k/4.
# XXX We must force the output sampling rate else the SGI won't play
# XXX files sampled at 5.5k or 7.333k; however this means that files
# XXX sampled at 11k are unnecessarily expanded.
# XXX Similar comments apply to some other file types.
30
t = pipes.Template()
31 32 33
t.append('sox -t hcom - -t aiff -r 22050 -', '--')
table['hcom'] = t

34
t = pipes.Template()
35 36 37
t.append('sox -t voc - -t aiff -r 11025 -', '--')
table['voc'] = t

38
t = pipes.Template()
39 40 41
t.append('sox -t wav - -t aiff -', '--')
table['wav'] = t

42
t = pipes.Template()
43 44 45
t.append('sox -t 8svx - -t aiff -r 16000 -', '--')
table['8svx'] = t

46
t = pipes.Template()
47 48 49
t.append('sox -t sndt - -t aiff -r 16000 -', '--')
table['sndt'] = t

50
t = pipes.Template()
51 52 53
t.append('sox -t sndr - -t aiff -r 16000 -', '--')
table['sndr'] = t

54
uncompress = pipes.Template()
55 56 57
uncompress.append('uncompress', '--')


58
class error(Exception):
Tim Peters's avatar
Tim Peters committed
59
    pass
60 61

def toaiff(filename):
Tim Peters's avatar
Tim Peters committed
62 63 64 65 66 67 68 69 70 71 72 73 74
    temps = []
    ret = None
    try:
        ret = _toaiff(filename, temps)
    finally:
        for temp in temps[:]:
            if temp != ret:
                try:
                    os.unlink(temp)
                except os.error:
                    pass
                temps.remove(temp)
    return ret
75 76

def _toaiff(filename, temps):
Tim Peters's avatar
Tim Peters committed
77
    if filename[-2:] == '.Z':
78 79
        (fd, fname) = tempfile.mkstemp()
        os.close(fd)
Tim Peters's avatar
Tim Peters committed
80 81 82 83 84 85 86 87 88 89
        temps.append(fname)
        sts = uncompress.copy(filename, fname)
        if sts:
            raise error, filename + ': uncompress failed'
    else:
        fname = filename
    try:
        ftype = sndhdr.whathdr(fname)
        if ftype:
            ftype = ftype[0] # All we're interested in
90
    except IOError, msg:
Tim Peters's avatar
Tim Peters committed
91 92 93 94
        if type(msg) == type(()) and len(msg) == 2 and \
                type(msg[0]) == type(0) and type(msg[1]) == type(''):
            msg = msg[1]
        if type(msg) != type(''):
95
            msg = repr(msg)
Tim Peters's avatar
Tim Peters committed
96 97 98
        raise error, filename + ': ' + msg
    if ftype == 'aiff':
        return fname
99
    if ftype is None or not ftype in table:
100
        raise error, '%s: unsupported audio file type %r' % (filename, ftype)
101
    (fd, temp) = tempfile.mkstemp()
102
    os.close(fd)
Tim Peters's avatar
Tim Peters committed
103 104 105 106 107
    temps.append(temp)
    sts = table[ftype].copy(fname, temp)
    if sts:
        raise error, filename + ': conversion to aiff failed'
    return temp