#include #include #include #include #include #include #include #include #include #include "ringbuffer.h" #ifdef LPKG_USING_DFS #include #include #ifdef LPKG_USING_DFS_ELMFAT #include #endif #endif aic_audio_ctrl audio_ctrl; ringbuf_t *ring_buf; #define TX_FIFO_SIZE 81920 #define TX_FIFO_PERIOD_COUNT 4 #define BUFFER_SIZE 2048 rt_uint8_t audio_tx_fifo[TX_FIFO_SIZE] __attribute__((aligned(64))); struct RIFF_HEADER_DEF { char riff_id[4]; // 'R','I','F','F' uint32_t riff_size; char riff_format[4]; // 'W','A','V','E' }; struct WAVE_FORMAT_DEF { uint16_t FormatTag; uint16_t Channels; unsigned int SamplesPerSec; unsigned int AvgBytesPerSec; uint16_t BlockAlign; uint16_t BitsPerSample; }; struct FMT_BLOCK_DEF { char fmt_id[4]; // 'f','m','t',' ' uint32_t fmt_size; struct WAVE_FORMAT_DEF wav_format; }; struct DATA_BLOCK_DEF { char data_id[4]; // 'R','I','F','F' uint32_t data_size; }; struct wav_info { struct RIFF_HEADER_DEF header; struct FMT_BLOCK_DEF fmt_block; struct DATA_BLOCK_DEF data_block; }; static void drv_audio_callback(aic_audio_ctrl *pcodec, void *arg) { unsigned long event = (unsigned long)arg; switch (event) { case AUDIO_TX_PERIOD_INT: ring_buf->read += pcodec->tx_info.buf_info.period_len; ring_buf->data_len -= pcodec->tx_info.buf_info.period_len; break; default: hal_log_err("%s(%d)\n", __func__, __LINE__); break; } } static int sound_aplay(int argc, char *argv[]) { int fd; struct wav_info *info = NULL; uint8_t *buffer = NULL; unsigned int pa, group, pin; uint8_t start_flag = 0; if (argc != 2) { hal_log_err("Usage:\n"); hal_log_err("sound_aplay song.wav\n"); return 0; } fd = open(argv[1], O_RDONLY); if (fd < 0) { hal_log_err("open file failed!\n"); goto __exit; } buffer = aicos_malloc(MEM_PSRAM_CMA, BUFFER_SIZE); if (!buffer) { hal_log_err("buffer malloc error!\n"); goto __exit; } ring_buf = aicos_malloc(MEM_PSRAM_CMA, sizeof(ringbuf_t)); if (!ring_buf) { hal_log_err("ring_buf malloc error!\n"); goto __exit; } ring_buf->buffer = audio_tx_fifo; ring_buf->size = TX_FIFO_SIZE; ring_buf->write = 0; ring_buf->read = 0; ring_buf->data_len = 0; info = aicos_malloc(MEM_PSRAM_CMA, sizeof(struct wav_info)); if (!info) { hal_log_err("malloc error!\n"); goto __exit; } if (read(fd, &(info->header), sizeof(struct RIFF_HEADER_DEF)) <= 0) { hal_log_err("wav header parse error!\n"); goto __exit; } if (read(fd, &(info->fmt_block), sizeof(struct FMT_BLOCK_DEF)) <= 0) { hal_log_err("wav fmt_block parse error!\n"); goto __exit; } if (read(fd, &(info->data_block), sizeof(struct DATA_BLOCK_DEF)) <= 0) { hal_log_err("wav data_block parse error!\n"); goto __exit; } hal_log_info("wav information:\n"); hal_log_info("samplerate %u\n", info->fmt_block.wav_format.SamplesPerSec); hal_log_info("channel %u\n", info->fmt_block.wav_format.Channels); audio_ctrl.tx_info.buf_info.buf = (void *)audio_tx_fifo; audio_ctrl.tx_info.buf_info.buf_len = TX_FIFO_SIZE; audio_ctrl.tx_info.buf_info.period_len = TX_FIFO_SIZE / TX_FIFO_PERIOD_COUNT; hal_audio_init(&audio_ctrl); hal_audio_attach_callback(&audio_ctrl, drv_audio_callback, NULL); /* Configure audio format */ /* AudioCodec only support 16 bits */ hal_audio_set_playback_channel(&audio_ctrl, info->fmt_block.wav_format.Channels); hal_audio_set_samplerate(&audio_ctrl, info->fmt_block.wav_format.SamplesPerSec); audio_ctrl.config.samplerate = info->fmt_block.wav_format.SamplesPerSec; audio_ctrl.config.channel = info->fmt_block.wav_format.Channels; audio_ctrl.config.samplebits = 16; #ifdef AIC_AUDIO_SPK_0 hal_audio_set_playback_by_spk0(&audio_ctrl); #endif #ifdef AIC_AUDIO_SPK_1 hal_audio_set_playback_by_spk1(&audio_ctrl); #endif #ifdef AIC_AUDIO_SPK_0_1 hal_audio_set_playback_by_spk0(&audio_ctrl); hal_audio_set_playback_by_spk1(&audio_ctrl); #ifdef AIC_AUDIO_SPK0_OUTPUT_DIFFERENTIAL hal_audio_set_pwm0_differential(&audio_ctrl); #endif #ifdef AIC_AUDIO_SPK1_OUTPUT_DIFFERENTIAL hal_audio_set_pwm1_differential(&audio_ctrl); #endif #endif pa = hal_gpio_name2pin(AIC_AUDIO_PA_ENABLE_GPIO); group = GPIO_GROUP(pa); pin = GPIO_GROUP_PIN(pa); hal_gpio_set_func(group, pin, 1); hal_gpio_direction_output(group, pin); #ifdef AIC_AUDIO_EN_PIN_HIGH hal_gpio_set_output(group, pin); #else hal_gpio_clr_output(group, pin); #endif hal_dma_init(); aicos_request_irq(DMA_IRQn, hal_dma_irq, 0, NULL, NULL); uint32_t total_len = 0; while (1) { int length, wr_size; uint8_t *tmp_buf; length = read(fd, buffer, BUFFER_SIZE); if (length <= 0) break; if (!start_flag) { wr_size = 0; tmp_buf = buffer; wr_size = ringbuf_in(ring_buf, tmp_buf, length); total_len += wr_size; if (total_len >= TX_FIFO_SIZE) { start_flag = 1; hal_audio_playback_start(&audio_ctrl); } } else { wr_size = 0; tmp_buf = buffer; while (length) { wr_size = ringbuf_in(ring_buf, tmp_buf, length); tmp_buf += wr_size; length -= wr_size; } } } #ifdef AIC_AUDIO_EN_PIN_HIGH hal_gpio_clr_output(group, pin); #else hal_gpio_set_output(group, pin); #endif hal_audio_playback_stop(&audio_ctrl); __exit: return 0; } CONSOLE_CMD(aplay, sound_aplay, "aplay song.wav");