1d86ce1b2SMilanka Ringwald#!/usr/bin/env python 2d86ce1b2SMilanka Ringwaldimport numpy as np 3d86ce1b2SMilanka Ringwaldimport wave 4d86ce1b2SMilanka Ringwaldimport struct 5d86ce1b2SMilanka Ringwaldimport sys 6c21a9c2fSMilanka Ringwaldfrom sbc import * 7205be8eaSMilanka Ringwaldfrom sbc_synthesis_v1 import * 8d86ce1b2SMilanka Ringwald 9c21a9c2fSMilanka RingwaldV = np.zeros(shape = (2, 10*2*8)) 10205be8eaSMilanka RingwaldN = np.zeros(shape = (16,8)) 111bd8157eSMilanka Ringwaldtotal_time_ms = 0 12d86ce1b2SMilanka Ringwald 135665ea35SMilanka Ringwalddef sbc_unpack_frame(fin, available_bytes, frame): 145665ea35SMilanka Ringwald if available_bytes == 0: 15f08a674bSMilanka Ringwald print "no available_bytes" 165665ea35SMilanka Ringwald raise TypeError 175665ea35SMilanka Ringwald 18d86ce1b2SMilanka Ringwald frame.syncword = get_bits(fin,8) 19d86ce1b2SMilanka Ringwald if frame.syncword != 156: 20f08a674bSMilanka Ringwald print ("out of sync %02x" % frame.syncword) 21d86ce1b2SMilanka Ringwald return -1 22d86ce1b2SMilanka Ringwald frame.sampling_frequency = get_bits(fin,2) 23d86ce1b2SMilanka Ringwald frame.nr_blocks = nr_blocks[get_bits(fin,2)] 24ba345fb8SMilanka Ringwald 25d86ce1b2SMilanka Ringwald frame.channel_mode = get_bits(fin,2) 26ad470863SMilanka Ringwald 27d86ce1b2SMilanka Ringwald if frame.channel_mode == MONO: 28d86ce1b2SMilanka Ringwald frame.nr_channels = 1 29d86ce1b2SMilanka Ringwald else: 30d86ce1b2SMilanka Ringwald frame.nr_channels = 2 31d86ce1b2SMilanka Ringwald 32d86ce1b2SMilanka Ringwald frame.allocation_method = get_bits(fin,1) 33d86ce1b2SMilanka Ringwald frame.nr_subbands = nr_subbands[get_bits(fin,1)] 345c9bef5bSMilanka Ringwald frame.init(frame.nr_blocks, frame.nr_subbands, frame.nr_channels) 355c9bef5bSMilanka Ringwald 36d86ce1b2SMilanka Ringwald frame.bitpool = get_bits(fin,8) 37d86ce1b2SMilanka Ringwald frame.crc_check = get_bits(fin,8) 38d86ce1b2SMilanka Ringwald 395c9bef5bSMilanka Ringwald # frame.join = np.zeros(frame.nr_subbands, dtype = np.uint8) 40d86ce1b2SMilanka Ringwald 41d86ce1b2SMilanka Ringwald if frame.channel_mode == JOINT_STEREO: 42d86ce1b2SMilanka Ringwald for sb in range(frame.nr_subbands-1): 43d86ce1b2SMilanka Ringwald frame.join[sb] = get_bits(fin,1) 44d86ce1b2SMilanka Ringwald get_bits(fin,1) # RFA 45d86ce1b2SMilanka Ringwald 46d86ce1b2SMilanka Ringwald frame.scale_factor = np.zeros(shape=(frame.nr_channels, frame.nr_subbands), dtype = np.int32) 47d86ce1b2SMilanka Ringwald 48d86ce1b2SMilanka Ringwald # print frame.audio_sample 49d86ce1b2SMilanka Ringwald for ch in range(frame.nr_channels): 50d86ce1b2SMilanka Ringwald for sb in range(frame.nr_subbands): 51d86ce1b2SMilanka Ringwald frame.scale_factor[ch][sb] = get_bits(fin, 4) 521522543dSMilanka Ringwald 53c21a9c2fSMilanka Ringwald crc = calculate_crc(frame) 54c21a9c2fSMilanka Ringwald if crc != frame.crc_check: 55ad470863SMilanka Ringwald print frame 56c21a9c2fSMilanka Ringwald print "error, crc not equal: ", crc, frame.crc_check 57c21a9c2fSMilanka Ringwald exit(1) 58c21a9c2fSMilanka Ringwald 59ad470863SMilanka Ringwald frame.scalefactor = np.zeros(shape=(frame.nr_channels, frame.nr_subbands), dtype = np.int32) 60d86ce1b2SMilanka Ringwald for ch in range(frame.nr_channels): 61d86ce1b2SMilanka Ringwald for sb in range(frame.nr_subbands): 62d86ce1b2SMilanka Ringwald frame.scalefactor[ch][sb] = 1 << (frame.scale_factor[ch][sb] + 1) 63d86ce1b2SMilanka Ringwald 64d86ce1b2SMilanka Ringwald 65ad470863SMilanka Ringwald frame.bits = sbc_bit_allocation(frame) 66ad470863SMilanka Ringwald 67ad470863SMilanka Ringwald frame.audio_sample = np.ndarray(shape=(frame.nr_blocks, frame.nr_channels, frame.nr_subbands), dtype = np.uint16) 68d86ce1b2SMilanka Ringwald for blk in range(frame.nr_blocks): 69d86ce1b2SMilanka Ringwald for ch in range(frame.nr_channels): 70d86ce1b2SMilanka Ringwald for sb in range(frame.nr_subbands): 71c21a9c2fSMilanka Ringwald frame.audio_sample[blk][ch][sb] = get_bits(fin, frame.bits[ch][sb]) 72d86ce1b2SMilanka Ringwald #print "block %2d - audio sample: %s" % (blk, frame.audio_sample[blk][0]) 73d86ce1b2SMilanka Ringwald 74d86ce1b2SMilanka Ringwald drop_remaining_bits() 75ad470863SMilanka Ringwald return 0 76d86ce1b2SMilanka Ringwald 77ad470863SMilanka Ringwalddef sbc_reconstruct_subband_samples(frame): 78c21a9c2fSMilanka Ringwald frame.levels = np.zeros(shape=(frame.nr_channels, frame.nr_subbands), dtype = np.int32) 79c21a9c2fSMilanka Ringwald frame.sb_sample = np.zeros(shape=(frame.nr_blocks, frame.nr_channels, frame.nr_subbands)) 80d86ce1b2SMilanka Ringwald 81d86ce1b2SMilanka Ringwald for ch in range(frame.nr_channels): 82d86ce1b2SMilanka Ringwald for sb in range(frame.nr_subbands): 83c21a9c2fSMilanka Ringwald frame.levels[ch][sb] = pow(2.0, frame.bits[ch][sb]) - 1 84d86ce1b2SMilanka Ringwald 85d86ce1b2SMilanka Ringwald for blk in range(frame.nr_blocks): 86d86ce1b2SMilanka Ringwald for ch in range(frame.nr_channels): 87d86ce1b2SMilanka Ringwald for sb in range(frame.nr_subbands): 88c21a9c2fSMilanka Ringwald if frame.levels[ch][sb] > 0: 89c21a9c2fSMilanka Ringwald AS = frame.audio_sample[blk][ch][sb] 90c21a9c2fSMilanka Ringwald L = frame.levels[ch][sb] 9157f2bc22SMilanka Ringwald SF = frame.scalefactor[ch][sb] 92ba345fb8SMilanka Ringwald frame.sb_sample[blk][ch][sb] = SF * ((AS*2.0+1.0) / L -1.0 ) 93d86ce1b2SMilanka Ringwald else: 94c21a9c2fSMilanka Ringwald frame.sb_sample[blk][ch][sb] = 0 95d86ce1b2SMilanka Ringwald 96d86ce1b2SMilanka Ringwald # sythesis filter 97d86ce1b2SMilanka Ringwald if frame.channel_mode == JOINT_STEREO: 98d86ce1b2SMilanka Ringwald for blk in range(frame.nr_blocks): 99d86ce1b2SMilanka Ringwald for sb in range(frame.nr_subbands): 100d86ce1b2SMilanka Ringwald if frame.join[sb]==1: 101c21a9c2fSMilanka Ringwald ch_a = frame.sb_sample[blk][0][sb] + frame.sb_sample[blk][1][sb] 102c21a9c2fSMilanka Ringwald ch_b = frame.sb_sample[blk][0][sb] - frame.sb_sample[blk][1][sb] 103ef8a7a12SMilanka Ringwald frame.sb_sample[blk][0][sb] = ch_a 104ef8a7a12SMilanka Ringwald frame.sb_sample[blk][1][sb] = ch_b 105c21a9c2fSMilanka Ringwald 106d86ce1b2SMilanka Ringwald return 0 107d86ce1b2SMilanka Ringwald 108d86ce1b2SMilanka Ringwald 1091bd8157eSMilanka Ringwalddef sbc_frame_synthesis_sig(frame, ch, blk, proto_table): 110205be8eaSMilanka Ringwald global V, N 111d86ce1b2SMilanka Ringwald M = frame.nr_subbands 112d86ce1b2SMilanka Ringwald L = 10 * M 113d86ce1b2SMilanka Ringwald M2 = 2*M 114d86ce1b2SMilanka Ringwald L2 = 2*L 115d86ce1b2SMilanka Ringwald 116d86ce1b2SMilanka Ringwald S = np.zeros(M) 117d86ce1b2SMilanka Ringwald U = np.zeros(L) 118d86ce1b2SMilanka Ringwald W = np.zeros(L) 119d86ce1b2SMilanka Ringwald frame.X = np.zeros(M) 120d86ce1b2SMilanka Ringwald 121d86ce1b2SMilanka Ringwald for i in range(M): 122c21a9c2fSMilanka Ringwald S[i] = frame.sb_sample[blk][ch][i] 123d86ce1b2SMilanka Ringwald 124d86ce1b2SMilanka Ringwald for i in range(L2-1, M2-1,-1): 125d86ce1b2SMilanka Ringwald V[ch][i] = V[ch][i-M2] 126d86ce1b2SMilanka Ringwald 127d86ce1b2SMilanka Ringwald for k in range(M2): 128d86ce1b2SMilanka Ringwald V[ch][k] = 0 129d86ce1b2SMilanka Ringwald for i in range(M): 130205be8eaSMilanka Ringwald V[ch][k] += N[k][i] * S[i] 131d86ce1b2SMilanka Ringwald 132d86ce1b2SMilanka Ringwald for i in range(5): 133d86ce1b2SMilanka Ringwald for j in range(M): 134d86ce1b2SMilanka Ringwald U[i*M2+j] = V[ch][i*2*M2+j] 135d82cd87cSMilanka Ringwald U[(i*2+1)*M+j] = V[ch][(i*4+3)*M+j] 136d86ce1b2SMilanka Ringwald 137d86ce1b2SMilanka Ringwald for i in range(L): 138d86ce1b2SMilanka Ringwald D = proto_table[i] * (-M) 139d86ce1b2SMilanka Ringwald W[i] = U[i]*D 140d86ce1b2SMilanka Ringwald 141d86ce1b2SMilanka Ringwald 1421522543dSMilanka Ringwald offset = blk*M 143d86ce1b2SMilanka Ringwald for j in range(M): 144d86ce1b2SMilanka Ringwald for i in range(10): 145d86ce1b2SMilanka Ringwald frame.X[j] += W[j+M*i] 1461522543dSMilanka Ringwald frame.pcm[ch][offset + j] = np.int16(frame.X[j]) 147d86ce1b2SMilanka Ringwald 148d86ce1b2SMilanka Ringwald 149205be8eaSMilanka Ringwalddef sbc_frame_synthesis_v1(frame, ch, blk, proto_table): 150205be8eaSMilanka Ringwald global V 151205be8eaSMilanka Ringwald N = matrix_N() 152205be8eaSMilanka Ringwald 153205be8eaSMilanka Ringwald M = frame.nr_subbands 154205be8eaSMilanka Ringwald L = 10 * M 155205be8eaSMilanka Ringwald M2 = 2*M 156205be8eaSMilanka Ringwald L2 = 2*L 157205be8eaSMilanka Ringwald 158205be8eaSMilanka Ringwald S = np.zeros(M) 159205be8eaSMilanka Ringwald W = np.zeros(L) 160205be8eaSMilanka Ringwald frame.X = np.zeros(M) 161205be8eaSMilanka Ringwald 162205be8eaSMilanka Ringwald for i in range(M): 163205be8eaSMilanka Ringwald S[i] = frame.sb_sample[blk][ch][i] 164205be8eaSMilanka Ringwald 165205be8eaSMilanka Ringwald for i in range(L2-1, M2-1,-1): 166205be8eaSMilanka Ringwald V[ch][i] = V[ch][i-M2] 167205be8eaSMilanka Ringwald 168205be8eaSMilanka Ringwald 169205be8eaSMilanka Ringwald for k in range(M2): 170205be8eaSMilanka Ringwald V[ch][k] = 0 171205be8eaSMilanka Ringwald for i in range(M): 172205be8eaSMilanka Ringwald V[ch][k] += N[k][i] * S[i] 173205be8eaSMilanka Ringwald 174205be8eaSMilanka Ringwald for i in range(L): 175205be8eaSMilanka Ringwald D = proto_table[i] * (-M) 176*fc754a2bSMilanka Ringwald W[i] = D * VSGN(i,M2) * V[ch][remap_V(i)] 177205be8eaSMilanka Ringwald 178205be8eaSMilanka Ringwald offset = blk*M 179205be8eaSMilanka Ringwald for j in range(M): 180205be8eaSMilanka Ringwald for i in range(10): 181205be8eaSMilanka Ringwald frame.X[j] += W[j+M*i] 182205be8eaSMilanka Ringwald frame.pcm[ch][offset + j] = np.int16(frame.X[j]) 183205be8eaSMilanka Ringwald 184205be8eaSMilanka Ringwald 185205be8eaSMilanka Ringwalddef sbc_frame_synthesis(frame, ch, blk, proto_table, implementation = "SIG"): 186205be8eaSMilanka Ringwald global total_time_ms 1871bd8157eSMilanka Ringwald 1881bd8157eSMilanka Ringwald t1 = time_ms() 1891bd8157eSMilanka Ringwald if implementation == "SIG": 1901bd8157eSMilanka Ringwald sbc_frame_synthesis_sig(frame, ch, blk, proto_table) 1911bd8157eSMilanka Ringwald elif implementation == "V1": 1921bd8157eSMilanka Ringwald sbc_frame_synthesis_v1(frame, ch, blk, proto_table) 1931bd8157eSMilanka Ringwald else: 1941bd8157eSMilanka Ringwald print ("synthesis %s not implemented" % implementation) 1951bd8157eSMilanka Ringwald exit(1) 1961bd8157eSMilanka Ringwald 1971bd8157eSMilanka Ringwald t2 = time_ms() 1981bd8157eSMilanka Ringwald total_time_ms += t2-t1 1991bd8157eSMilanka Ringwald 2001bd8157eSMilanka Ringwald 201205be8eaSMilanka Ringwalddef sbc_init_synthesis_sig(M): 202205be8eaSMilanka Ringwald global N 203205be8eaSMilanka Ringwald M2 = M << 1 204205be8eaSMilanka Ringwald 205205be8eaSMilanka Ringwald N = np.zeros(shape = (M2,M)) 206205be8eaSMilanka Ringwald for k in range(M2): 207205be8eaSMilanka Ringwald for i in range(M): 208205be8eaSMilanka Ringwald N[k][i] = np.cos((i+0.5)*(k+M/2)*np.pi/M) 209205be8eaSMilanka Ringwald 210205be8eaSMilanka Ringwald 211205be8eaSMilanka Ringwald 212205be8eaSMilanka Ringwalddef sbc_init_sythesis(nr_subbands, implementation = "SIG"): 213205be8eaSMilanka Ringwald if implementation == "SIG": 214205be8eaSMilanka Ringwald sbc_init_synthesis_sig(nr_subbands) 215205be8eaSMilanka Ringwald elif implementation == "V1": 216205be8eaSMilanka Ringwald sbc_init_synthesis_v1(nr_subbands) 217205be8eaSMilanka Ringwald else: 218205be8eaSMilanka Ringwald print ("synthesis %s not implemented" % implementation) 219205be8eaSMilanka Ringwald exit(1) 220205be8eaSMilanka Ringwald 221205be8eaSMilanka Ringwald 222205be8eaSMilanka Ringwalddef sbc_synthesis(frame, implementation = "SIG"): 223d86ce1b2SMilanka Ringwald if frame.nr_subbands == 4: 224d86ce1b2SMilanka Ringwald proto_table = Proto_4_40 225d86ce1b2SMilanka Ringwald elif frame.nr_subbands == 8: 226d86ce1b2SMilanka Ringwald proto_table = Proto_8_80 227d86ce1b2SMilanka Ringwald else: 228d86ce1b2SMilanka Ringwald return -1 229d86ce1b2SMilanka Ringwald for ch in range(frame.nr_channels): 230d86ce1b2SMilanka Ringwald for blk in range(frame.nr_blocks): 231205be8eaSMilanka Ringwald sbc_frame_synthesis(frame, ch, blk, proto_table, implementation) 232d86ce1b2SMilanka Ringwald 233d86ce1b2SMilanka Ringwald return frame.nr_blocks * frame.nr_subbands 234d86ce1b2SMilanka Ringwald 235205be8eaSMilanka Ringwalddef sbc_decode(frame, implementation = "SIG"): 236ad470863SMilanka Ringwald err = sbc_reconstruct_subband_samples(frame) 237ad470863SMilanka Ringwald if err >= 0: 238205be8eaSMilanka Ringwald err = sbc_synthesis(frame, implementation) 239ad470863SMilanka Ringwald return err 240d86ce1b2SMilanka Ringwald 241ad470863SMilanka Ringwald 242ad470863SMilanka Ringwalddef write_wav_file(fout, frame): 243d86ce1b2SMilanka Ringwald values = [] 2441522543dSMilanka Ringwald 2451522543dSMilanka Ringwald for i in range(frame.nr_subbands * frame.nr_blocks): 2461522543dSMilanka Ringwald for ch in range(frame.nr_channels): 247ad470863SMilanka Ringwald try: 2481522543dSMilanka Ringwald packed_value = struct.pack('h', frame.pcm[ch][i]) 249d86ce1b2SMilanka Ringwald values.append(packed_value) 250ad470863SMilanka Ringwald except struct.error: 251ad470863SMilanka Ringwald print frame 2521522543dSMilanka Ringwald print i, frame.pcm[ch][i], frame.pcm[ch] 253ad470863SMilanka Ringwald exit(1) 254d86ce1b2SMilanka Ringwald 255d86ce1b2SMilanka Ringwald value_str = ''.join(values) 256d86ce1b2SMilanka Ringwald fout.writeframes(value_str) 257d86ce1b2SMilanka Ringwald 258d86ce1b2SMilanka Ringwald 259205be8eaSMilanka Ringwald 260ba114a98SMatthias Ringwaldif __name__ == "__main__": 261ba114a98SMatthias Ringwald usage = ''' 262205be8eaSMilanka Ringwald Usage: ./sbc_decoder.py input.sbc implementation[default=SIG, V1] 263ba114a98SMatthias Ringwald ''' 264d86ce1b2SMilanka Ringwald 265ba114a98SMatthias Ringwald if (len(sys.argv) < 2): 266ba114a98SMatthias Ringwald print(usage) 267ba114a98SMatthias Ringwald sys.exit(1) 268ba114a98SMatthias Ringwald try: 269ba114a98SMatthias Ringwald infile = sys.argv[1] 270ba114a98SMatthias Ringwald if not infile.endswith('.sbc'): 271ba114a98SMatthias Ringwald print(usage) 272ba114a98SMatthias Ringwald sys.exit(1) 273d86ce1b2SMilanka Ringwald 274ba114a98SMatthias Ringwald wavfile = infile.replace('.sbc', '-decoded.wav') 275ad470863SMilanka Ringwald fout = False 276d86ce1b2SMilanka Ringwald 277205be8eaSMilanka Ringwald implementation = "SIG" 278205be8eaSMilanka Ringwald if len(sys.argv) == 3: 279205be8eaSMilanka Ringwald implementation = sys.argv[2] 280205be8eaSMilanka Ringwald if implementation != "V1": 281205be8eaSMilanka Ringwald print ("synthesis %s not implemented" % implementation) 282205be8eaSMilanka Ringwald exit(1) 283205be8eaSMilanka Ringwald 284205be8eaSMilanka Ringwald print ("\nSynthesis implementation: %s\n" % implementation) 285205be8eaSMilanka Ringwald 286ba114a98SMatthias Ringwald with open (infile, 'rb') as fin: 287ba114a98SMatthias Ringwald try: 2885665ea35SMilanka Ringwald fin.seek(0, 2) 2895665ea35SMilanka Ringwald file_size = fin.tell() 2905665ea35SMilanka Ringwald fin.seek(0, 0) 2915665ea35SMilanka Ringwald 292ba114a98SMatthias Ringwald frame_count = 0 293ba114a98SMatthias Ringwald while True: 294205be8eaSMilanka Ringwald frame = SBCFrame() 295ba114a98SMatthias Ringwald if frame_count % 200 == 0: 296f08a674bSMilanka Ringwald print "== Frame %d == %d" % (frame_count, fin.tell()) 297f08a674bSMilanka Ringwald 298205be8eaSMilanka Ringwald err = sbc_unpack_frame(fin, file_size - fin.tell(), frame) 2995c9bef5bSMilanka Ringwald if frame_count == 0: 300205be8eaSMilanka Ringwald sbc_init_sythesis(frame.nr_subbands, implementation) 301205be8eaSMilanka Ringwald print frame 302205be8eaSMilanka Ringwald 303ad470863SMilanka Ringwald 304ba114a98SMatthias Ringwald if err: 305ba114a98SMatthias Ringwald print "error, frame_count: ", frame_count 306ba114a98SMatthias Ringwald break 307ba114a98SMatthias Ringwald 3085c9bef5bSMilanka Ringwald 309205be8eaSMilanka Ringwald sbc_decode(frame, implementation) 310ba114a98SMatthias Ringwald 311ba114a98SMatthias Ringwald if frame_count == 0: 312ba114a98SMatthias Ringwald fout = wave.open(wavfile, 'w') 313205be8eaSMilanka Ringwald fout.setnchannels(frame.nr_channels) 314ba114a98SMatthias Ringwald fout.setsampwidth(2) 315205be8eaSMilanka Ringwald fout.setframerate(sampling_frequencies[frame.sampling_frequency]) 316ba114a98SMatthias Ringwald fout.setnframes(0) 317ba114a98SMatthias Ringwald fout.setcomptype = 'NONE' 318ba114a98SMatthias Ringwald 319205be8eaSMilanka Ringwald write_wav_file(fout, frame) 320ba114a98SMatthias Ringwald frame_count += 1 321ba114a98SMatthias Ringwald 322205be8eaSMilanka Ringwald # if frame_count == 1: 323205be8eaSMilanka Ringwald # break 3241bd8157eSMilanka Ringwald 325ad470863SMilanka Ringwald except TypeError as err: 326ad470863SMilanka Ringwald if not fout: 327ad470863SMilanka Ringwald print err 328ad470863SMilanka Ringwald else: 329ba114a98SMatthias Ringwald fout.close() 3301bd8157eSMilanka Ringwald if frame_count > 0: 331ad470863SMilanka Ringwald print ("DONE, SBC file %s decoded into WAV file %s " % (infile, wavfile)) 332205be8eaSMilanka Ringwald print ("Average sythesis time per frame: %d ms/frame" % (total_time_ms/frame_count)) 3331bd8157eSMilanka Ringwald else: 3341bd8157eSMilanka Ringwald print ("No frame found") 335ba114a98SMatthias Ringwald exit(0) 336d86ce1b2SMilanka Ringwald 3371bd8157eSMilanka Ringwald fout.close() 3381bd8157eSMilanka Ringwald if frame_count > 0: 3391bd8157eSMilanka Ringwald print ("DONE: SBC file %s decoded into WAV file %s " % (infile, wavfile)) 3401bd8157eSMilanka Ringwald print ("Average sythesis time per frame: %d ms/frame" % (total_time_ms/frame_count)) 3411bd8157eSMilanka Ringwald else: 3421bd8157eSMilanka Ringwald print ("No frame found") 3431bd8157eSMilanka Ringwald 344ba114a98SMatthias Ringwald except IOError as e: 345ba114a98SMatthias Ringwald print(usage) 346ba114a98SMatthias Ringwald sys.exit(1) 347d86ce1b2SMilanka Ringwald 348d86ce1b2SMilanka Ringwald 349d86ce1b2SMilanka Ringwald 350d86ce1b2SMilanka Ringwald 351d86ce1b2SMilanka Ringwald 352