~ubuntu-branches/ubuntu/saucy/sphinxtrain/saucy

« back to all changes in this revision

Viewing changes to python/cmusphinx/s3file.py

  • Committer: Package Import Robot
  • Author(s): Samuel Thibault
  • Date: 2013-01-02 04:10:21 UTC
  • Revision ID: package-import@ubuntu.com-20130102041021-ynsizmz33fx02hea
Tags: upstream-1.0.8
ImportĀ upstreamĀ versionĀ 1.0.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (c) 2006 Carnegie Mellon University
 
2
#
 
3
# You may copy and modify this freely under the same terms as
 
4
# Sphinx-III
 
5
 
 
6
"""Read/write Sphinx-III binary parameter files.
 
7
 
 
8
All the various binary parameter files created by SphinxTrain and used
 
9
by Sphinx-III and PocketSphinx share a common file format.  This
 
10
module contains some base classes for reading and writing these files.
 
11
"""
 
12
 
 
13
__author__ = "David Huggins-Daines <dhuggins@cs.cmu.edu>"
 
14
__version__ = "$Revision: 8994 $"
 
15
 
 
16
from struct import unpack, pack
 
17
from numpy import array,reshape,shape,fromstring
 
18
 
 
19
class S3File(object):
 
20
    "Read Sphinx-III binary files"
 
21
    def __init__(self, filename=None, mode="rb"):
 
22
        if filename != None:
 
23
            self.open(filename, mode)
 
24
 
 
25
    def getall(self):
 
26
        return self._params
 
27
 
 
28
    def __getitem__(self, key):
 
29
        return self._params[key]
 
30
 
 
31
    def __setitem__(self, key, value):
 
32
        self._params[key] = value
 
33
 
 
34
    def __delitem__(self, key):
 
35
        del self._params[key]
 
36
 
 
37
    def __iter__(self):
 
38
        return iter(self._params)
 
39
 
 
40
    def __len__(self):
 
41
        return len(self._params)
 
42
 
 
43
    def open(self, filename, mode="rb"):
 
44
        self.filename = filename
 
45
        self.fh = file(filename, mode)
 
46
        self.readheader()
 
47
 
 
48
    def readheader(self):
 
49
        """
 
50
        Read binary header.  Sets the following attributes:
 
51
 
 
52
          - fileattr (a dictionary of attribute-value pairs)
 
53
          - swap (a byteswap string as used by the struct module)
 
54
          - otherend (a flag indicating if the file is wrong-endian
 
55
                  for the current platform)
 
56
          - data_start (offset of the start of data in the file)
 
57
        """
 
58
        spam = self.fh.readline()
 
59
        self.fileattr = {}
 
60
        if spam != "s3\n":
 
61
            raise Exception("File ID not found or invalid: " + spam)
 
62
        while True:
 
63
            spam = self.fh.readline()
 
64
            if spam == "":
 
65
                raise Exception("EOF while reading headers")
 
66
            if spam.endswith("endhdr\n"):
 
67
                break
 
68
            sp = spam.find(' ')
 
69
            k = spam[0:sp].strip()
 
70
            v = spam[sp:].strip()
 
71
            self.fileattr[k] = v
 
72
        # This is 0x11223344 in the file's byte order
 
73
        spam = unpack("<i", self.fh.read(4))[0]
 
74
        if spam == 0x11223344:
 
75
            self.swap = "<" # little endian
 
76
        elif spam == 0x44332211:
 
77
            self.swap = ">" # big endian
 
78
        else:
 
79
            raise Exception("Invalid byte-order mark %08x" % spam)
 
80
        # Now determine whether we need to swap to get to native
 
81
        # byteorder (shouldn't this be easier???)
 
82
        self.otherend = (unpack('=i', pack(self.swap + 'i', spam))[0] != spam)
 
83
        self.data_start = self.fh.tell()
 
84
 
 
85
    def read3d(self):
 
86
        self.d1 = unpack(self.swap + "I", self.fh.read(4))[0]
 
87
        self.d2 = unpack(self.swap + "I", self.fh.read(4))[0]
 
88
        self.d3 = unpack(self.swap + "I", self.fh.read(4))[0]
 
89
        self._nfloats = unpack(self.swap + "I", self.fh.read(4))[0]
 
90
        if self._nfloats != self.d1 * self.d2 * self.d3:
 
