xref: /btstack/test/sbc/sbc_decoder.py (revision df25739fc3ea5a0a90f0f5925e6461d653697d2e)
1#!/usr/bin/env python
2import numpy as np
3import wave
4import struct
5import sys
6from sbc import *
7from sbc_synthesis_v1 import *
8
9V = np.zeros(shape = (2, 10*2*8))
10N = np.zeros(shape = (16,8))
11total_time_ms = 0
12
13def sbc_unpack_frame(fin, available_bytes, frame):
14    if available_bytes == 0:
15        print "no available_bytes"
16        raise TypeError
17
18    frame.syncword = get_bits(fin,8)
19    if frame.syncword != 156:
20        print ("out of sync %02x" % frame.syncword)
21        return -1
22    frame.sampling_frequency = get_bits(fin,2)
23    frame.nr_blocks = nr_blocks[get_bits(fin,2)]
24
25    frame.channel_mode = get_bits(fin,2)
26
27    if frame.channel_mode == MONO:
28        frame.nr_channels = 1
29    else:
30        frame.nr_channels = 2
31
32    frame.allocation_method = get_bits(fin,1)
33    frame.nr_subbands = nr_subbands[get_bits(fin,1)]
34    frame.init(frame.nr_blocks, frame.nr_subbands, frame.nr_channels)
35
36    frame.bitpool = get_bits(fin,8)
37    frame.crc_check = get_bits(fin,8)
38
39    # frame.join = np.zeros(frame.nr_subbands, dtype = np.uint8)
40
41    if frame.channel_mode == JOINT_STEREO:
42        for sb in range(frame.nr_subbands-1):
43            frame.join[sb] = get_bits(fin,1)
44        get_bits(fin,1) # RFA
45
46    frame.scale_factor = np.zeros(shape=(frame.nr_channels, frame.nr_subbands), dtype = np.int32)
47
48    # print frame.audio_sample
49    for ch in range(frame.nr_channels):
50        for sb in range(frame.nr_subbands):
51            frame.scale_factor[ch][sb] = get_bits(fin, 4)
52
53    crc = calculate_crc(frame)
54    if crc != frame.crc_check:
55        print frame
56        print "error, crc not equal: ", crc, frame.crc_check
57        exit(1)
58
59    frame.scalefactor = np.zeros(shape=(frame.nr_channels, frame.nr_subbands), dtype = np.int32)
60    for ch in range(frame.nr_channels):
61        for sb in range(frame.nr_subbands):
62            frame.scalefactor[ch][sb] = 1 << (frame.scale_factor[ch][sb] + 1)
63
64
65    frame.bits = sbc_bit_allocation(frame)
66
67    frame.audio_sample = np.ndarray(shape=(frame.nr_blocks, frame.nr_channels, frame.nr_subbands), dtype = np.uint16)
68    for blk in range(frame.nr_blocks):
69        for ch in range(frame.nr_channels):
70            for sb in range(frame.nr_subbands):
71                frame.audio_sample[blk][ch][sb] = get_bits(fin, frame.bits[ch][sb])
72        #print "block %2d - audio sample: %s" % (blk, frame.audio_sample[blk][0])
73
74    drop_remaining_bits()
75    return 0
76
77def sbc_reconstruct_subband_samples(frame):
78    frame.levels = np.zeros(shape=(frame.nr_channels, frame.nr_subbands), dtype = np.int32)
79    frame.sb_sample = np.zeros(shape=(frame.nr_blocks, frame.nr_channels, frame.nr_subbands))
80
81    for ch in range(frame.nr_channels):
82        for sb in range(frame.nr_subbands):
83            frame.levels[ch][sb] = pow(2.0, frame.bits[ch][sb]) - 1
84
85    for blk in range(frame.nr_blocks):
86        for ch in range(frame.nr_channels):
87            for sb in range(frame.nr_subbands):
88                if frame.levels[ch][sb] > 0:
89                    AS = frame.audio_sample[blk][ch][sb]
90                    L  = frame.levels[ch][sb]
91                    SF = frame.scalefactor[ch][sb]
92                    frame.sb_sample[blk][ch][sb] = SF * ((AS*2.0+1.0) / L -1.0 )
93                else:
94                    frame.sb_sample[blk][ch][sb] = 0
95
96    # sythesis filter
97    if frame.channel_mode == JOINT_STEREO:
98        for blk in range(frame.nr_blocks):
99            for sb in range(frame.nr_subbands):
100                if frame.join[sb]==1:
101                    ch_a = frame.sb_sample[blk][0][sb] + frame.sb_sample[blk][1][sb]
102                    ch_b = frame.sb_sample[blk][0][sb] - frame.sb_sample[blk][1][sb]
103                    frame.sb_sample[blk][0][sb] = ch_a
104                    frame.sb_sample[blk][1][sb] = ch_b
105
106    return 0
107
108
109def sbc_frame_synthesis_sig(frame, ch, blk, proto_table):
110    global V, N
111    M = frame.nr_subbands
112    L = 10 * M
113    M2 = 2*M
114    L2 = 2*L
115
116    S = np.zeros(M)
117    U = np.zeros(L)
118    W = np.zeros(L)
119    frame.X = np.zeros(M)
120
121    for i in range(M):
122        S[i] = frame.sb_sample[blk][ch][i]
123
124    for i in range(L2-1, M2-1,-1):
125        V[ch][i] = V[ch][i-M2]
126
127    for k in range(M2):
128        V[ch][k] = 0
129        for i in range(M):
130            V[ch][k] += N[k][i] * S[i]
131
132    for i in range(5):
133        for j in range(M):
134            U[i*M2+j] = V[ch][i*2*M2+j]
135            U[(i*2+1)*M+j] = V[ch][(i*4+3)*M+j]
136
137    for i in range(L):
138        D = proto_table[i] * (-M)
139        W[i] = U[i]*D
140
141
142    offset = blk*M
143    for j in range(M):
144        for i in range(10):
145            frame.X[j] += W[j+M*i]
146        frame.pcm[ch][offset + j] = np.int16(frame.X[j])
147
148
149def sbc_frame_synthesis_v1(frame, ch, blk, proto_table):
150    global V
151    N = matrix_N()
152
153    M = frame.nr_subbands
154    L = 10 * M
155    M2 = 2*M
156    L2 = 2*L
157
158    S = np.zeros(M)
159    W = np.zeros(L)
160    frame.X = np.zeros(M)
161
162    for i in range(M):
163        S[i] = frame.sb_sample[blk][ch][i]
164
165    for i in range(L2-1, M2-1,-1):
166        V[ch][i] = V[ch][i-M2]
167
168
169    for k in range(M2):
170        V[ch][k] = 0
171        for i in range(M):
172            V[ch][k] += N[k][i] * S[i]
173
174    for i in range(L):
175        D = proto_table[i] * (-M)
176        W[i] = D * VSGN(i,M2) * V[ch][remap_V(i)]
177
178    offset = blk*M
179    for j in range(M):
180        for i in range(10):
181            frame.X[j] += W[j+M*i]
182        frame.pcm[ch][offset + j] = np.int16(frame.X[j])
183
184
185def sbc_frame_synthesis(frame, ch, blk, proto_table, implementation = "SIG"):
186    global total_time_ms
187
188    t1 = time_ms()
189    if implementation == "SIG":
190         sbc_frame_synthesis_sig(frame, ch, blk, proto_table)
191    elif implementation == "V1":
192        sbc_frame_synthesis_v1(frame, ch, blk, proto_table)
193    else:
194        print ("synthesis %s not implemented" % implementation)
195        exit(1)
196
197    t2 = time_ms()
198    total_time_ms += t2-t1
199
200
201def sbc_init_synthesis_sig(M):
202    global N
203    M2 = M << 1
204
205    N = np.zeros(shape = (M2,M))
206    for k in range(M2):
207        for i in range(M):
208            N[k][i] = np.cos((i+0.5)*(k+M/2)*np.pi/M)
209
210
211
212def sbc_init_sythesis(nr_subbands, implementation = "SIG"):
213    if implementation == "SIG":
214         sbc_init_synthesis_sig(nr_subbands)
215    elif implementation == "V1":
216        sbc_init_synthesis_v1(nr_subbands)
217    else:
218        print ("synthesis %s not implemented" % implementation)
219        exit(1)
220
221
222def sbc_synthesis(frame, implementation = "SIG"):
223    if frame.nr_subbands == 4:
224        proto_table = Proto_4_40
225    elif frame.nr_subbands == 8:
226        proto_table = Proto_8_80
227    else:
228        return -1
229    for ch in range(frame.nr_channels):
230        for blk in range(frame.nr_blocks):
231            sbc_frame_synthesis(frame, ch, blk, proto_table, implementation)
232
233    return frame.nr_blocks * frame.nr_subbands
234
235def sbc_decode(frame, implementation = "SIG"):
236    err = sbc_reconstruct_subband_samples(frame)
237    if err >= 0:
238        err = sbc_synthesis(frame, implementation)
239    return err
240
241
242def write_wav_file(fout, frame):
243    values = []
244
245    for i in range(frame.nr_subbands * frame.nr_blocks):
246        for ch in range(frame.nr_channels):
247            try:
248                packed_value = struct.pack('h', frame.pcm[ch][i])
249                values.append(packed_value)
250            except struct.error:
251                print frame
252                print i, frame.pcm[ch][i], frame.pcm[ch]
253                exit(1)
254
255    value_str = ''.join(values)
256    fout.writeframes(value_str)
257
258
259
260if __name__ == "__main__":
261    usage = '''
262    Usage: ./sbc_decoder.py input.sbc implementation[default=SIG, V1]
263    '''
264
265    if (len(sys.argv) < 2):
266        print(usage)
267        sys.exit(1)
268    try:
269        infile = sys.argv[1]
270        if not infile.endswith('.sbc'):
271            print(usage)
272            sys.exit(1)
273
274        wavfile = infile.replace('.sbc', '-decoded.wav')
275        fout = False
276
277        implementation = "SIG"
278        if len(sys.argv) == 3:
279            implementation = sys.argv[2]
280            if implementation != "V1":
281                print ("synthesis %s not implemented" % implementation)
282                exit(1)
283
284        print ("\nSynthesis implementation: %s\n" % implementation)
285
286        with open (infile, 'rb') as fin:
287            try:
288                fin.seek(0, 2)
289                file_size = fin.tell()
290                fin.seek(0, 0)
291
292                frame_count = 0
293                while True:
294                    frame = SBCFrame()
295                    if frame_count % 200 == 0:
296                        print "== Frame %d == %d" % (frame_count, fin.tell())
297
298                    err = sbc_unpack_frame(fin, file_size - fin.tell(), frame)
299                    if frame_count == 0:
300                        sbc_init_sythesis(frame.nr_subbands, implementation)
301                        print frame
302
303
304                    if err:
305                        print "error, frame_count: ", frame_count
306                        break
307
308
309                    sbc_decode(frame, implementation)
310
311                    if frame_count == 0:
312                        fout = wave.open(wavfile, 'w')
313                        fout.setnchannels(frame.nr_channels)
314                        fout.setsampwidth(2)
315                        fout.setframerate(sampling_frequencies[frame.sampling_frequency])
316                        fout.setnframes(0)
317                        fout.setcomptype = 'NONE'
318
319                    write_wav_file(fout, frame)
320                    frame_count += 1
321
322                    # if frame_count == 1:
323                    #     break
324
325            except TypeError as err:
326                if not fout:
327                    print err
328                else:
329                    fout.close()
330                    if frame_count > 0:
331                        print ("DONE, SBC file %s decoded into WAV file %s " % (infile, wavfile))
332                        print ("Average sythesis time per frame: %d ms/frame" % (total_time_ms/frame_count))
333                    else:
334                        print ("No frame found")
335                exit(0)
336
337        fout.close()
338        if frame_count > 0:
339            print ("DONE: SBC file %s decoded into WAV file %s " % (infile, wavfile))
340            print ("Average sythesis time per frame: %d ms/frame" % (total_time_ms/frame_count))
341        else:
342            print ("No frame found")
343
344    except IOError as e:
345        print(usage)
346        sys.exit(1)
347
348
349
350
351
352