You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

149 lines
3.9 KiB

/*
* Copyright (c) Hisilicon Technologies Co., Ltd. 2020-2021. All rights reserved.
* Description: tiny_capture sample
* Author: audio
* Create: 2020-04-03
*/
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <tinyalsa/asoundlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <pthread.h>
#include "securec.h"
#include "td_type.h"
#include "uapi_sound.h"
#include "karaoke.h"
#define MIC_BUF_MAX_SIZE 16384
struct pcm *pcm;
static td_bool g_single_channel_support = TD_FALSE;
static td_void get_max_channels_support(td_u32 card, td_u32 device)
{
struct pcm_params *params = TD_NULL;
params = pcm_params_get(card, device, PCM_IN);
if (params == NULL) {
printf("Device does not exist.\n");
return;
}
if (pcm_params_get_max(params, PCM_PARAM_CHANNELS) == 1) {
g_single_channel_support = TD_TRUE;
} else {
g_single_channel_support = TD_FALSE;
}
pcm_params_free(params);
}
td_s32 usb_mic_dev_init(unsigned int card)
{
struct pcm_config config;
const td_u32 device = 0;
memset_s(&config, sizeof(config), 0, sizeof(config));
get_max_channels_support(card, device);
config.channels = (g_single_channel_support == TD_TRUE) ? 1 : CHANNELS_2;
config.rate = UAPI_AUDIO_SAMPLE_RATE_48K;
config.period_size = DEFAULT_PERIOD_SIZE;
config.period_count = DEFAULT_PERIOD_COUNT;
config.format = PCM_FORMAT_S16_LE;
config.start_threshold = 0;
config.stop_threshold = 0;
config.silence_threshold = 0;
pcm = pcm_open(card, device, PCM_IN, &config);
if (pcm == TD_NULL || pcm_is_ready(pcm) == TD_FALSE) {
printf("Unable to open PCM device (%s)\n", pcm_get_error(pcm));
return -1;
}
return TD_SUCCESS;
}
td_void usb_mic_dev_deinit(td_void)
{
pcm_close(pcm);
}
static td_void *tiny_capture_thread(td_void *args)
{
struct timespec end;
struct timespec now;
td_u32 period_size;
td_s16 *mic_buf = TD_NULL;
td_s16 *mic_buf2 = TD_NULL;
td_s32 n;
sample_capture_ctx *capture_ctx = (sample_capture_ctx *)args;
mic_buf = (td_s16 *)malloc(MIC_BUF_MAX_SIZE * sizeof(td_s16));
if (mic_buf == TD_NULL) {
return TD_NULL;
}
mic_buf2 = (td_s16 *)malloc(MIC_BUF_MAX_SIZE * sizeof(td_s16));
if (mic_buf2 == TD_NULL) {
free(mic_buf);
return TD_NULL;
}
if (g_single_channel_support == TD_TRUE) {
period_size = DEFAULT_PERIOD_SIZE / CHANNELS_2;
capture_ctx->ao_frame.pcm_buffer = (td_s32 *)mic_buf2;
} else {
period_size = DEFAULT_PERIOD_SIZE;
capture_ctx->ao_frame.pcm_buffer = (td_s32 *)mic_buf;
}
clock_gettime(CLOCK_MONOTONIC, &now);
end.tv_sec = now.tv_sec;
end.tv_nsec = now.tv_nsec;
while (capture_ctx->stop == TD_FALSE) {
do {
n = pcm_read(pcm, mic_buf, period_size);
} while (n == -EAGAIN);
if (g_single_channel_support == TD_TRUE) {
for (td_u32 i = 0; i < period_size / sizeof(td_s16); i++) {
mic_buf2[CHANNELS_2 * i] = mic_buf[i];
mic_buf2[CHANNELS_2 * i + 1] = mic_buf[i];
}
}
uapi_snd_send_track_data(capture_ctx->track_id, &capture_ctx->ao_frame);
}
free(mic_buf);
free(mic_buf2);
usb_mic_dev_deinit();
return TD_NULL;
}
td_void capture_sample_start(sample_capture_ctx *capture_ctx)
{
if (capture_ctx == TD_NULL) {
return;
}
capture_ctx->stop = TD_FALSE;
pthread_create(&capture_ctx->thread, TD_NULL, tiny_capture_thread, capture_ctx);
}
td_void capture_sample_stop(sample_capture_ctx *capture_ctx)
{
if (capture_ctx == TD_NULL) {
return;
}
capture_ctx->stop = TD_TRUE;
pthread_join(capture_ctx->thread, TD_NULL);
}