xref: /btstack/test/sbc/sbc_encoder.py (revision c21a9c2f3621834ccdbca1efaf4d958002a4ef9c)
1#!/usr/bin/env python
2import numpy as np
3import wave
4import struct
5import sys
6from sbc import *
7
8X = np.zeros(40)
9
10def fetch_samples_for_next_sbc_frame(fin, nr_audio_frames, frame):
11    raw_data = fin.readframes(nr_audio_frames) # Returns byte data
12
13    total_samples = nr_audio_frames * frame.nr_channels
14    fmt = "%ih" % total_samples # read signed 2 byte shorts
15
16    frame.pcm =  np.array(struct.unpack(fmt, raw_data))
17    del raw_data
18
19    # channels = [ [] for ch in range(frame.nr_channels) ]
20    # for index, value in enumerate(integer_data):
21    #     bucket = index % nr_channels
22    #     channels[bucket].append(value)
23
24
25def sbc_analyse(frame, ch, blk, C, debug):
26    global X
27    M = frame.nr_subbands
28    L = 10 * M
29    M2 = 2*M
30    L2 = 2*L
31
32    Z = np.zeros(L)
33    Y = np.zeros(M2)
34    W = np.zeros(shape=(M, M2))
35    S = np.zeros(M)
36
37    for i in range(L-1, M-1, -1):
38        X[i] = X[i-M]
39    for i in range(M-1, -1, -1):
40        X[i] = frame.EX[M-1-i]
41
42    for i in range(L):
43        Z[i] = X[i] * C[i]
44
45    for i in range(M2):
46        for k in range(5):
47            Y[i] += Z[i+k*8]
48
49    for i in range(M):
50        for k in range(M2):
51            W[i][k] = np.cos((i+0.5)*(k-2)*np.pi/M)
52            S[i] += W[i][k] * Y[k]
53
54    if debug:
55        #print "EX:", frame.EX
56        print "X:", X
57        print "Z:"
58        print "Y:", Y
59        print "W:", W
60        print "S:", S
61
62    for sb in range(M):
63        frame.sb_sample[blk][ch][sb] = S[sb]
64
65
66def sbc_encode(frame,debug):
67    if frame.nr_subbands == 4:
68        proto_table = Proto_4_40
69    elif frame.nr_subbands == 8:
70        proto_table = Proto_8_80
71    else:
72        return -1
73
74    frame.sb_sample = np.ndarray(shape=(frame.nr_blocks, frame.nr_channels, frame.nr_subbands))
75
76    # channels = [ [] for ch in range(frame.nr_channels) ]
77    # for index, value in enumerate(frame.pcm):
78    #     bucket = index % frame.nr_channels
79    #     channels[bucket].append(value)
80
81    # print "encoder pcm ", frame.pcm
82
83    index = 0
84    for ch in range(frame.nr_channels):
85        for blk in range(frame.nr_blocks):
86            for sb in range(frame.nr_subbands):
87                frame.EX[sb] = frame.pcm[index] #channels[ch][blk * frame.nr_subbands + sb]
88                index+=1
89            sbc_analyse(frame, ch, blk, proto_table,debug)
90    sbc_quantization(frame)
91
92
93def should_use_joint_coding(frame):
94    return False
95
96def calculate_scalefactor(max_subbandsample):
97    x = 0
98    while True:
99        y = 1 << x + 1
100        if y > max_subbandsample:
101            break
102        x += 1
103    return (x,y)
104
105
106def frame_to_bitstream(frame):
107    global bitstream, bitstream_bits_available
108    init_bitstream()
109
110    add_bits(frame.syncword, 8)
111    add_bits(frame.sampling_frequency, 2)
112    add_bits(frame.nr_blocks/4-1, 2)
113    add_bits(frame.channel_mode, 2)
114    add_bits(frame.allocation_method, 1)
115    add_bits(frame.nr_subbands/4-1, 1)
116    add_bits(frame.bitpool, 8)
117    add_bits(frame.crc_check, 8)
118
119    for sb in range(frame.nr_subbands):
120        add_bits(frame.join[sb],1)
121
122    for ch in range(frame.nr_channels):
123        for sb in range(frame.nr_subbands):
124            add_bits(frame.scale_factor[ch][sb], 4)
125
126    for blk in range(frame.nr_blocks):
127        for ch in range(frame.nr_channels):
128            for sb in range(frame.nr_subbands):
129                add_bits(frame.audio_sample[blk][ch][sb], frame.bits[ch][sb])
130
131    # bitstream_len = 16 + frame.nr_subbands + frame.nr_channels * frame.nr_subbands * 4
132    return bitstream
133
134def sbc_quantization(frame):
135
136    frame.join = np.zeros(frame.nr_subbands, dtype = np.uint8)
137    if should_use_joint_coding(frame):
138        return
139
140    max_subbandsample = np.zeros(shape = (frame.nr_channels, frame.nr_subbands))
141
142    for blk in range(frame.nr_blocks):
143        for ch in range(frame.nr_channels):
144            for sb in range(frame.nr_subbands):
145                m = abs(frame.sb_sample[blk][ch][sb])
146                if max_subbandsample[ch][sb] < m:
147                    max_subbandsample[ch][sb] = m
148
149
150    for ch in range(frame.nr_channels):
151        for sb in range(frame.nr_subbands):
152            (frame.scale_factor[ch][sb], frame.scalefactor[ch][sb]) = calculate_scalefactor(max_subbandsample[ch][sb])
153
154    frame.bits = sbc_bit_allocation(frame)
155
156    # Reconstruct the Audio Samples
157    frame.levels = np.zeros(shape=(frame.nr_channels, frame.nr_subbands), dtype = np.int32)
158    for ch in range(frame.nr_channels):
159        for sb in range(frame.nr_subbands):
160            frame.levels[ch][sb] = pow(2.0, frame.bits[ch][sb]) - 1
161
162    frame.syncword = 156
163    frame.crc_check = calculate_crc(frame)
164
165    for blk in range(frame.nr_blocks):
166        for ch in range(frame.nr_channels):
167            for sb in range(frame.nr_subbands):
168                if frame.levels[ch][sb] > 0:
169                    SB = frame.sb_sample[blk][ch][sb]
170                    SF = frame.scalefactor[ch][sb]
171                    L  = frame.levels[ch][sb]
172                    AS = np.uint16(((SB * L / SF    + L) - 1.0)/2.0)
173                    frame.audio_sample[blk][ch][sb] = AS
174                else:
175                    frame.audio_sample[blk][ch][sb] = 0
176
177
178    return 0
179
180
181# usage = '''
182# Usage: ./sbc_encoder.py input.wav block_size nr_subbands bitpool
183# '''
184# nr_blocks = 0
185# nr_subbands = 0
186
187# if (len(sys.argv) < 5):
188#     print(usage)
189#     sys.exit(1)
190# try:
191#     infile = sys.argv[1]
192#     if not infile.endswith('.wav'):
193#         print(usage)
194#         sys.exit(1)
195#     nr_blocks = int(sys.argv[2])
196#     nr_subbands = int(sys.argv[3])
197#     bitpool = int(sys.argv[4])
198#     sbcfile = infile.replace('.wav', '-encoded.sbc')
199
200#     fin = wave.open(infile, 'rb')
201
202#     wav_nr_channels = fin.getnchannels()
203#     wav_sample_rate = fin.getframerate()
204#     wav_nr_frames = fin.getnframes()
205#     sbc_sampling_frequency = sbc_sampling_frequency_index(wav_sample_rate)
206
207#     sbc_frame_count = 0
208#     audio_frame_count = 0
209
210#     while audio_frame_count < wav_nr_frames:
211#         if sbc_frame_count % 200 == 0:
212#             print "== Frame %d ==" % (sbc_frame_count)
213
214#         sbc_encoder_frame = SBCFrame(nr_blocks, nr_subbands, wav_nr_channels, sbc_sampling_frequency, bitpool)
215
216#         wav_nr_audio_frames = sbc_encoder_frame.nr_blocks * sbc_encoder_frame.nr_subbands
217#         fetch_samples_for_next_sbc_frame(fin, wav_nr_audio_frames, sbc_encoder_frame)
218#         sbc_encode(sbc_encoder_frame)
219
220#         # stream = frame_to_bitstream(frame)
221#         audio_frame_count += wav_nr_audio_frames
222#         sbc_frame_count += 1
223
224#     # except TypeError:
225#     #     fin.close()
226#     #     print "DONE, WAV file %s encoded into SBC file %s ", (infile, sbcfile)
227
228#     #channels, num_audio_frames, wav_nr_channels, wav_sample_rate = read_waw_file(wavfile)
229
230
231# except IOError as e:
232#     print(usage)
233#     sys.exit(1)
234
235
236
237
238
239