/* * Copyright (c) Hisilicon Technologies Co., Ltd. 2020-2021. All rights reserved. * Description: tiny_capture sample * Author: audio * Create: 2020-04-03 */ #include #include #include #include #include #include #include #include #include #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); }