2025-04-08 18:46:12 +08:00

1440 lines
35 KiB
C

#include "rtthread.h"
#include <rtdevice.h>
#include "include.h"
#include <drivers/audio.h>
#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