luckfox-pico-sdk/sysdrv/source/mcu/rt-thread/components/aupipe/basics/audiosink.c
luckfox-eng29 8f34c2760d project:build.sh: Added fastboot support; custom modifications to U-Boot and kernel implemented using patches.
project:cfg:BoardConfig_IPC: Added fastboot BoardConfig file and firmware post-scripts, distinguishing between
the BoardConfigs for Luckfox Pico Pro and Luckfox Pico Max. project:app: Added fastboot_client and rk_smart_door
for quick boot applications; updated rkipc app to adapt to the latest media library. media:samples: Added more
usage examples. media:rockit: Fixed bugs; removed support for retrieving data frames from VPSS. media:isp:
Updated rkaiq library and related tools to support connection to RKISP_Tuner. sysdrv:Makefile: Added support for
compiling drv_ko on Luckfox Pico Ultra W using Ubuntu; added support for custom root filesystem.
sysdrv:tools:board: Updated Buildroot optional mirror sources, updated some software versions, and stored device
tree files and configuration files that undergo multiple modifications for U-Boot and kernel separately.
sysdrv:source:mcu: Used RISC-V MCU SDK with RT-Thread system, mainly for initializing camera AE during quick
boot. sysdrv:source:uboot: Added support for fastboot; added high baud rate DDR bin for serial firmware upgrades.
sysdrv:source:kernel: Upgraded to version 5.10.160; increased NPU frequency for RV1106G3; added support for
fastboot.

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>
2024-10-14 09:47:04 +08:00

233 lines
5.4 KiB
C

