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