91
            raise Exception(("Number of data points %d doesn't match "
 
92
                             + "total %d = %d*%d*%d")
 
93
                            %
 
94
                            (self._nfloats,
 
95
                             self.d1 * self.d2 * self.d3,
 
96
                             self.d1, self.d2, self.d3))
 
97
        spam = self.fh.read(self._nfloats * 4)
 
98
        params = fromstring(spam, 'f')
 
99
        if self.otherend:
 
100
            params = params.byteswap()
 
101
        return reshape(params, (self.d1, self.d2, self.d3)).astype('d')
 
102
 
 
103
    def read2d(self):
 
104
        self.d1 = unpack(self.swap + "I", self.fh.read(4))[0]
 
105
        self.d2 = unpack(self.swap + "I", self.fh.read(4))[0]
 
106
        self._nfloats = unpack(self.swap + "I", self.fh.read(4))[0]
 
107
        if self._nfloats != self.d1 * self.d2:
 
108
            raise Exception(("Number of data points %d doesn't match "
 
109
                             + "total %d = %d*%d")
 
110
                            %
 
111
                            (self._nfloats,
 
112
                             self.d1 * self.d2,
 
113
                             self.d1, self.d2))
 
114
        spam = self.fh.read(self._nfloats * 4)
 
115
        params = fromstring(spam, 'f')
 
116
        if self.otherend:
 
117
            params = params.byteswap()
 
118
        return reshape(params, (self.d1, self.d2)).astype('d')
 
119
 
 
120
    def read1d(self):
 
121
        self.d1 = unpack(self.swap + "I", self.fh.read(4))[0]
 
122
        self._nfloats = unpack(self.swap + "I", self.fh.read(4))[0]
 
123
        if self._nfloats != self.d1:
 
124
            raise Exception(("Number of data points %d doesn't match "
 
125
                             + "total %d")
 
126
                            %
 
127
                            (self._nfloats, self.d1))
 
128
        spam = self.fh.read(self._nfloats * 4)
 
129
        params = fromstring(spam, 'f')
 
130
        if self.otherend:
 
131
            params = params.byteswap()
 
132
        return params.astype('d')
 
133
        
 
134
class S3File_write:
 
135
    "Write Sphinx-III binary files"
 
136
    def __init__(self, filename=None, mode="wb", attr={"version":1.0}):
 
137
        self.fileattr = attr
 
138
        if filename != None:
 
139
            self.open(filename)
 
140
 
 
141
    def open(self, filename):
 
142
        self.filename = filename
 
143
        self.fh = file(filename, "wb")
 
144
        self.writeheader()
 
145
 
 
146
    def writeheader(self):
 
147
        self.fh.write("s3\n")
 
148
        for k,v in self.fileattr.iteritems():
 
149
            self.fh.write("%s %s\n" % (k,v))
 
150
        # Make sure the binary data lives on a 4-byte boundary
 
151
        lsb = (self.fh.tell() + len("endhdr\n")) & 3
 
152
        if lsb != 0:
 
153
            align = 4-lsb
 
154
            self.fh.write("%sendhdr\n" % (" " * align))
 
155
        else:
 
156
            self.fh.write("endhdr\n")
 
157
        self.fh.write(pack("=i", 0x11223344))
 
158
        self.data_start = self.fh.tell()
 
159
 
 
160
    def write3d(self, stuff):
 
161
        d1, d2, d3 = shape(stuff)
 
162
        self.fh.write(pack("=IIII",
 
163
                           d1, d2, d3,
 
164
                           d1 * d2 * d3))
 
165
        stuff.ravel().astype('f').tofile(self.fh)
 
166
 
 
167
    def write2d(self, stuff):
 
168
        d1, d2 = shape(stuff)
 
169
        self.fh.write(pack("=III",
 
170
                           d1, d2,
 
171
                           d1 * d2))
 
172
        stuff.ravel().astype('f').tofile(self.fh)
 
173
 
 
174
    def write1d(self, stuff):
 
175
        d1 = len(stuff)
 
176
        self.fh.write(pack("=II", d1, d1))
 
177
        stuff.ravel().astype('f').tofile(self.fh)
 
178
 
 
179
    def __del__(self):
 
180
        self.close()
 
181
 
 
182
    def close(self):
 
183
        self.fh.close()