/**
* Copyright (c) 2022 Rockchip Electronics Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "aupipe.h"
#ifdef RT_USING_AUPIPE_AUDIOSINK
#include "drv_heap.h"
#include "rk_audio.h"
#undef DBG_SECTION_NAME
#define DBG_SECTION_NAME "AUDIOSINK"
#define AUDIOSINK(obj) ((ApAudioSink *)(obj))
typedef struct audiosink_object
{
ApObject base;
ApPad *sink_pad;
int channels;
char *card_name;
char *buffer;
rt_thread_t loop;
struct rt_device *card;
struct AUDIO_PARAMS param;
struct audio_buf abuf;
uint32_t bit_width;
uint32_t sink_map;
uint32_t default_map;
} ApAudioSink;
static int audiosink_process(ApPad *pad, ApBuffer *buffer);
static int audiosink_init(ApObject *obj, void *arg)
{
ApAudioSink *audsink = AUDIOSINK(obj);
int status = RT_EOK;
Aupipe *aupipe = obj->parent;
char *parameters = (char *)arg;
status |= aupipe_find_property(parameters, "card",
VALUE_TYPE_STRING, &audsink->card_name);
status |= aupipe_find_property(parameters, "channels",
VALUE_TYPE_INT, &audsink->channels);
if (status != RT_EOK)
{
LOG_E("%s plug-in parameter initialization failed", audsink->base.name);
return -RT_ERROR;
}
audsink->bit_width = aupipe->bits >> 3;
audsink->sink_map = (1 << audsink->channels) - 1;
audsink->buffer = rt_malloc(aupipe->period_size * audsink->channels * audsink->bit_width);
audsink->sink_pad = aupipe_pad_new(obj, audsink->channels);
RT_ASSERT(audsink->sink_pad != NULL);
for (int i = 0; i < audsink->channels; i++)
{
audsink->sink_pad[i].process = audiosink_process;
}
return RT_EOK;
}
static int audiosink_deinit(ApObject *obj)
{
ApAudioSink *audsink = AUDIOSINK(obj);
rt_free(audsink->buffer);
rt_free(audsink->sink_pad);
rt_free(audsink->card_name);
return RT_EOK;
}
static int audiosink_process(ApPad *pad, ApBuffer *buffer)
{
ApAudioSink *obj = AUDIOSINK(pad->parent);
int ret = RT_EOK;
short *out = (short *)obj->buffer;
if (buffer->type != DATA_TYPE_AUDIO)
{
aupipe_buffer_unref(buffer);
return -RT_ERROR;
}
for (int i = 0; i < obj->abuf.period_size; i++)
{
rt_memcpy(obj->buffer + (obj->param.channels * i + pad->id) * obj->bit_width,
buffer->data + obj->bit_width * i, obj->bit_width);
}
aupipe_buffer_unref(buffer);
obj->sink_map = obj->sink_map & (~(1 << pad->id));
if (obj->sink_map != 0)
{
return ret;
}
obj->sink_map = (1 << obj->channels) - 1;
if (!rt_device_write(obj->card, 0, out, obj->abuf.period_size))
{
rt_kprintf("Error playing sample\n");
ret = -RT_ERROR;
}
return ret;
}
static int audiosink_open_card(ApAudioSink *obj)
{
int size;
rt_err_t ret;
int period_count = 4;
Aupipe *aupipe = obj->base.parent;
struct audio_buf *abuf = &obj->abuf;
struct AUDIO_PARAMS *param = &obj->param;
obj->card = rt_device_find(obj->card_name);
if (!obj->card)
{
LOG_E("Can't find sound device: %s\n", obj->card_name);
goto no_card;
}
ret = rt_device_open(obj->card, RT_DEVICE_OFLAG_WRONLY);
if (ret < 0)
{
LOG_E("Failed to open %s, err: %d\n", obj->card->parent.name, ret);
goto open_failed;
}
abuf->period_size = aupipe->period_size;
abuf->buf_size = aupipe->period_size * period_count;
size = abuf->buf_size * obj->channels * (aupipe->bits >> 3); /* frames to bytes */
abuf->buf = rt_malloc_uncache(size);
if (!abuf->buf)
{
LOG_E("Buffer alloc failed!\n");
goto malloc_failed;
}
param->channels = obj->channels;
param->sampleRate = aupipe->rate;
param->sampleBits = aupipe->bits;
ret = rt_device_control(obj->card, RK_AUDIO_CTL_PCM_PREPARE, abuf);
RT_ASSERT(ret == RT_EOK);
ret = rt_device_control(obj->card, RK_AUDIO_CTL_HW_PARAMS, param);
RT_ASSERT(ret == RT_EOK);
return RT_EOK;
malloc_failed:
rt_device_close(obj->card);
open_failed:
no_card:
return -RT_ERROR;
}
static int audiosink_close_card(ApAudioSink *obj)
{
struct audio_buf *abuf = &obj->abuf;
rt_err_t ret;
ret = rt_device_control(obj->card, RK_AUDIO_CTL_STOP, NULL);
RT_ASSERT(ret == RT_EOK);
ret = rt_device_control(obj->card, RK_AUDIO_CTL_PCM_RELEASE, NULL);
RT_ASSERT(ret == RT_EOK);
rt_free_uncache(abuf->buf);
rt_device_close(obj->card);
return RT_EOK;
}
static int audiosink_set_state(ApObject *obj, int state)
{
ApAudioSink *audsink = AUDIOSINK(obj);
switch (state)
{
case STATE_NULL_TO_READY:
LOG_I("STATE_NULL_TO_READY");
if (audiosink_open_card(audsink) != RT_EOK)
return -RT_ERROR;
break;
case STATE_READY_TO_NULL:
LOG_I("STATE_READY_TO_NULL");
audiosink_close_card(audsink);
break;
default:
break;
}
return RT_EOK;
}
static int audiosink_set_property(ApObject *obj, char *name, void *arg)
{
return RT_EOK;
}
static int audiosink_get_property(ApObject *obj, char *name, void *arg)
{
return RT_EOK;
}
static ApPad *audiosink_get_pad(ApObject *obj, int type, int id)
{
ApAudioSink *audsink = AUDIOSINK(obj);
if (type == PAD_TYPE_SRC)
return NULL;
return &audsink->sink_pad[id];
}
OBJECT_BASE_DEFINE(audiosink, ApAudioSink);
#endif