static int vorbis_floor1_decode(vorbis_context *vc, vorbis_floor_data *vfu, float *vec) { vorbis_floor1 *vf = &vfu->t1; GetBitContext *gb = &vc->gb; uint16_t range_v[4] = { 256, 128, 86, 64 }; unsigned range = range_v[vf->multiplier - 1]; uint16_t floor1_Y[258]; uint16_t floor1_Y_final[258]; int floor1_flag[258]; unsigned class, cdim, cbits, csub, cval, offset, i, j; int book, adx, ady, dy, off, predicted, err; if (!get_bits1(gb)) // silence return 1; // Read values (or differences) for the floor's points floor1_Y[0] = get_bits(gb, ilog(range - 1)); floor1_Y[1] = get_bits(gb, ilog(range - 1)); av_dlog(NULL, "floor 0 Y %d floor 1 Y %d \n", floor1_Y[0], floor1_Y[1]); offset = 2; for (i = 0; i < vf->partitions; ++i) { class = vf->partition_class[i]; cdim = vf->class_dimensions[class]; cbits = vf->class_subclasses[class]; csub = (1 << cbits) - 1; cval = 0; av_dlog(NULL, "Cbits %u\n", cbits); if (cbits) // this reads all subclasses for this partition's class cval = get_vlc2(gb, vc->codebooks[vf->class_masterbook[class]].vlc.table, vc->codebooks[vf->class_masterbook[class]].nb_bits, 3); for (j = 0; j < cdim; ++j) { book = vf->subclass_books[class][cval & csub]; av_dlog(NULL, "book %d Cbits %u cval %u bits:%d\n", book, cbits, cval, get_bits_count(gb)); cval = cval >> cbits; if (book > -1) { floor1_Y[offset+j] = get_vlc2(gb, vc->codebooks[book].vlc.table, vc->codebooks[book].nb_bits, 3); } else { floor1_Y[offset+j] = 0; } av_dlog(NULL, " floor(%d) = %d \n", vf->list[offset+j].x, floor1_Y[offset+j]); } offset+=cdim; } // Amplitude calculation from the differences floor1_flag[0] = 1; floor1_flag[1] = 1; floor1_Y_final[0] = floor1_Y[0]; floor1_Y_final[1] = floor1_Y[1]; for (i = 2; i < vf->x_list_dim; ++i) { unsigned val, highroom, lowroom, room, high_neigh_offs, low_neigh_offs; low_neigh_offs = vf->list[i].low; high_neigh_offs = vf->list[i].high; dy = floor1_Y_final[high_neigh_offs] - floor1_Y_final[low_neigh_offs]; // render_point begin adx = vf->list[high_neigh_offs].x - vf->list[low_neigh_offs].x; ady = FFABS(dy); err = ady * (vf->list[i].x - vf->list[low_neigh_offs].x); off = err / adx; if (dy < 0) { predicted = floor1_Y_final[low_neigh_offs] - off; } else { predicted = floor1_Y_final[low_neigh_offs] + off; } // render_point end val = floor1_Y[i]; highroom = range-predicted; lowroom = predicted; if (highroom < lowroom) { room = highroom * 2; } else { room = lowroom * 2; // SPEC mispelling } if (val) { floor1_flag[low_neigh_offs] = 1; floor1_flag[high_neigh_offs] = 1; floor1_flag[i] = 1; if (val >= room) { if (highroom > lowroom) { floor1_Y_final[i] = val - lowroom + predicted; } else { floor1_Y_final[i] = predicted - val + highroom - 1; } } else { if (val & 1) { floor1_Y_final[i] = predicted - (val + 1) / 2; } else { floor1_Y_final[i] = predicted + val / 2; } } } else { floor1_flag[i] = 0; floor1_Y_final[i] = predicted; } av_dlog(NULL, " Decoded floor(%d) = %u / val %u\n", vf->list[i].x, floor1_Y_final[i], val); } // Curve synth - connect the calculated dots and convert from dB scale FIXME optimize ? ff_vorbis_floor1_render_list(vf->list, vf->x_list_dim, floor1_Y_final, floor1_flag, vf->multiplier, vec, vf->list[1].x); av_dlog(NULL, " Floor decoded\n"); return 0; }