📄 sbc.c
字号:
for (blk = 0; blk < frame->blocks; blk++) sbc_analyze_eight(state, frame, ch, blk); return frame->blocks * 8; default: return -EIO; }}/* * Packs the SBC frame from frame into the memory at data. At most len * bytes will be used, should more memory be needed an appropriate * error code will be returned. Returns the length of the packed frame * on success or a negative value on error. * * The error codes are: * -1 Not enough memory reserved * -2 Unsupported sampling rate * -3 Unsupported number of blocks * -4 Unsupported number of subbands * -5 Bitpool value out of bounds * -99 not implemented */static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len){ int produced; /* Will copy the header parts for CRC-8 calculation here */ uint8_t crc_header[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; int crc_pos = 0; /* Sampling frequency as temporary value for table lookup */ uint8_t sf; uint16_t audio_sample; int ch, sb, blk, bit; /* channel, subband, block and bit counters */ int bits[2][8]; /* bits distribution */ int levels[2][8]; /* levels are derived from that */ u_int32_t scalefactor[2][8]; /* derived from frame->scale_factor */ data[0] = SBC_SYNCWORD; if (frame->sampling_frequency == 16000) { data[1] = (SBC_FS_16 & 0x03) << 6; sf = SBC_FS_16; } else if (frame->sampling_frequency == 32000) { data[1] = (SBC_FS_32 & 0x03) << 6; sf = SBC_FS_32; } else if (frame->sampling_frequency == 44100) { data[1] = (SBC_FS_44 & 0x03) << 6; sf = SBC_FS_44; } else if (frame->sampling_frequency == 48000) { data[1] = (SBC_FS_48 & 0x03) << 6; sf = SBC_FS_48; } else return -2; switch (frame->blocks) { case 4: data[1] |= (SBC_NB_4 & 0x03) << 4; break; case 8: data[1] |= (SBC_NB_8 & 0x03) << 4; break; case 12: data[1] |= (SBC_NB_12 & 0x03) << 4; break; case 16: data[1] |= (SBC_NB_16 & 0x03) << 4; break; default: return -3; break; } data[1] |= (frame->channel_mode & 0x03) << 2; data[1] |= (frame->allocation_method & 0x01) << 1; switch (frame->subbands) { case 4: /* Nothing to do */ break; case 8: data[1] |= 0x01; break; default: return -4; break; } data[2] = frame->bitpool; if ((frame->channel_mode == MONO || frame->channel_mode == DUAL_CHANNEL) && frame->bitpool > frame->subbands << 4) return -5; if ((frame->channel_mode == STEREO || frame->channel_mode == JOINT_STEREO) && frame->bitpool > frame->subbands << 5) return -5; /* Can't fill in crc yet */ produced = 32; crc_header[0] = data[1]; crc_header[1] = data[2]; crc_pos = 16; for (ch = 0; ch < frame->channels; ch++) { for (sb = 0; sb < frame->subbands; sb++) { frame->scale_factor[ch][sb] = 0; scalefactor[ch][sb] = 2; for (blk = 0; blk < frame->blocks; blk++) { while (scalefactor[ch][sb] < fabs(frame->sb_sample_f[blk][ch][sb])) { frame->scale_factor[ch][sb]++; scalefactor[ch][sb] *= 2; } } } } if (frame->channel_mode == JOINT_STEREO) { /* like frame->sb_sample but joint stereo */ int32_t sb_sample_j[16][2]; /* scalefactor and scale_factor in joint case */ u_int32_t scalefactor_j[2]; uint8_t scale_factor_j[2]; frame->join = 0; for (sb = 0; sb < frame->subbands - 1; sb++) { scale_factor_j[0] = 0; scalefactor_j[0] = 2; scale_factor_j[1] = 0; scalefactor_j[1] = 2; for (blk = 0; blk < frame->blocks; blk++) { /* Calculate joint stereo signal */ sb_sample_j[blk][0] = (frame->sb_sample_f[blk][0][sb] + frame->sb_sample_f[blk][1][sb]) >> 1; sb_sample_j[blk][1] = (frame->sb_sample_f[blk][0][sb] - frame->sb_sample_f[blk][1][sb]) >> 1; /* calculate scale_factor_j and scalefactor_j for joint case */ while (scalefactor_j[0] < fabs(sb_sample_j[blk][0])) { scale_factor_j[0]++; scalefactor_j[0] *= 2; } while (scalefactor_j[1] < fabs(sb_sample_j[blk][1])) { scale_factor_j[1]++; scalefactor_j[1] *= 2; } } /* decide whether to join this subband */ if ((scalefactor[0][sb] + scalefactor[1][sb]) > (scalefactor_j[0] + scalefactor_j[1]) ) { /* use joint stereo for this subband */ frame->join |= 1 << sb; frame->scale_factor[0][sb] = scale_factor_j[0]; frame->scale_factor[1][sb] = scale_factor_j[1]; scalefactor[0][sb] = scalefactor_j[0]; scalefactor[1][sb] = scalefactor_j[1]; for (blk = 0; blk < frame->blocks; blk++) { frame->sb_sample_f[blk][0][sb] = sb_sample_j[blk][0]; frame->sb_sample_f[blk][1][sb] = sb_sample_j[blk][1]; } } } data[4] = 0; for (sb = 0; sb < frame->subbands - 1; sb++) data[4] |= ((frame->join >> sb) & 0x01) << (frame->subbands - 1 - sb); crc_header[crc_pos >> 3] = data[4]; produced += frame->subbands; crc_pos += frame->subbands; } for (ch = 0; ch < frame->channels; ch++) { for (sb = 0; sb < frame->subbands; sb++) { data[produced >> 3] <<= 4; crc_header[crc_pos >> 3] <<= 4; data[produced >> 3] |= frame->scale_factor[ch][sb] & 0x0F; crc_header[crc_pos >> 3] |= frame->scale_factor[ch][sb] & 0x0F; produced += 4; crc_pos += 4; } } /* align the last crc byte */ if(crc_pos % 8) crc_header[crc_pos >> 3] <<= 8 - (crc_pos % 8); data[3] = sbc_crc8(crc_header, crc_pos); sbc_calculate_bits(frame, bits, sf); for (ch = 0; ch < frame->channels; ch++) { for (sb = 0; sb < frame->subbands; sb++) levels[ch][sb] = (1 << bits[ch][sb]) - 1; } for (blk = 0; blk < frame->blocks; blk++) { for (ch = 0; ch < frame->channels; ch++) { for (sb = 0; sb < frame->subbands; sb++) { if (levels[ch][sb] > 0) { audio_sample = (uint16_t) ((((frame->sb_sample_f[blk][ch][sb]*levels[ch][sb]) >> (frame->scale_factor[ch][sb] + 1)) + levels[ch][sb]) >> 1); audio_sample <<= 16 - bits[ch][sb]; for (bit = 0; bit < bits[ch][sb]; bit++) { data[produced >> 3] <<= 1; if(audio_sample & 0x8000) data[produced >> 3] |= 0x1; audio_sample <<= 1; produced++; } } } } } /* align the last byte */ if(produced % 8) { data[produced >> 3] <<= 8 - (produced % 8); } return (produced + 7) >> 3;}struct sbc_priv { int init; struct sbc_frame frame; struct sbc_decoder_state dec_state; struct sbc_encoder_state enc_state;};static void sbc_set_defaults(sbc_t *sbc, unsigned long flags){ sbc->rate = 44100; sbc->channels = 2; sbc->joint = 0; sbc->subbands = 8; sbc->blocks = 16; sbc->bitpool = 32; sbc->swap = 0;}int sbc_init(sbc_t *sbc, unsigned long flags){ if (!sbc) return -EIO; memset(sbc, 0, sizeof(sbc_t)); sbc->priv = malloc(sizeof(struct sbc_priv)); if (!sbc->priv) return -ENOMEM; memset(sbc->priv, 0, sizeof(struct sbc_priv)); sbc_set_defaults(sbc, flags); return 0;}int sbc_parse(sbc_t *sbc, void *input, int input_len){ return sbc_decode(sbc, input, input_len, NULL, 0, NULL);}int sbc_decode(sbc_t *sbc, void *input, int input_len, void *output, int output_len, int *written){ struct sbc_priv *priv; char *ptr; int i, ch, framelen, samples; if (!sbc && !input) return -EIO; priv = sbc->priv; framelen = sbc_unpack_frame(input, &priv->frame, input_len); if (!priv->init) { sbc_decoder_init(&priv->dec_state, &priv->frame); priv->init = 1; sbc->rate = priv->frame.sampling_frequency; sbc->channels = priv->frame.channels; sbc->subbands = priv->frame.subbands; sbc->blocks = priv->frame.blocks; sbc->bitpool = priv->frame.bitpool; priv->frame.codesize = sbc_get_codesize(sbc); priv->frame.length = sbc_get_frame_length(sbc); } if (!output) return framelen; if (written) *written = 0; samples = sbc_synthesize_audio(&priv->dec_state, &priv->frame); ptr = output; if (output_len < samples * priv->frame.channels * 2) samples = output_len / (priv->frame.channels * 2); for (i = 0; i < samples; i++) { for (ch = 0; ch < priv->frame.channels; ch++) { int16_t s; s = priv->frame.pcm_sample[ch][i]; if (sbc->swap) { *ptr++ = (s & 0xff00) >> 8; *ptr++ = (s & 0x00ff); } else { *ptr++ = (s & 0x00ff); *ptr++ = (s & 0xff00) >> 8; } } } if (written) *written = samples * priv->frame.channels * 2; return framelen;}int sbc_encode(sbc_t *sbc, void *input, int input_len, void *output, int output_len, int *written){ struct sbc_priv *priv; char *ptr; int i, ch, framelen, samples; if (!sbc && !input) return -EIO; priv = sbc->priv; if (written) *written = 0; if (!priv->init) { priv->frame.sampling_frequency = sbc->rate; priv->frame.channels = sbc->channels; if (sbc->channels > 1) { if (sbc->joint) priv->frame.channel_mode = JOINT_STEREO; else priv->frame.channel_mode = STEREO; } else priv->frame.channel_mode = MONO; priv->frame.allocation_method = sbc->allocation; priv->frame.subbands = sbc->subbands; priv->frame.blocks = sbc->blocks; priv->frame.bitpool = sbc->bitpool; priv->frame.codesize = sbc_get_codesize(sbc); priv->frame.length = sbc_get_frame_length(sbc); sbc_encoder_init(&priv->enc_state, &priv->frame); priv->init = 1; } /* input must be large enough to encode a complete frame */ if (input_len < priv->frame.codesize) return 0; /* output must be large enough to receive the encoded frame */ if (!output || output_len < priv->frame.length) return -ENOSPC; ptr = input; for (i = 0; i < priv->frame.subbands * priv->frame.blocks; i++) { for (ch = 0; ch < sbc->channels; ch++) { int16_t s; if (sbc->swap) s = (ptr[0] & 0xff) << 8 | (ptr[1] & 0xff); else s = (ptr[0] & 0xff) | (ptr[1] & 0xff) << 8; ptr += 2; priv->frame.pcm_sample[ch][i] = s; } } samples = sbc_analyze_audio(&priv->enc_state, &priv->frame); framelen = sbc_pack_frame(output, &priv->frame, output_len); if (written) *written = framelen; return samples * sbc->channels * 2;}void sbc_finish(sbc_t *sbc){ if (!sbc) return; if (sbc->priv) free(sbc->priv); memset(sbc, 0, sizeof(sbc_t));}int sbc_get_frame_length(sbc_t *sbc){ int ret; ret = 4 + (4 * sbc->subbands * sbc->channels) / 8; /* This term is not always evenly divide so we round it up */ if (sbc->channels == 1) ret += ((sbc->blocks * sbc->channels * sbc->bitpool) + 7) / 8; else ret += (((sbc->joint ? sbc->subbands : 0) + sbc->blocks * sbc->bitpool) + 7) / 8; return ret;}int sbc_get_frame_duration(sbc_t *sbc){ return (1000000 * sbc->blocks * sbc->subbands) / sbc->rate;}int sbc_get_codesize(sbc_t *sbc){ return sbc->subbands * sbc->blocks * sbc->channels * 2;}int sbc_reinit(sbc_t *sbc, unsigned long flags){ struct sbc_priv *priv; if (!sbc || !sbc->priv) return -EIO; priv = sbc->priv; if (priv->init == 1) memset(sbc->priv, 0, sizeof(struct sbc_priv)); sbc_set_defaults(sbc, flags); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -