#include "stream_src.h" static void stream_src_irq_cb(void *hdl) { struct __stream_src *stream = hdl; audio_stream_resume(&stream->entry); } static int stream_src_output_handler(void *hdl, void *buf, int len) { struct __stream_src *stream = hdl; if (!stream) { return 0; } #if 0 if (stream->out_buf) { if (stream->out_points < stream->out_total) { return 0; } else { stream->out_buf = NULL; return stream->out_total * 2; } } stream->out_buf = buf; stream->out_points = 0; stream->out_total = len / 2; #endif struct audio_data_frame frame = {0}; frame.channel = stream->channel; frame.sample_rate = stream->target_sr; frame.data_sync = stream->data_sync; frame.data_len = len; frame.data = buf; int tlen = stream->out_points * 2; audio_stream_run(&stream->entry, &frame); return (stream->out_points * 2 - tlen); } static int stream_src_run(struct __stream_src *stream, s16 *data, int len) { if (stream->src_hdl == NULL) { return 0; } return audio_src_resample_write(stream->src_hdl, data, len); } static void stream_src_output_data_process_len(struct audio_stream_entry *entry, int len) { struct __stream_src *stream = container_of(entry, struct __stream_src, entry); if (stream) { stream->out_points += len / 2; } } static void stream_src_check(struct __stream_src *stream, u16 sr, u8 ch_num) { if ((stream->src_always == 0) && (stream->target_sr == sr)) { audio_hw_src_stop(stream->src_hdl); audio_hw_src_close(stream->src_hdl); free(stream->src_hdl); stream->src_hdl = NULL; return ; } if (stream->src_hdl == NULL) { stream->src_hdl = zalloc(sizeof(struct audio_src_handle)); ASSERT(stream->src_hdl); stream->channel = ch_num; audio_hw_src_open(stream->src_hdl, ch_num, SRC_TYPE_RESAMPLE); audio_hw_src_set_rate(stream->src_hdl, sr, stream->target_sr); audio_src_set_output_handler(stream->src_hdl, stream, stream_src_output_handler); audio_src_set_rise_irq_handler(stream->src_hdl, stream, stream_src_irq_cb); } else { audio_hw_src_set_rate(stream->src_hdl, sr, stream->target_sr); } } static int stream_src_data_handler(struct audio_stream_entry *entry, struct audio_data_frame *in, struct audio_data_frame *out) { struct __stream_src *stream = container_of(entry, struct __stream_src, entry); out->sample_rate = stream->target_sr; if (in->data_len) { out->no_subsequent = 1; } #if 0 //输出剩余数据 if (stream->out_buf && (stream->out_points < stream->out_total)) { struct audio_data_frame frame; memset(&frame, 0, sizeof(frame)); frame.channel = in->channel; frame.sample_rate = stream->target_sr; frame.data_sync = in->data_sync; while (1) { frame.data_len = (stream->out_total - stream->out_points) * 2; frame.data = &stream->out_buf[stream->out_points]; int len = stream->out_points; audio_stream_run(entry, &frame); break; } //未输出完退出 if (stream->out_points < stream->out_total) { return 0; } } else { //printf("=========\n"); } #endif stream->data_sync = in->data_sync; //同步检查 stream_src_check(stream, in->sample_rate, in->channel); int len = 0; u8 cnt = 0; len = stream_src_run(stream, in->data, in->data_len); #if 0 if (stream->out_buf && (stream->out_points < stream->out_total)) { struct audio_data_frame frame; memset(&frame, 0, sizeof(frame)); frame.channel = in->channel; frame.sample_rate = stream->target_sr; frame.data_sync = in->data_sync; while (1) { frame.data_len = (stream->out_total - stream->out_points) * 2; frame.data = &stream->out_buf[stream->out_points]; int len = stream->out_points; audio_stream_run(entry, &frame); break; } if (stream->out_points < stream->out_total) { return len; } if (!len) { len = stream_src_run(stream, in->data, in->data_len); } } else { out->data_len = 0; //printf("^^^^^^^^^^/n"); } #endif return len; } void stream_src_set_target_rate(struct __stream_src *hdl, u16 sr) { if (hdl) { hdl->target_sr = sr; } } struct __stream_src *stream_src_open(u16 target_sr, u8 always) { struct __stream_src *stream = zalloc(sizeof(struct __stream_src)); ASSERT(stream); stream->src_always = always; stream->target_sr = target_sr; stream->entry.data_process_len = stream_src_output_data_process_len; stream->entry.data_handler = stream_src_data_handler; return stream; } void stream_src_close(struct __stream_src **hdl) { if (hdl && (*hdl)) { struct __stream_src *stream = *hdl; audio_stream_del_entry(&stream->entry); if (stream->src_hdl) { audio_hw_src_stop(stream->src_hdl); audio_hw_src_close(stream->src_hdl); free(stream->src_hdl); stream->src_hdl = NULL; } local_irq_disable(); free(stream); *hdl = NULL; local_irq_enable(); } } void stream_src_resume(struct __stream_src *hdl) { if (hdl) { audio_stream_resume(&hdl->entry); } }