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
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);
|
|
}
|