static guint fill_queue (GstScaletempo * scaletempo, GstBuffer * buf_in, guint offset) { GstScaletempoPrivate *p = GST_SCALETEMPO_GET_PRIVATE (scaletempo); guint bytes_in = GST_BUFFER_SIZE (buf_in) - offset; guint offset_unchanged = offset; if (p->bytes_to_slide > 0) { if (p->bytes_to_slide < p->bytes_queued) { guint bytes_in_move = p->bytes_queued - p->bytes_to_slide; memmove (p->buf_queue, p->buf_queue + p->bytes_to_slide, bytes_in_move); p->bytes_to_slide = 0; p->bytes_queued = bytes_in_move; } else { guint bytes_in_skip; p->bytes_to_slide -= p->bytes_queued; bytes_in_skip = MIN (p->bytes_to_slide, bytes_in); p->bytes_queued = 0; p->bytes_to_slide -= bytes_in_skip; offset += bytes_in_skip; bytes_in -= bytes_in_skip; } } if (bytes_in > 0) { guint bytes_in_copy = MIN (p->bytes_queue_max - p->bytes_queued, bytes_in); memcpy (p->buf_queue + p->bytes_queued, GST_BUFFER_DATA (buf_in) + offset, bytes_in_copy); p->bytes_queued += bytes_in_copy; offset += bytes_in_copy; } return offset - offset_unchanged; }
static guint best_overlap_offset_float (GstScaletempo * scaletempo) { GstScaletempoPrivate *p = GST_SCALETEMPO_GET_PRIVATE (scaletempo); gfloat *pw, *po, *ppc, *search_start; gfloat best_corr = G_MININT; guint best_off = 0; gint i, off; pw = p->table_window; po = p->buf_overlap; po += p->samples_per_frame; ppc = p->buf_pre_corr; for (i = p->samples_per_frame; i < p->samples_overlap; i++) { *ppc++ = *pw++ * *po++; } search_start = (gfloat *) p->buf_queue + p->samples_per_frame; for (off = 0; off < p->frames_search; off++) { gfloat corr = 0; gfloat *ps = search_start; ppc = p->buf_pre_corr; for (i = p->samples_per_frame; i < p->samples_overlap; i++) { corr += *ppc++ * *ps++; } if (corr > best_corr) { best_corr = corr; best_off = off; } search_start += p->samples_per_frame; } return best_off * p->bytes_per_frame; }
static void output_overlap_s16 (GstScaletempo * scaletempo, gpointer buf_out, guint bytes_off) { GstScaletempoPrivate *p = GST_SCALETEMPO_GET_PRIVATE (scaletempo); gint16 *pout = buf_out; gint32 *pb = p->table_blend; gint16 *po = p->buf_overlap; gint16 *pin = (gint16 *) (p->buf_queue + bytes_off); gint i; for (i = 0; i < p->samples_overlap; i++) { *pout++ = *po - ((*pb++ * (*po - *pin++)) >> 16); po++; } }
static guint best_overlap_offset_s16 (GstScaletempo * scaletempo) { GstScaletempoPrivate *p = GST_SCALETEMPO_GET_PRIVATE (scaletempo); gint32 *pw, *ppc; gint16 *po, *search_start; gint64 best_corr = G_MININT64; guint best_off = 0; guint off; glong i; pw = p->table_window; po = p->buf_overlap; po += p->samples_per_frame; ppc = p->buf_pre_corr; for (i = p->samples_per_frame; i < p->samples_overlap; i++) { *ppc++ = (*pw++ * *po++) >> 15; } search_start = (gint16 *) p->buf_queue + p->samples_per_frame; for (off = 0; off < p->frames_search; off++) { gint64 corr = 0; gint16 *ps = search_start; ppc = p->buf_pre_corr; ppc += p->samples_overlap - p->samples_per_frame; ps += p->samples_overlap - p->samples_per_frame; i = -((glong) p->samples_overlap - (glong) p->samples_per_frame); do { corr += ppc[i + 0] * ps[i + 0]; corr += ppc[i + 1] * ps[i + 1]; corr += ppc[i + 2] * ps[i + 2]; corr += ppc[i + 3] * ps[i + 3]; i += 4; } while (i < 0); if (corr > best_corr) { best_corr = corr; best_off = off; } search_start += p->samples_per_frame; } return best_off * p->bytes_per_frame; }
static guint fill_queue (GstScaletempo * scaletempo, GstBuffer * buf_in, guint offset) { GstScaletempoPrivate *p = GST_SCALETEMPO_GET_PRIVATE (scaletempo); guint bytes_in = gst_buffer_get_size (buf_in) - offset; guint offset_unchanged = offset; GstMapInfo map; gst_buffer_map (buf_in, &map, GST_MAP_READ); if (p->bytes_to_slide > 0) { if (p->bytes_to_slide < p->bytes_queued) { guint bytes_in_move = p->bytes_queued - p->bytes_to_slide; memmove (p->buf_queue, p->buf_queue + p->bytes_to_slide, bytes_in_move); p->bytes_to_slide = 0; p->bytes_queued = bytes_in_move; } else { guint bytes_in_skip; p->bytes_to_slide -= p->bytes_queued; bytes_in_skip = MIN (p->bytes_to_slide, bytes_in); p->bytes_queued = 0; p->bytes_to_slide -= bytes_in_skip; offset += bytes_in_skip; bytes_in -= bytes_in_skip; } } if (bytes_in > 0) { guint bytes_in_copy = MIN (p->bytes_queue_max - p->bytes_queued, bytes_in); memcpy (p->buf_queue + p->bytes_queued, map.data + offset, bytes_in_copy); p->bytes_queued += bytes_in_copy; offset += bytes_in_copy; } gst_buffer_unmap (buf_in, &map); return offset - offset_unchanged; }
static void reinit_buffers (GstScaletempo * scaletempo) { GstScaletempoPrivate *p = GST_SCALETEMPO_GET_PRIVATE (scaletempo); gint i, j; guint frames_overlap; guint new_size; guint frames_stride = p->ms_stride * p->sample_rate / 1000.0; p->bytes_stride = frames_stride * p->bytes_per_frame; /* overlap */ frames_overlap = frames_stride * p->percent_overlap; if (frames_overlap < 1) { /* if no overlap */ p->bytes_overlap = 0; p->bytes_standing = p->bytes_stride; p->samples_standing = p->bytes_standing / p->bytes_per_sample; p->output_overlap = NULL; } else { guint prev_overlap = p->bytes_overlap; p->bytes_overlap = frames_overlap * p->bytes_per_frame; p->samples_overlap = frames_overlap * p->samples_per_frame; p->bytes_standing = p->bytes_stride - p->bytes_overlap; p->samples_standing = p->bytes_standing / p->bytes_per_sample; p->buf_overlap = g_realloc (p->buf_overlap, p->bytes_overlap); p->table_blend = g_realloc (p->table_blend, p->samples_overlap * 4); /* sizeof (gint32|gfloat) */ if (p->bytes_overlap > prev_overlap) { memset ((guint8 *) p->buf_overlap + prev_overlap, 0, p->bytes_overlap - prev_overlap); } if (p->use_int) { gint32 *pb = p->table_blend; gint64 blend = 0; for (i = 0; i < frames_overlap; i++) { gint32 v = blend / frames_overlap; for (j = 0; j < p->samples_per_frame; j++) { *pb++ = v; } blend += 65535; /* 2^16 */ } p->output_overlap = output_overlap_s16; } else { gfloat *pb = p->table_blend; gfloat t = (gfloat) frames_overlap; for (i = 0; i < frames_overlap; i++) { gfloat v = i / t; for (j = 0; j < p->samples_per_frame; j++) { *pb++ = v; } } p->output_overlap = output_overlap_float; } } /* best overlap */ p->frames_search = (frames_overlap <= 1) ? 0 : p->ms_search * p->sample_rate / 1000.0; if (p->frames_search < 1) { /* if no search */ p->best_overlap_offset = NULL; } else { guint bytes_pre_corr = (p->samples_overlap - p->samples_per_frame) * 4; /* sizeof (gint32|gfloat) */ p->buf_pre_corr = g_realloc (p->buf_pre_corr, bytes_pre_corr + UNROLL_PADDING); p->table_window = g_realloc (p->table_window, bytes_pre_corr); if (p->use_int) { gint64 t = frames_overlap; gint32 n = 8589934588LL / (t * t); /* 4 * (2^31 - 1) / t^2 */ gint32 *pw; memset ((guint8 *) p->buf_pre_corr + bytes_pre_corr, 0, UNROLL_PADDING); pw = p->table_window; for (i = 1; i < frames_overlap; i++) { gint32 v = (i * (t - i) * n) >> 15; for (j = 0; j < p->samples_per_frame; j++) { *pw++ = v; } } p->best_overlap_offset = best_overlap_offset_s16; } else {