static unsigned trivial_resample(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) { unsigned i_index, o_index; void *src, *dst; struct trivial_data *trivial_data; pa_assert(r); pa_assert(input); pa_assert(output); pa_assert(out_n_frames); trivial_data = r->impl.data; src = pa_memblock_acquire_chunk(input); dst = pa_memblock_acquire_chunk(output); for (o_index = 0;; o_index++, trivial_data->o_counter++) { i_index = ((uint64_t) trivial_data->o_counter * r->i_ss.rate) / r->o_ss.rate; i_index = i_index > trivial_data->i_counter ? i_index - trivial_data->i_counter : 0; if (i_index >= in_n_frames) break; pa_assert_fp(o_index * r->w_fz < pa_memblock_get_length(output->memblock)); memcpy((uint8_t*) dst + r->w_fz * o_index, (uint8_t*) src + r->w_fz * i_index, (int) r->w_fz); } pa_memblock_release(input->memblock); pa_memblock_release(output->memblock); *out_n_frames = o_index; trivial_data->i_counter += in_n_frames; /* Normalize counters */ while (trivial_data->i_counter >= r->i_ss.rate) { pa_assert(trivial_data->o_counter >= r->o_ss.rate); trivial_data->i_counter -= r->i_ss.rate; trivial_data->o_counter -= r->o_ss.rate; } return 0; }
/*** sink_input callbacks ***/ static int cmtspeech_sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) { struct userdata *u; int queue_counter = 0; pa_assert_fp(i); pa_sink_input_assert_ref(i); pa_assert_se(u = i->userdata); pa_assert_fp(chunk); if (u->cmt_connection.dl_frame_queue) { cmtspeech_dl_buf_t *buf; while ((buf = pa_asyncq_pop(u->cmt_connection.dl_frame_queue, FALSE))) { pa_memchunk cmtchunk; if (cmtspeech_buffer_to_memchunk(u, buf, &cmtchunk) < 0) continue; queue_counter++; if (pa_memblockq_push(u->dl_memblockq, &cmtchunk) < 0) { pa_log_debug("Failed to push DL frame to dl_memblockq (len %zu max %zu)", pa_memblockq_get_length(u->dl_memblockq), pa_memblockq_get_maxlength(u->dl_memblockq)); } else { cmtspeech_dl_sideinfo_push(buf->spc_flags, cmtchunk.length, u); } pa_memblock_unref(cmtchunk.memblock); } } /* More than one DL frame in queue means that sink has not asked for more * data for over 20ms and something may be wrong. */ if (queue_counter > 1) { pa_log_info("%d frames found from queue (dl buf size %zu)", queue_counter, pa_memblockq_get_length(u->dl_memblockq)); } if (pa_memblockq_get_length(u->dl_memblockq) > 3*u->dl_frame_size) { size_t drop_bytes = pa_memblockq_get_length(u->dl_memblockq) - 3*u->dl_frame_size; pa_memblockq_drop(u->dl_memblockq, drop_bytes); cmtspeech_dl_sideinfo_drop(u, drop_bytes); pa_log_debug("Too much data in DL buffer dropped %zu bytes", drop_bytes); } pa_assert_fp((pa_memblockq_get_length(u->dl_memblockq) % u->dl_frame_size) == 0); if (util_memblockq_to_chunk(u->core->mempool, u->dl_memblockq, chunk, u->dl_frame_size)) { ONDEBUG_TOKENS(fprintf(stderr, "d")); cmtspeech_dl_sideinfo_forward(u); } else { if (u->cmt_connection.first_dl_frame_received) pa_log_debug("No DL audio: %zu bytes in queue %zu needed", pa_memblockq_get_length(u->dl_memblockq), u->dl_frame_size); cmtspeech_dl_sideinfo_bogus(u); pa_silence_memchunk_get(&u->core->silence_cache, u->core->mempool, chunk, &u->ss, u->dl_frame_size); } return 0; }