Project management of NTIS P1 Cybernetic Systems and Department of Cybernetics | WiKKY

Project

General

Profile

Task #3855 » asf2json_mix.py

Tihelka Dan, 09.08.2016 15:15

 
1
#!/usr/bin/python2
2

    
3
import codecs
4
import glob
5
import json
6

    
7
import asf_new as asf  # dummy asf_new.py. To be replace just by asf
8

    
9
fmask = 'words_*.asf'
10
omask = 'words_{}_{}-{}'  # Mask for the word
11

    
12
# ASF items confersion
13
iconv = {'phone'         : unicode,
14
         'word'          : unicode,
15
         'prosodeme'     : unicode,
16
         'concatenate'   : unicode,
17
         'suspicious'    : unicode,
18
         'pphrsBoundPos' : unicode,
19
         'pwordBoundPos' : unicode,
20
         'mlfEndTime'    : float,
21
         'mlfBegTime'    : float,
22
         'HTKScore'      : unicode,  # Not used as number here
23
        }
24

    
25

    
26
def main() :
27

    
28
    # Nacte ASF soubory
29
    # - co soubor, to stejne slovo
30
    for fname in glob.glob(fmask) :
31

    
32
        # Read the ASF data
33
        asfdata = asf.ASF(attrconv = iconv)
34
        asfdata.read_file(fname)
35
        # Individual middle-phone splits for the given word
36
        splits  = {}
37

    
38
        # Jmeno je foneticky, ale ma u sebe prefix a suffix, ktery se musi opravit
39
        word    = fname
40
        word    = word.replace('words_', '') # Odstran zacatek
41
        word    = word.replace('.asf',  '') # Odstran konec
42
        phntext = '|{}|'.format(word)
43

    
44
        # Get individual concatenation parts
45
        for sent,segs in asfdata.iteritems() :
46
            # Find the split unit
47
            split,_ = segs.find_exact('concatenate', '*><*')
48
            part1   = segs[0:split+1]
49
            part2   = segs[split:]
50
            # Convert them to diphones
51
            part1   = to_diphs(part1, sent)
52
            part2   = to_diphs(part2, sent)
53

    
54
            # Store the parts
55
            splits[sent] = (part1, part2)
56

    
57
        # Zkombinuj ruzne casti slova do JSON struktury
58
        for sent1,(part1,part2) in splits.iteritems() :
59
            for sent2,(partA,partB) in splits.iteritems() :
60
                # Ignore the matching parts
61
                if sent1 == sent2 :
62
                   continue
63

    
64
                # Output file
65
                ofile = omask.format(word, sent1, sent2)
66

    
67
                # Join the parts
68
                join  = part1 + partB
69
                # Add first and final pause
70
                join.insert(0, {'diphone' : '${}'.format(join[ 0]['l-phone'])})
71
                join.append(   {'diphone' : '{}$'.format(join[-1]['r-phone'])})
72

    
73
                # Build JSON from it
74
                units = []
75
                data  = {'phntext' :  phntext,
76
                         'phrtype' :  to_phrtype(join),
77
                         'phrlctx' : '$',
78
                         'phrrctx' : '$',
79
                         'units'   :  units,
80
                         'File'    :  ofile + '.wav',
81
                        }
82
                # Add units
83
                for u in join :
84
                    u =  dict(u)  # Make copy. Will be changed
85
                    d =  u['diphone']
86
                    # Remove all not-required keys
87
                    for k in set(u.keys()).difference(('BegTime', 'EndTime', 'Sentence')) :
88
                        del u[k]
89
                    # Add to JSON
90
                    item = {'name'  :  d, }
91
                    # Add the info for cndidate to be kep, if there is such
92
                    if u :
93
                       item['keep'] = (u, )
94
                    # Add it to the data
95
                    units.append(item)
96

    
97
                # Store the JSON to disc. Wrap data to a sequence as JSON must be a sequence
98
                json.dump((data, ), codecs.open(ofile + '.json', 'wt', 'utf8'), sort_keys = True, indent = 4)
99
#                # Add it to the main json
100
#                sdata.append(data)
101

    
102
#    # Store the JSON to disc
103
#    json.dump(sdata, codecs.open(ojson, 'wt', 'utf8'), sort_keys = True, indent = 4)
104

    
105

    
106
## Posloupnost fonu prevede do posloupnosti difonu
107
#
108
def to_diphs(units, sent) :
109
    # Copy
110
    uout = []
111
    # Build diphones, copying the base features required for JSon
112
    for u1,u2 in zip(units[:-1], units[1:]) :
113
        uout.append({'Sentence'  :  sent,
114
                     'BegTime'   : (u1['mlfBegTime'] + u1['mlfEndTime']) / 2.0,  # Middle of 1st phone
115
                     'EndTime'   : (u2['mlfBegTime'] + u2['mlfEndTime']) / 2.0,  # Middle of 2nd phone
116
                     'diphone'   :  u1['phone']      + u2['phone'],
117
                     'l-phone'   :  u1['phone'],
118
                     'r-phone'   :  u2['phone'],
119
                     'prosodeme' :  u2['prosodeme'],
120
                    })
121
    # Vrati seznam
122
    return uout
123

    
124
## Z posledni ne-pauza jednotky urci typ fraze
125
#
126
def to_phrtype(units) :
127
    for u in reversed(units) :
128
        if   u.get('phone', ' ')       in '$%#' :
129
             continue
130
        if   u.get('diphone', ' ')[-1] in '$%#' :
131
             continue
132
        # Get the type
133
        p  = u.get('prosodeme', '?? NOT SET ??')
134
        # Convert the type
135
        if   p == '3.1' : return '3'
136
        elif p == '1.1' : return '1'
137
        elif p == '2.2' : return '2'
138
        elif p == '0'   : return '0'
139
        else            : raise ValueError('Unknown prosodeme {} for unit {}'.format(p, u))
140

    
141
    # Not found?
142
    raise ValueError('Unknown prosodeme for units {}'.format(units))
143

    
144
#
145
# ---------
146
#
147
if __name__ == '__main__' :
148
     main()
(2-2/2)