#include "rtthread.h" #include #include "include.h" #include #include "mixer.h" #include "sound_delay.h" #include "audio.h" #if CONFIG_SOUND_MIXER static rt_size_t mixer_sound_read(rt_device_t, rt_off_t, void *, rt_size_t); static void mixer_entry(void *pv); static void mixer_deinit(void); MIXER_T *g_mixer = NULL; #if MIXER_MUX_NEW_STRATEGY uint32_t mixer_outside_src_buf_init(void) { char *ptr; ptr = (char *)rt_malloc(OUTSIDE_SRC_EXCHANGE_BUF_SIZE); if(0 == ptr) { return MIXER_FAILURE; } rt_memset(ptr, 0, OUTSIDE_SRC_EXCHANGE_BUF_SIZE); g_mixer->outside_src_buf = ptr; g_mixer->outside_src_pos = 0; MIXER_PRINTF("[mixer] mixer_outside_src_buf_init\r\n"); return MIXER_SUCCESS; } uint32_t mixer_outside_src_buf_deinit(void) { MIXER_PRINTF("[mixer] mixer_outside_src_buf_deinit\r\n"); if(g_mixer->outside_src_buf) { rt_free(g_mixer->outside_src_buf); g_mixer->outside_src_buf = 0; } return MIXER_SUCCESS; } uint32_t mixer_outside_mp_init(void) { rt_err_t ret; MIXER_PRINTF("[mixer] mixer_outside_mp_init\r\n"); RT_ASSERT(g_mixer->outside_src_buf); ret = rt_mp_init(&(g_mixer->outside_mp.pool), "outside_mp", g_mixer->outside_src_buf, (OUTSIDE_MP_BLOCK_SIZE + 4) * OUTSIDE_MP_BLOCK_COUNT, OUTSIDE_MP_BLOCK_SIZE); RT_ASSERT(RT_EOK == ret); g_mixer->outside_mp.blk_count = OUTSIDE_MP_BLOCK_COUNT; g_mixer->outside_mp.blk_size = OUTSIDE_MP_BLOCK_SIZE; return MIXER_SUCCESS; } uint32_t mixer_outside_mp_recycle_all(void) { uint32_t i; uint32_t ret; void *mp_ptr; uint32_t *mp_addr_array; MIXER_PRINTF("[mixer] mixer_outside_mp_recycle_all\r\n"); RT_ASSERT(g_mixer); ret = MIXER_SUCCESS; mp_addr_array = rt_malloc(sizeof(*mp_addr_array) * OUTSIDE_MP_BLOCK_COUNT); if(NULL == mp_addr_array) { MIXER_WARNING_LOG("mixer_recycle_mp_malloc_failed\r\n"); ret = MIXER_FAILURE; goto recycle_exit; } /* alloc all memory nodes at the mempool*/ for(i = 0; i < OUTSIDE_MP_BLOCK_COUNT; i ++) { mp_ptr = rt_mp_alloc(&g_mixer->outside_mp.pool, RT_WAITING_FOREVER); if(NULL == mp_ptr) { MIXER_WARNING_LOG("mixer_mp_alloc_failed\r\n"); ret = MIXER_FAILURE; } MIXER_PRINTF("[mixer] mp_alloc:0x%x\r\n", mp_ptr); mp_addr_array[i] = (uint32_t)mp_ptr; } /* alloc all memory nodes at the mempool*/ for(i = 0; i < OUTSIDE_MP_BLOCK_COUNT; i ++) { MIXER_PRINTF("[mixer] mp_free:0x%x\r\n", mp_addr_array[i]); rt_mp_free((void *)mp_addr_array[i]); } rt_free(mp_addr_array); mp_addr_array = NULL; MIXER_PRINTF("[mixer] mp_recycling_over\r\n"); recycle_exit: return ret; } uint32_t mixer_outside_mp_deinit(void) { rt_err_t ret; MIXER_PRINTF("[mixer] mixer_outside_mp_deinit\r\n"); ret = rt_mp_detach(&(g_mixer->outside_mp.pool)); RT_ASSERT(RT_EOK == ret); return MIXER_SUCCESS; } #else uint32_t mixer_mp_init(void) { uint32_t ret; RT_ASSERT(g_mixer); MIXER_PRINTF("[mixer] mixer_mp_init\r\n"); ret = MIXER_SUCCESS; g_mixer->mp.blk_size = MP_BLOCK_SIZE; g_mixer->mp.blk_count = MP_BLOCK_COUNT; g_mixer->mp.pool = rt_mp_create("mixer_mp", g_mixer->mp.blk_count, g_mixer->mp.blk_size); if(RT_NULL == g_mixer->mp.pool) { MIXER_WARNING_LOG("mixer_mp_create_failed\r\n"); ret = MIXER_FAILURE; } return ret; } void mixer_mp_deinit(void) { rt_err_t ret; MIXER_PRINTF("[mixer] mixer_mp_deinit\r\n"); ret = rt_mp_delete(g_mixer->mp.pool); RT_ASSERT(RT_EOK == ret); g_mixer->mp.pool = RT_NULL; g_mixer->mp.blk_count = 0; g_mixer->mp.blk_size = 0; } #endif uint32_t mixer_init(void) { rt_err_t ret; MIXER_PRINTF("[mixer] mixer_init\r\n"); sdly_init(); sdly_start_play(); g_mixer = rt_malloc(sizeof(*g_mixer)); if(NULL == g_mixer) { MIXER_WARNING_LOG("mixer_init_failed\r\n"); goto init_exit; } rt_memset(g_mixer, 0, sizeof(*g_mixer)); g_mixer->mx_msg_queue = rt_mq_create(MX_MSG_QUEUE_NAME, sizeof(MIXER_MSG_T), MX_MSG_QUEUE_COUNT, RT_IPC_FLAG_FIFO); if(RT_NULL == g_mixer->mx_msg_queue) { goto init_exit; } g_mixer->mx_mutex = rt_mutex_create(MX_MUTEX_NAME, RT_IPC_FLAG_FIFO);; if(RT_NULL == g_mixer->mx_mutex) { goto init_exit; } g_mixer->wait_end = rt_sem_create("mixer_sema", 0, RT_IPC_FLAG_FIFO); if(RT_NULL == g_mixer->wait_end) { goto init_exit; } #if MIXER_MUX_NEW_STRATEGY if(MIXER_FAILURE == mixer_outside_src_buf_init()) { goto init_exit; } mixer_outside_mp_init(); #else if(MIXER_FAILURE == mixer_mp_init()) { goto init_exit; } #endif INIT_LIST_HEAD(&g_mixer->music_src_list); ret = rt_thread_init(&g_mixer->mx_thread, MX_THREAD_NAME, mixer_entry, NULL, g_mixer->mx_stack, sizeof(g_mixer->mx_stack), MIXER_THREAD_PRIORITY, 10); RT_ASSERT(RT_EOK == ret); g_mixer->is_thd_running = 1; g_mixer->is_thd_pause = 0; g_mixer->audio_sample_rate = MIXER_DEFAULT_SAMPLE_RATE; ret = rt_thread_startup(&g_mixer->mx_thread); RT_ASSERT(RT_EOK == ret); return MIXER_SUCCESS; init_exit: mixer_deinit(); return MIXER_FAILURE; } static uint32_t mixer_send_msg(uint32_t sig, uint32_t detail, uint32_t len) { rt_err_t ret; uint32_t val; MIXER_MSG_T msg; msg.sig = sig; msg.detail = detail; msg.len = len; RT_ASSERT(g_mixer->mx_msg_queue); ret = rt_mq_send(g_mixer->mx_msg_queue, &msg, sizeof(msg)); if(RT_EOK == ret) { MIXER_LOG("mixer_send_msg:0x%x\r\n", detail); val = MIXER_SUCCESS; } else { MIXER_PRINTF("[mixer] mixer_send_msg_failed:0x%x\r\n", detail); val = MIXER_FAILURE; } return val; } uint32_t mixer_send_data_msg(void *node_ptr, uint32_t len) { uint32_t ret; ret = mixer_send_msg(DATA_SIGNATURE, (uint32_t)node_ptr, len); if(ret == MIXER_FAILURE) { RT_ASSERT(ret != MIXER_FAILURE); rt_mp_free(node_ptr); } return MIXER_SUCCESS; } uint32_t mixer_send_msg_audio_src_flow(void) { uint32_t ret; MIXER_PRINTF("[mixer] audio_src_flow\r\n"); ret = mixer_send_msg(MSG_SIGNATURE, MSG_TYPE_AUDIO_SRC_FLOW, 8); RT_ASSERT(ret == MIXER_SUCCESS); ret = rt_sem_take(g_mixer->wait_end, 5000); if(ret == -RT_ETIMEOUT) { MIXER_WARNING_LOG("[mixer] wait_end timeout\r\n"); } /* maybe wait_end may release many times*/ while(rt_sem_trytake(g_mixer->wait_end) != -RT_ETIMEOUT ); MIXER_PRINTF("[mixer] audio_src_flow ed\r\n"); return 0; } uint32_t mixer_send_msg_audio_src_static(void) { uint32_t ret; MIXER_PRINTF("[mixer] audio_src_static\r\n"); ret = mixer_send_msg(MSG_SIGNATURE, MSG_TYPE_AUDIO_SRC_STATIC, 8); RT_ASSERT(ret == MIXER_SUCCESS); ret = rt_sem_take(g_mixer->wait_end, 5000); if(ret == -RT_ETIMEOUT) { MIXER_WARNING_LOG("[mixer] wait_end timeout\r\n"); } /* maybe wait_end may release many times*/ while(rt_sem_trytake(g_mixer->wait_end) != -RT_ETIMEOUT ); MIXER_PRINTF("[mixer] audio_src_static ed\r\n"); return 0; } void mixer_run(void) { rt_mutex_take(g_mixer->mx_mutex, RT_WAITING_FOREVER); g_mixer->is_thd_running = 1; rt_mutex_release(g_mixer->mx_mutex); } void mixer_stop(void) { rt_mutex_take(g_mixer->mx_mutex, RT_WAITING_FOREVER); g_mixer->is_thd_running = 0; rt_mutex_release(g_mixer->mx_mutex); } uint32_t mixer_is_running(void) { uint32_t ret; rt_mutex_take(g_mixer->mx_mutex, RT_WAITING_FOREVER); ret = g_mixer->is_thd_running; rt_mutex_release(g_mixer->mx_mutex); return ret; } void mixer_pause(void) { int ret; MIXER_PRINTF("[mixer] mixer_pause\r\n"); if(g_mixer->is_thd_pause == MIX_ACT_PAUSE) return; ret = mixer_send_msg(MSG_SIGNATURE, MSG_TYPE_PAUSE_MIXER, 8); RT_ASSERT(ret == MIXER_SUCCESS) ret = rt_sem_take(g_mixer->wait_end, 5000); if(ret == -RT_ETIMEOUT) { MIXER_WARNING_LOG("[mixer] wait_end timeout\r\n"); } /* maybe wait_end may release many times*/ while(rt_sem_trytake(g_mixer->wait_end) != -RT_ETIMEOUT ); MIXER_PRINTF("[mixer] mixer_pause d \r\n"); } void mixer_replay(void) { int ret; MIXER_PRINTF("[mixer] mixer_replay\r\n"); if(g_mixer->is_thd_pause == MIX_ACT_PLAYING) return; ret = mixer_send_msg(MSG_SIGNATURE, MSG_TYPE_REPLAY_MIXER, 8); RT_ASSERT(ret == MIXER_SUCCESS) ret = rt_sem_take(g_mixer->wait_end, 5000); if(ret == -RT_ETIMEOUT) { MIXER_WARNING_LOG("[mixer] wait_end timeout\r\n"); } /* maybe wait_end may release many times*/ while(rt_sem_trytake(g_mixer->wait_end) != -RT_ETIMEOUT ); MIXER_PRINTF("[mixer] mixer_replayed \r\n"); } static uint32_t mixer_adc_open(void) { uint32_t ret; rt_err_t val; rt_device_t dev; uint32_t sample_rate; uint32_t channel_cnt; ADC_DEV_T *adc = &(g_mixer->adc_dev); RT_ASSERT(g_mixer); MIXER_PRINTF("[mixer] mixer_adc_open, %p\r\n", adc->dev); if(adc->dev == NULL) { dev = rt_device_find("mic"); if(NULL == dev) { ret = MIXER_FAILURE; goto adco_exit; } } else { dev = adc->dev; } if(dev->open_flag & RT_DEVICE_OFLAG_OPEN) { MIXER_PRINTF("[mixer] mixer adc aready open\r\n"); return MIXER_SUCCESS; } ret = MIXER_SUCCESS; val = rt_device_open(dev, RT_DEVICE_OFLAG_RDONLY); RT_ASSERT(RT_EOK == val); adc->dev = dev; MIXER_PRINTF("[mixer] mixer_adc_opened\r\n"); adco_exit: return ret; } static uint32_t mixer_adc_set_rate(uint32_t rate) { rt_err_t val; rt_device_t dev; uint32_t sample_rate; ADC_DEV_T *adc = &(g_mixer->adc_dev); RT_ASSERT(g_mixer); RT_ASSERT(adc->dev); MIXER_PRINTF("[mixer] mixer_adc_set_rate, %d\r\n", rate); dev = adc->dev; sample_rate = rate; val = rt_device_control(dev, CODEC_CMD_SAMPLERATE, (void *)&sample_rate); RT_ASSERT(RT_EOK == val); adc->rate = rate; sdly_config(sample_rate); sdly_init_forepart_mute(); sdly_start_play(); return MIXER_SUCCESS; } static uint32_t mixer_adc_close(void) { ADC_DEV_T *adc = &(g_mixer->adc_dev); rt_err_t val; RT_ASSERT(g_mixer); RT_ASSERT(adc->dev); MIXER_PRINTF("[mixer] mixer_adc_close\r\n"); if (!(adc->dev->open_flag & RT_DEVICE_OFLAG_OPEN)) { return MIXER_SUCCESS; } val = rt_device_close(adc->dev); RT_ASSERT(RT_EOK == val); return MIXER_SUCCESS; } static rt_err_t mixer_dac_write_done(struct rt_device *device, void *ptr) { if (!ptr) { MIXER_PRINTF("[mixer] device buf_release NULL\n"); return -RT_ERROR; } rt_mp_free(ptr); return RT_EOK; } static uint32_t mixer_dac_open(void) { uint32_t ret; rt_err_t val; rt_device_t dev; uint32_t sample_rate; DAC_DEV_T *dac = &(g_mixer->dac_dev); RT_ASSERT(g_mixer); MIXER_PRINTF("[mixer] mixer_dac_open\r\n"); if(dac->dev == NULL) { dev = rt_device_find("sound"); if(NULL == dev) { ret = MIXER_FAILURE; goto daco_exit; } } else { dev = dac->dev; } if(dev->open_flag & RT_DEVICE_OFLAG_OPEN) { MIXER_PRINTF("[mixer] mixer dac aready open\r\n"); return MIXER_SUCCESS; } ret = MIXER_SUCCESS; rt_device_set_tx_complete(dev, mixer_dac_write_done); val = rt_device_open(dev, RT_DEVICE_OFLAG_WRONLY); RT_ASSERT(RT_EOK == val); dac->dev = dev; MIXER_PRINTF("[mixer] mixer_dac_opened\r\n"); daco_exit: return ret; } static uint32_t mixer_dac_set_rate(uint32_t rate) { rt_err_t val; rt_device_t dev; uint32_t sample_rate; DAC_DEV_T *dac = &(g_mixer->dac_dev); RT_ASSERT(g_mixer); RT_ASSERT(dac->dev); MIXER_PRINTF("[mixer] mixer_dac_set_rate, %d\r\n", rate); dev = dac->dev; sample_rate = rate; val = rt_device_control(dev, CODEC_CMD_SAMPLERATE, (void *)&sample_rate); RT_ASSERT(RT_EOK == val); dac->rate = rate; return MIXER_SUCCESS; } static uint32_t mixer_dac_close(void) { DAC_DEV_T *dac = &(g_mixer->dac_dev); rt_err_t val; RT_ASSERT(g_mixer); RT_ASSERT(dac->dev); MIXER_PRINTF("[mixer] mixer_dac_close\r\n"); if (!(dac->dev->open_flag & RT_DEVICE_OFLAG_OPEN)) { return MIXER_SUCCESS; } val = rt_device_close(dac->dev); RT_ASSERT(RT_EOK == val); return MIXER_SUCCESS; } static uint32_t mixer_music_src_in(uint8_t *buf, uint32_t len) { uint32_t ret; MUSIC_SRC_NODE_T *node; ret = MIXER_SUCCESS; if((0 == len) || (!g_mixer->is_mux_src)) { goto in_exit; } MIXER_LOG("mixer_msrc_in:%d\r\n", len); node = (MUSIC_SRC_NODE_T *)rt_malloc(sizeof(*node)); if(NULL == node) { ret = MIXER_FAILURE; goto in_exit; } node->buf = buf; node->len = len; node->use_pos = 0; rt_mutex_take(g_mixer->mx_mutex, RT_WAITING_FOREVER); list_add_tail(&node->hdr, &g_mixer->music_src_list); rt_mutex_release(g_mixer->mx_mutex); return MIXER_SUCCESS; in_exit: rt_mp_free(buf); return ret; } #if MIXER_MUX_NEW_STRATEGY uint32_t mixer_music_src_peek_current_node_len(void) { LIST_HEADER_T *tmp; LIST_HEADER_T *pos; uint32_t length = 0; MUSIC_SRC_NODE_T *mnode = NULL; rt_mutex_take(g_mixer->mx_mutex, RT_WAITING_FOREVER); list_for_each_safe(pos, tmp, &g_mixer->music_src_list) { mnode = list_entry(pos, MUSIC_SRC_NODE_T, hdr); length = mnode->len; break; } rt_mutex_release(g_mixer->mx_mutex); return length; } void *mixer_music_src_peek_current_node_buf(void) { LIST_HEADER_T *tmp; LIST_HEADER_T *pos; void *node_buf_ptr = NULL; MUSIC_SRC_NODE_T *mnode = NULL; rt_mutex_take(g_mixer->mx_mutex, RT_WAITING_FOREVER); list_for_each_safe(pos, tmp, &g_mixer->music_src_list) { mnode = list_entry(pos, MUSIC_SRC_NODE_T, hdr); node_buf_ptr = (void *)mnode->buf; break; } rt_mutex_release(g_mixer->mx_mutex); return node_buf_ptr; } uint32_t mixer_music_src_out2(void) { LIST_HEADER_T *tmp; LIST_HEADER_T *pos; MUSIC_SRC_NODE_T *mnode = NULL; MIXER_LOG("mixer_music_src_out2\r\n"); rt_mutex_take(g_mixer->mx_mutex, RT_WAITING_FOREVER); list_for_each_safe(pos, tmp, &g_mixer->music_src_list) { mnode = list_entry(pos, MUSIC_SRC_NODE_T, hdr); list_del(&mnode->hdr); break; } rt_mutex_release(g_mixer->mx_mutex); RT_ASSERT(mnode); rt_free(mnode); return MIXER_SUCCESS; } uint32_t mixer_music_src_flush2(void) { LIST_HEADER_T *tmp; LIST_HEADER_T *pos; MUSIC_SRC_NODE_T *node = NULL; rt_mutex_take(g_mixer->mx_mutex, RT_WAITING_FOREVER); list_for_each_safe(pos, tmp, &g_mixer->music_src_list) { node = list_entry(pos, MUSIC_SRC_NODE_T, hdr); MIXER_PRINTF("[mixer] mixer_music_src_flush2:0x%x\r\n", node); list_del(&node->hdr); rt_mp_free(node->buf); rt_free(node); } rt_mutex_release(g_mixer->mx_mutex); return MIXER_SUCCESS; } #else uint32_t mixer_music_src_out(MUSIC_SRC_NODE_T *node) { void *ptr; MIXER_LOG("mixer_music_src_out\r\n"); rt_mutex_take(g_mixer->mx_mutex, RT_WAITING_FOREVER); ptr = (void *)node->buf; list_del(&node->hdr); rt_mutex_release(g_mixer->mx_mutex); rt_mp_free(ptr); rt_free(node); return MIXER_SUCCESS; } uint32_t mixer_music_src_flush(void) { LIST_HEADER_T *tmp; LIST_HEADER_T *pos; MUSIC_SRC_NODE_T *node = NULL; MIXER_PRINTF("[mixer] mixer_music_src_flush\r\n"); rt_mutex_take(g_mixer->mx_mutex, RT_WAITING_FOREVER); list_for_each_safe(pos, tmp, &g_mixer->music_src_list) { node = list_entry(pos, MUSIC_SRC_NODE_T, hdr); mixer_music_src_out(node); } rt_mutex_release(g_mixer->mx_mutex); return MIXER_SUCCESS; } uint32_t mixer_music_src_get_data(uint8_t *buf, uint32_t expected_len) { uint32_t count; uint8_t *data_ptr; uint32_t expected_cnt; uint32_t length = 0; LIST_HEADER_T *tmp; LIST_HEADER_T *pos; MUSIC_SRC_NODE_T *node = NULL; data_ptr = buf; expected_cnt = expected_len; if(!(expected_cnt && data_ptr)) { goto get_exit; } rt_mutex_take(g_mixer->mx_mutex, RT_WAITING_FOREVER); list_for_each_safe(pos, tmp, &g_mixer->music_src_list) { node = list_entry(pos, MUSIC_SRC_NODE_T, hdr); RT_ASSERT(node->len >= node->use_pos); count = node->len - node->use_pos; if(count >= expected_cnt) { rt_memcpy(data_ptr, &node->buf[node->use_pos], expected_cnt); node->use_pos += expected_cnt; length += expected_cnt; if(node->len == node->use_pos) { mixer_music_src_out(node); } break; } else { rt_memcpy(data_ptr, &node->buf[node->use_pos], count); node->use_pos = node->len; data_ptr = &data_ptr[count]; length += count; expected_cnt -= count; } if(node->len == node->use_pos) { mixer_music_src_out(node); } } rt_mutex_release(g_mixer->mx_mutex); get_exit: return length; } #endif static uint32_t mixer_music_src_get_data_len(void) { uint32_t length = 0; LIST_HEADER_T *tmp; LIST_HEADER_T *pos; MUSIC_SRC_NODE_T *node = NULL; rt_mutex_take(g_mixer->mx_mutex, RT_WAITING_FOREVER); list_for_each_safe(pos, tmp, &g_mixer->music_src_list) { node = list_entry(pos, MUSIC_SRC_NODE_T, hdr); RT_ASSERT(node->len >= node->use_pos); length += node->len - node->use_pos; } rt_mutex_release(g_mixer->mx_mutex); return length; } static MUSIC_SRC_NODE_T *mixer_music_src_peek(void) { LIST_HEADER_T *tmp; LIST_HEADER_T *pos; MUSIC_SRC_NODE_T *ret = NULL; rt_mutex_take(g_mixer->mx_mutex, RT_WAITING_FOREVER); list_for_each_safe(pos, tmp, &g_mixer->music_src_list) { ret = list_entry(pos, MUSIC_SRC_NODE_T, hdr); break; } rt_mutex_release(g_mixer->mx_mutex); return ret; } static uint32_t _mixer_single_channel_data_double_padding(void *start, void *buf, uint32_t len) { uint32_t i; uint16_t *dst, *src; dst = start; src = buf; RT_ASSERT(0 == ((uint32_t)dst & 0x01)); RT_ASSERT(0 == ((uint32_t)src & 0x01)); for(i = 0; i < (len >> 1); i++) { dst[2 * i] = src[i]; dst[2 * i + 1] = src[i]; } return len * 2; } #if MIXER_MUX_NEW_STRATEGY uint32_t mixer_mux2_acoustics(void) { uint32_t ret; uint32_t expected_len; uint32_t inside_data_len; rt_uint8_t *inside_src_buf; rt_uint8_t *outside_src_buf; rt_size_t read_bytes, wr_bytes; rt_device_t adc_device; rt_device_t dac_device; MIXER_LOG("mixer_mux2_acoustics\r\n"); RT_ASSERT(g_mixer->adc_dev.dev); RT_ASSERT(g_mixer->dac_dev.dev); adc_device = g_mixer->adc_dev.dev; dac_device = g_mixer->dac_dev.dev; outside_src_buf = g_mixer->outside_src_buf; RT_ASSERT(outside_src_buf); #if CFG_SUPPORT_SINGLE_CHANNEL /*step 1: get music data of current node(inside audio source)*/ expected_len = mixer_music_src_peek_current_node_len(); MIXER_LOG("expected_len:%d\r\n", expected_len); if(0 == expected_len) { goto mux_exit; } RT_ASSERT(1 != (expected_len & 0x01)); RT_ASSERT(expected_len >= 2); if(expected_len != g_mixer->outside_src_pos) { char *outside_buf_ptr = &outside_src_buf[g_mixer->outside_src_pos]; char *outside_rd_ptr = &outside_src_buf[(g_mixer->outside_src_pos + expected_len) >> 1];; uint32_t outside_rd_len = (expected_len - g_mixer->outside_src_pos) >> 1; read_bytes = mixer_sound_read(adc_device, 0, outside_rd_ptr, outside_rd_len); read_bytes = _mixer_single_channel_data_double_padding(outside_buf_ptr, outside_rd_ptr, read_bytes); g_mixer->outside_src_pos += read_bytes; } if(expected_len != g_mixer->outside_src_pos) { /* maybe the thread need suspend a little time here*/ goto mux_exit; } /*step 2: get music data(inside audio source)*/ inside_src_buf = mixer_music_src_peek_current_node_buf(); inside_data_len = expected_len; MIXER_LOG("inside_src:%x:%d\r\n", inside_src_buf, inside_data_len); RT_ASSERT(inside_src_buf); /*step 3: mixer*/ sdly_mixer_multi_playing(outside_src_buf, inside_src_buf, inside_data_len); #else #error "it is not the single channel of mic!!!" #endif sdly_forepart_mute(inside_src_buf, inside_data_len); g_mixer->outside_src_pos = 0; mixer_music_src_out2(); wr_bytes = rt_device_write(dac_device, 0, inside_src_buf, inside_data_len); if(wr_bytes != inside_data_len) { MIXER_PRINTF("[mixer] WR_MISMATCH:%d:%d\r\n", inside_data_len, wr_bytes); } return MIXER_SUCCESS; mux_exit: MIXER_LOG("mux_exit\r\n"); return ret; } uint32_t mixer_single2_acoustics(void) { rt_uint8_t *exchange_buf; rt_size_t read_bytes, wr_bytes; rt_device_t adc_device; rt_device_t dac_device; RT_ASSERT(g_mixer->adc_dev.dev); RT_ASSERT(g_mixer->dac_dev.dev); adc_device = g_mixer->adc_dev.dev; dac_device = g_mixer->dac_dev.dev; MIXER_LOG("mixer_single2_acoustics:0x%x:0x%x\r\n", adc_device, dac_device); exchange_buf = rt_mp_alloc(&g_mixer->outside_mp.pool, RT_WAITING_NO); if(!exchange_buf) { MIXER_WARNING_LOG("."); MIXER_LOG("mixer_mp_alloc_failed\r\n"); return MIXER_FAILURE; } #if CFG_SUPPORT_SINGLE_CHANNEL read_bytes = mixer_sound_read(adc_device, 0, &exchange_buf[(g_mixer->outside_mp.blk_size >> 1)], (g_mixer->outside_mp.blk_size >> 1)); MIXER_LOG("single_rd:0x%x:%d\r\n", exchange_buf, read_bytes); if(0 == read_bytes) { rt_mp_free(exchange_buf); return MIXER_SUCCESS; } read_bytes = _mixer_single_channel_data_double_padding(exchange_buf, &exchange_buf[(g_mixer->outside_mp.blk_size >> 1)], read_bytes); sdly_mixer_single_playing(exchange_buf, read_bytes); #else #error "it is not the single channel of mic!!!" #endif sdly_forepart_mute(exchange_buf, read_bytes); wr_bytes = rt_device_write(dac_device, 0, exchange_buf, read_bytes); if(wr_bytes != read_bytes) { MIXER_WARNING_LOG("wr_mismatch:%d:%d\r\n", read_bytes, wr_bytes); } return MIXER_SUCCESS; } #else uint32_t mixer_mux_acoustics(void) { uint32_t ret; uint32_t expected_len; uint32_t inside_data_len; rt_uint8_t *inside_src_buf; rt_uint8_t *outside_src_buf; rt_size_t read_bytes, wr_bytes; rt_device_t adc_device; rt_device_t dac_device; MIXER_LOG("mixer_mux_acoustics\r\n"); RT_ASSERT(g_mixer->adc_dev.dev); RT_ASSERT(g_mixer->dac_dev.dev); adc_device = g_mixer->adc_dev.dev; dac_device = g_mixer->dac_dev.dev; outside_src_buf = rt_mp_alloc(g_mixer->mp.pool, RT_WAITING_NO); inside_src_buf = rt_mp_alloc(g_mixer->mp.pool, RT_WAITING_NO); if((!outside_src_buf) || (!inside_src_buf)) { ret = MIXER_FAILURE; goto mux_exit; } #if CFG_SUPPORT_SINGLE_CHANNEL /*step 1: get mic data(outside audio source)*/ expected_len = MIN(mixer_music_src_get_data_len(), g_mixer->mp.blk_size); MIXER_LOG("expected_len:%d:%d:%d\r\n", expected_len, mixer_music_src_get_data_len(), g_mixer->mp.blk_size); if(0 == expected_len) { goto mux_exit; } RT_ASSERT(1 != (expected_len & 0x01)); RT_ASSERT(expected_len >= 2); read_bytes = mixer_sound_read(adc_device, 0, &outside_src_buf[(g_mixer->mp.blk_size >> 1)], (expected_len >> 1)); read_bytes = _mixer_single_channel_data_double_padding(outside_src_buf, &outside_src_buf[(g_mixer->mp.blk_size >> 1)], read_bytes); /*clear adc data for noise*/ sdly_forepart_mute(outside_src_buf, read_bytes); /*step 2: get music data(inside audio source)*/ inside_data_len = mixer_music_src_get_data(inside_src_buf, read_bytes); MIXER_LOG("read_bytes:%d:%d\r\n", inside_data_len, read_bytes); RT_ASSERT(inside_data_len == read_bytes); /*step 3: mixer*/ sdly_mixer_multi_playing(outside_src_buf, inside_src_buf, inside_data_len); #else #error "it is not the single channel of mic!!!" #endif rt_mp_free(outside_src_buf); wr_bytes = rt_device_write(dac_device, 0, inside_src_buf, inside_data_len); if(wr_bytes != inside_data_len) { MIXER_PRINTF("[mixer] WR_MISMATCH:%d:%d\r\n", inside_data_len, wr_bytes); rt_mp_free(inside_src_buf); } return MIXER_SUCCESS; mux_exit: if(outside_src_buf) { rt_mp_free(outside_src_buf); } if(inside_src_buf) { rt_mp_free(inside_src_buf); } return ret; } uint32_t mixer_single_acoustics(void) { rt_uint8_t *exchange_buf; rt_size_t read_bytes, wr_bytes; rt_device_t adc_device; rt_device_t dac_device; RT_ASSERT(g_mixer->adc_dev.dev); RT_ASSERT(g_mixer->dac_dev.dev); adc_device = g_mixer->adc_dev.dev; dac_device = g_mixer->dac_dev.dev; MIXER_LOG("mixer_single_acoustics:0x%x:0x%x\r\n", adc_device, dac_device); exchange_buf = rt_mp_alloc(g_mixer->mp.pool, RT_WAITING_NO); if(!exchange_buf) { //MIXER_WARNING_LOG("."); MIXER_LOG("mixer_mp_alloc_failed\r\n"); return MIXER_FAILURE; } #if CFG_SUPPORT_SINGLE_CHANNEL read_bytes = mixer_sound_read(adc_device, 0, &exchange_buf[(g_mixer->mp.blk_size >> 1)], (g_mixer->mp.blk_size >> 1)); MIXER_LOG("single_rd:0x%x:%d\r\n", exchange_buf, read_bytes); if(0 == read_bytes) { rt_mp_free(exchange_buf); return MIXER_SUCCESS; } read_bytes = _mixer_single_channel_data_double_padding(exchange_buf, &exchange_buf[(g_mixer->mp.blk_size >> 1)], read_bytes); /*clear adc data for noise*/ sdly_forepart_mute(exchange_buf, read_bytes); sdly_mixer_single_playing(exchange_buf, read_bytes); #else #error "it is not the single channel of mic!!!" #endif wr_bytes = rt_device_write(dac_device, 0, exchange_buf, read_bytes); if(wr_bytes != read_bytes) { MIXER_WARNING_LOG("wr_mismatch:%d:%d\r\n", read_bytes, wr_bytes); rt_mp_free(exchange_buf); } return MIXER_SUCCESS; } #endif static uint32_t mixer_device_open(void) { MIXER_PRINTF("[mixer] mixer_device_open\r\n"); audio_adc_enable_linein(); mixer_adc_open(); mixer_adc_set_rate(MIXER_DEFAULT_SAMPLE_RATE); mixer_dac_open(); mixer_dac_set_rate(MIXER_DEFAULT_SAMPLE_RATE); g_mixer->is_mux_src = 0; g_mixer->audio_sample_rate = MIXER_DEFAULT_SAMPLE_RATE; return MIXER_SUCCESS; } static uint32_t mixer_device_close(void) { MIXER_PRINTF("[mixer] mixer_device_close\r\n"); mixer_adc_close(); mixer_dac_close(); audio_adc_disable_linein(); g_mixer->is_mux_src = 0; return MIXER_SUCCESS; } uint32_t mixer_device_set_rate(uint32_t sample_rate) { int ret; MIXER_PRINTF("[mixer] set_rate:%d-%d\r\n", sample_rate, g_mixer->audio_sample_rate); if(g_mixer->audio_sample_rate == sample_rate) return 0; ret = mixer_send_msg(MSG_SIGNATURE, MSG_TYPE_AUDIO_SET_SAMPLE_RATE, sample_rate); RT_ASSERT(ret == MIXER_SUCCESS) ret = rt_sem_take(g_mixer->wait_end, 5000); if(ret == -RT_ETIMEOUT) { MIXER_WARNING_LOG("[mixer] wait_end timeout\r\n"); } /* maybe wait_end may release many times*/ while(rt_sem_trytake(g_mixer->wait_end) != -RT_ETIMEOUT ); MIXER_PRINTF("[mixer] set_rate ed\r\n", sample_rate); return 0; } uint32_t mixer_device_get_rate(void) { return g_mixer->audio_sample_rate; } static void mixer_entry(void *pv) { rt_err_t ret; MIXER_MSG_T msg; uint32_t is_mux_src; RT_ASSERT(g_mixer); RT_ASSERT(g_mixer->mx_msg_queue); /*default setting: no music, only linein(outside mic device)*/ mixer_device_open(); while(g_mixer->is_thd_running) { msg.sig = 0; ret = rt_mq_recv(g_mixer->mx_msg_queue, &msg, sizeof(msg), MX_MSG_QUEUE_TIMEOUT); switch(msg.detail) { case MSG_TYPE_AUDIO_SRC_FLOW: if(MSG_SIGNATURE == msg.sig) { MIXER_PRINTF("[mixer] AUDIO_SRC_FLOW:%d\r\n", g_mixer->is_thd_pause); if(g_mixer->is_thd_pause == MIX_ACT_PLAYING) { g_mixer->is_mux_src = 1; } else { mixer_dac_open(); } ret = rt_sem_release(g_mixer->wait_end); RT_ASSERT(ret == RT_EOK); } break; case MSG_TYPE_AUDIO_SRC_STATIC: if(MSG_SIGNATURE == msg.sig) { MIXER_PRINTF("[mixer] AUDIO_SRC_STATIC:%d\r\n", g_mixer->is_thd_pause); if(g_mixer->is_thd_pause == MIX_ACT_PLAYING) { g_mixer->is_mux_src = 0; #if !MIXER_MUX_NEW_STRATEGY mixer_music_src_flush(); #endif } else { mixer_dac_close(); } ret = rt_sem_release(g_mixer->wait_end); RT_ASSERT(ret == RT_EOK); } break; case MSG_TYPE_AUDIO_SET_SAMPLE_RATE: if(MSG_SIGNATURE == msg.sig) { MIXER_PRINTF("[mixer] MSG_TYPE_AUDIO_SET_SAMPLE_RATE:%d - %d\r\n", msg.len, g_mixer->audio_sample_rate); if(g_mixer->is_thd_pause == MIX_ACT_PLAYING) { if(g_mixer->audio_sample_rate != msg.len) { g_mixer->audio_sample_rate = msg.len; mixer_adc_set_rate(g_mixer->audio_sample_rate); //rt_thread_delay(1000); mixer_dac_set_rate(g_mixer->audio_sample_rate); } } else { mixer_dac_set_rate(msg.len); } ret = rt_sem_release(g_mixer->wait_end); RT_ASSERT(ret == RT_EOK); } break; case MSG_TYPE_PAUSE_MIXER: if(MSG_SIGNATURE == msg.sig) { MIXER_PRINTF("[mixer] MSG_TYPE_PAUSE_MIXER\r\n"); g_mixer->is_thd_pause = MIX_ACT_PAUSE; mixer_adc_close(); if(g_mixer->is_mux_src == 0) mixer_dac_close(); audio_adc_disable_linein(); #if !MIXER_MUX_NEW_STRATEGY mixer_music_src_flush(); #endif ret = rt_sem_release(g_mixer->wait_end); RT_ASSERT(ret == RT_EOK); } break; case MSG_TYPE_REPLAY_MIXER: if(MSG_SIGNATURE == msg.sig) { MIXER_PRINTF("[mixer] MSG_TYPE_REPLAY_MIXER:%d,%d\r\n", g_mixer->audio_sample_rate, g_mixer->is_mux_src); audio_adc_enable_linein(); mixer_adc_open(); mixer_adc_set_rate(g_mixer->audio_sample_rate); mixer_dac_open(); mixer_dac_set_rate(g_mixer->audio_sample_rate); g_mixer->is_thd_pause = MIX_ACT_PLAYING; ret = rt_sem_release(g_mixer->wait_end); RT_ASSERT(ret == RT_EOK); } break; default: if(DATA_SIGNATURE == msg.sig) { uint8_t *buf = (uint8_t *)msg.detail; uint32 len = msg.len; MIXER_LOG("DATA_SIGNATURE\r\n"); mixer_music_src_in(buf, len); } break; } if(g_mixer->is_thd_pause == MIX_ACT_PAUSE) continue; if(g_mixer->is_mux_src) { #if MIXER_MUX_NEW_STRATEGY mixer_mux2_acoustics(); #else mixer_mux_acoustics(); #endif } else { #if MIXER_MUX_NEW_STRATEGY mixer_single2_acoustics(); #else mixer_single_acoustics(); #endif } } mixer_device_close(); mixer_deinit(); } static void mixer_deinit(void) { rt_err_t ret; MIXER_PRINTF("[mixer] mixer_deinit\r\n"); if(NULL == g_mixer) { return; } if(g_mixer->mx_msg_queue) { rt_mq_detach(g_mixer->mx_msg_queue); ret = rt_mq_delete(g_mixer->mx_msg_queue); RT_ASSERT(RT_EOK == ret); g_mixer->mx_msg_queue = NULL; } if(g_mixer->mx_mutex) { rt_mutex_detach(g_mixer->mx_mutex); ret = rt_mutex_delete(g_mixer->mx_mutex); RT_ASSERT(RT_EOK == ret); g_mixer->mx_mutex = NULL; } if(g_mixer->wait_end) { rt_sem_detach(g_mixer->wait_end); ret = rt_sem_delete(g_mixer->wait_end); RT_ASSERT(RT_EOK == ret); g_mixer->wait_end = NULL; } #if MIXER_MUX_NEW_STRATEGY mixer_outside_mp_deinit(); mixer_outside_src_buf_deinit(); #else mixer_mp_deinit(); #endif rt_free(g_mixer); g_mixer = NULL; sdly_deinit(); } static rt_size_t mixer_sound_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) { rt_size_t read_bytes = 0; while (read_bytes < size) { rt_size_t rb = rt_device_read(dev, pos, (void *)((char *)buffer + read_bytes), size - read_bytes); if (rb == 0) break; read_bytes += rb; } return read_bytes; } uint32_t mixer_device_write(void *buffer, int size) { if(g_mixer->is_thd_pause == MIX_ACT_PAUSE) return 1; mixer_send_data_msg(buffer, size); return 0; } #endif // CONFIG_SOUND_MIXER // eof