#include "simple_pipeline.h" #include "boards/common/board.h" #include "audio_codecs/audio_codec.h" #include #include static inline int16_t lrint16(float v){ if(v>32767.f) return 32767; if(v<-32768.f) return -32768; return (int16_t)v; } static void resample_mono_nearest(const int16_t* in, int in_samples, int in_rate, int16_t* out, int out_samples, int out_rate){ if(in_rate==out_rate){ for(int i=0;i=in_samples) idx=in_samples-1; out[i]=in[idx]; } } recorder_pipeline_handle_t recorder_pipeline_open(){ auto h = (recorder_pipeline_handle_t)pvPortMalloc(sizeof(recorder_pipeline_t)); h->task = nullptr; h->dest_rate = 16000; auto codec = Board::GetInstance().GetAudioCodec(); h->src_rate = codec->input_sample_rate(); h->channels = 1; h->block_bytes = (h->dest_rate/50)*sizeof(int16_t); codec->EnableInput(true); return h; } void recorder_pipeline_run(recorder_pipeline_handle_t){ } void recorder_pipeline_close(recorder_pipeline_handle_t h){ if(!h) return; if (h->task) { vTaskDelete(h->task); } auto codec = Board::GetInstance().GetAudioCodec(); codec->EnableInput(false); vPortFree(h); } int recorder_pipeline_get_default_read_size(recorder_pipeline_handle_t h){ return h? h->block_bytes: 0; } int recorder_pipeline_read(recorder_pipeline_handle_t h, char *buffer, int buf_size){ if(!h || !buffer) return 0; auto codec = Board::GetInstance().GetAudioCodec(); int out_samples = h->dest_rate/50; std::vector tmp; if(h->src_rate==h->dest_rate){ tmp.resize(out_samples); } else{ tmp.resize((int)((float)out_samples*h->src_rate/h->dest_rate)); } if(!codec->InputData(tmp)) return 0; std::vector out(out_samples); resample_mono_nearest(tmp.data(), (int)tmp.size(), h->src_rate, out.data(), out_samples, h->dest_rate); int bytes = out_samples*sizeof(int16_t); if(bytes>buf_size) bytes=buf_size; memcpy(buffer, out.data(), bytes); return bytes; } player_pipeline_handle_t player_pipeline_open(){ auto h = (player_pipeline_handle_t)pvPortMalloc(sizeof(player_pipeline_t)); h->task = nullptr; h->src_rate = 16000; auto codec = Board::GetInstance().GetAudioCodec(); h->dest_rate = codec->output_sample_rate(); h->channels = codec->output_channels(); h->block_bytes = (h->src_rate/50)*sizeof(int16_t); h->fade_total = h->dest_rate / 10; // 100ms淡入 h->fade_done = 0; codec->EnableOutput(true); return h; } void player_pipeline_run(player_pipeline_handle_t){ } void player_pipeline_close(player_pipeline_handle_t h){ if(!h) return; if (h->task) { vTaskDelete(h->task); } auto codec = Board::GetInstance().GetAudioCodec(); codec->EnableOutput(false); vPortFree(h); } int player_pipeline_get_default_read_size(player_pipeline_handle_t h){ return h? h->block_bytes: 0; } int player_pipeline_write(player_pipeline_handle_t h, char *buffer, int buf_size){ if(!h || !buffer || buf_size<=0) return 0; int in_samples = buf_size/sizeof(int16_t); std::vector in(in_samples); memcpy(in.data(), buffer, buf_size); int out_samples = (int)((float)in_samples*h->dest_rate/h->src_rate); std::vector out(out_samples); resample_mono_nearest(in.data(), in_samples, h->src_rate, out.data(), out_samples, h->dest_rate); if (h->fade_done < h->fade_total) { int n = out_samples; for (int i = 0; i < n; ++i) { int done = h->fade_done + i; float g = done < h->fade_total ? (float)done / (float)h->fade_total : 1.0f; out[i] = lrint16((float)out[i] * g); } h->fade_done += n; if (h->fade_done > h->fade_total) h->fade_done = h->fade_total; } auto codec = Board::GetInstance().GetAudioCodec(); if (h->channels == 2) { std::vector stereo(out_samples * 2); for (int i = 0, j = 0; i < out_samples; ++i) { stereo[j++] = out[i]; stereo[j++] = out[i]; } codec->OutputData(stereo); } else { codec->OutputData(out); } return buf_size; } void player_pipeline_write_play_buffer_flag(player_pipeline_handle_t){ } void player_pipeline_set_src_rate(player_pipeline_handle_t h, int rate){ if (!h || rate <= 0) return; h->src_rate = rate; h->block_bytes = (h->src_rate/50)*sizeof(int16_t); }