add && fix voice capture, add record wave,raw orig data and final data; add adc codec voice capture; format combine dmic and adc;

This commit is contained in:
wangzijiao 2018-08-15 20:45:00 +08:00
parent 42986a822f
commit 66a7be5e7b
6 changed files with 455 additions and 125 deletions

View File

@ -57,10 +57,18 @@ static int voice_major;
static int voice_status;
static double voice_confidence;
static VoiceSessionStatus vss = VoiceSession_Init;
static WorkMode wm = WorkMode_R311_PV1;
/* ------------------------------------------------------------------------
** Function Definitions
** ------------------------------------------------------------------------ */
void setWorkMode(WorkMode mode) {
wm = mode;
}
WorkMode getWorkMode() {
return wm;
}
void setVss(VoiceSessionStatus st) { vss = st; }
VoiceSessionStatus getVss() { return vss; }

View File

@ -57,6 +57,10 @@ typedef enum {
VoiceSession_Created = 2
} VoiceSessionStatus;
typedef enum {
WorkMode_R311_PV1 = 0
} WorkMode;
void setVss(VoiceSessionStatus st);
VoiceSessionStatus getVss();
@ -92,6 +96,9 @@ void setVoiceConfidence(double voiceConfidence);
double getVoiceConfidence();
void resetAdc();
void setWorkMode(WorkMode mode);
WorkMode getWorkMode();
#ifdef __cplusplus
} /* extern "C" */
#endif /* C++ */

View File

@ -47,7 +47,9 @@ typedef struct _RecordData{
pthread_t tid_queue_read;
int runing;
int backupfilefd;
int finalfilefd;
struct pcm_config *pcm_cfg;
struct pcm_config *adc;
size_t significant_bits_per_sample;
size_t bits_per_sample;
size_t bits_per_frame;
@ -61,7 +63,6 @@ typedef struct _RecordData{
size_t buffer_frames;
size_t period_frames;
snd_output_t *log;
}RecordData;
struct pcm_config {
@ -72,14 +73,17 @@ struct pcm_config {
unsigned int period_count;
record_audio_fn audio_cb;
RecordData *recordata;
RecordData *adc;
char *format;
char *backupfilename;
char *finalfilename;
int backupfile_waveformat;
};
int Neteasae_record_start(struct pcm_config *pcm_cfg);
void Netease_record_stop(struct pcm_config *pcm_cfg);
void device_list(void);
void pcm_list(void);
#ifdef __cplusplus
} /* extern "C" */

View File

@ -29,10 +29,12 @@ when who why
#include "srcwsapi.h"
#include "uvdbus/smart_sound.h"
#include "yunxin.h"
#include <getopt.h>
#include <jansson.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <uvdbus/fifo.h>
#include <uvdbus/log.h>
@ -46,21 +48,10 @@ when who why
/* ------------------------------------------------------------------------
** Macros
** ------------------------------------------------------------------------ */
//#define BACKUP_ORIG_AUDIO
#define BACKUP_FINAL_AUDIO
/* ------------------------------------------------------------------------
** Defines
** ------------------------------------------------------------------------ */
#ifdef BACKUP_ORIG_AUDIO
#define ORIG_AUDIO_FILENAME "/mnt/UDISK/origaudio.pcm"
static int fd_audio_orig;
char *BACKUP_PATH;
#endif
#ifdef BACKUP_FINAL_AUDIO
static int fd_audio_final;
#endif
//#define ENABLE_OEM_DBUS
@ -75,6 +66,7 @@ static int fd_audio_final;
** ------------------------------------------------------------------------ */
// unsigned int g_bIsUsedTestServer;
static int in_aborting = 0;
static int justrecord = 0;
/* ------------------------------------------------------------------------
** Functions
** ------------------------------------------------------------------------ */
@ -88,10 +80,26 @@ const char *g_fmaeCfgPath = "/usr/share/fmae_res/config.ini";
CAEDATA *caeconfig = NULL;
#endif
struct pcm_config recordconfig;
struct pcm_config recordconfig = {0};
struct audio_bypass *audiobypassconfig = NULL;
static char been_wakedup = 0;
static long parse_long(const char *str, int *err)
{
long val;
char *endptr;
errno = 0;
val = strtol(str, &endptr, 0);
if (errno != 0 || *endptr != '\0')
*err = -1;
else
*err = 0;
return val;
}
#if USED_NETEASE_DC
static struct kfifo g_AudioCacheBuf;
// static DECLARE_KFIFO(g_AudioCacheBuf, unsigned char, WAKE_CACHE_DATA_SIZE);
@ -226,17 +234,9 @@ int Duilite_beforming_cb(void *userdata, int type, char *msg, int len) {
size_t hasWritten;
if (type == DUILITE_MSG_TYPE_BINARY) {
#ifdef BACKUP_FINAL_AUDIO
fd = open("/tmp/finalaudio", O_CREAT | O_APPEND | O_RDWR);
if (fd > 0) {
hasWritten = write(fd, msg, len);
close(fd);
n_debug("Has written:%d\n", hasWritten);
} else {
n_error("open file(%s) error: %d", "/tmp/finalaudio", fd);
if (recordconfig.recordata && recordconfig.recordata->finalfilefd > 0) {
write(recordconfig.recordata->finalfilefd, msg, len);
}
#endif
if (!!audiobypassconfig) {
Netease_audiobypass_write(audiobypassconfig, msg, len);
}
@ -283,9 +283,6 @@ static void CAEAudioCb(const void *audioData, unsigned int audioLen, int param1,
static void record_audio_cb(const void *audio, unsigned int audio_len,
int err_code) {
unsigned long long cachetime;
#ifdef BACKUP_ORIG_AUDIO
return;
#endif
#ifdef DEBUG_WASTE_TIME
Netease_caltime(&cachetime, 1);
@ -509,46 +506,153 @@ void LogFunc(int logLevel, const char *log, void *userData) {
IHW_LogRawString(logLevel, (char *)log);
}
static void signal_handler(int sig)
{
if (in_aborting)
return;
static void signal_handler(int sig) {
if (in_aborting)
return;
in_aborting = 1;
in_aborting = 1;
n_debug("Aborted by signal:%d, %s\n", sig, strsignal(sig));
Netease_record_stop(&recordconfig);
signal(sig, SIG_DFL);
signal(sig, SIG_DFL);
}
static void usage() {
printf(
"Usage:\n"
"-h, --help help\n"
"-l, --list-devices list all soundcards and digital audio "
"devices\n"
"-L, --list-pcms list device names\n"
"-w, --work-mode=# work mode: 0: r311_pv1\n"
"-f, --list-format list all format in alsa\n"
"-r, --just-record Only record voice to file\n"
"-t, --type=# sample format (case insensitive): raw,wav\n"
"--rawfile=# record raw data to filepath\n"
"--finalfile=# record duilite output to filepath\n");
}
enum {
OPT_RAW_FILE = 1,
OPT_FINAL_FILE
};
void main(int argc, char **argv) {
int ret;
int ret, c, option_index, err,tmp;
char *rawfile = "/dev/null";
char *finalfile = "/dev/null";
static const char short_options[] = "hlt:w:Lfr";
static const struct option long_options[] = {
{"help", 0, 0, 'h'},
{"list-devices", 0, 0, 'l'},
{"list-pcms", 0, 0, 'L'},
{"list-format", 0, 0, 'f'},
{"just-record", 0, 0, 'r'},
{"rawfile", 1, 0, OPT_RAW_FILE},
{"finalfile", 1, 0, OPT_FINAL_FILE},
{"type", 1, 0, 't'},
{"work-mode", 1, 0, 'w'},
{0, 0, 0, 0}};
#ifdef BOARD_DMIC
unsigned int channels = 8;
unsigned int rate = 16000;
unsigned int card = 1;
unsigned int device = 0;
#else
unsigned int card = 2;
unsigned int device = 0;
unsigned int channels = 2;
unsigned int rate = 96000;
#endif
// unsigned int frames;
unsigned int period_size = 1535;
unsigned int period_count = 4;
recordconfig.backupfile_waveformat = 1;
recordconfig.audio_cb = record_audio_cb;
setWorkMode(WorkMode_R311_PV1);
char sound_device_name[30];
if (argc == 1) {
printf("Not enough arg!\n");
usage();
return;
}
while ((c = getopt_long(argc, argv, short_options, long_options,
&option_index)) != -1) {
switch (c) {
case 'h':
usage();
return;
case 'l':
device_list();
return;
case 'L':
pcm_list();
return;
case 'r':
justrecord = 1;
break;
case 't':
if (strcasecmp(optarg, "wav") == 0) {
recordconfig.backupfile_waveformat = 1;
} else if (strcasecmp(optarg, "raw") == 0) {
recordconfig.backupfile_waveformat = 0;
}
printf("Wave format:%d\n", recordconfig.backupfile_waveformat);
break;
case 'w':
tmp = parse_long(optarg, &err);
if (err < 0) {
printf("invalid work mode!%s\n", optarg);
return;
} else {
setWorkMode((WorkMode)tmp);
}
break;
case OPT_RAW_FILE:
rawfile = optarg;
printf("Raw file:%s\n", optarg);
break;
case OPT_FINAL_FILE:
finalfile = optarg;
printf("Final file:%s\n", optarg);
break;
default:
printf("Unknow cmd!(%d)\n", c);
usage();
exit(0);
}
}
printf("parse arg end!\n");
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
signal(SIGABRT, signal_handler);
signal(SIGTERM, signal_handler);
signal(SIGABRT, signal_handler);
// Base module init
BaseInit();
printf("Work mode:%d\n", getWorkMode());
// resetAdc();
if (justrecord == 1) {
if (rawfile == NULL && finalfile == NULL) {
printf("Must input rawfile or finalfile!\n");
return;
}
if (rawfile != NULL) {
recordconfig.backupfilename = rawfile;
printf("Will record raw to file:%s\n", rawfile);
}
if (finalfile != NULL) {
recordconfig.finalfilename = finalfile;
printf("Will record final data to file:%s\n", finalfile);
}
recordconfig.audio_cb = NULL;
Neteasae_record_start(&recordconfig);
while (1)
usleep(1000000);
}
#ifdef ENABLE_OEM_DBUS
ret = Netease_dbus_oem_init(DBusMessageCb);
#else
// ret = Netease_Dbus_Init(DBusMessageCb);
ret = Netease_Dbus_Init(DBusMessageCb);
#endif
if (NETEASE_SUCCESS == ret) {
n_debug("Dbus init success\n");
@ -579,39 +683,6 @@ void main(int argc, char **argv) {
}
#endif
snprintf(sound_device_name, sizeof(sound_device_name), "hw:%u,%u", card,
device);
recordconfig.device_name = sound_device_name;
recordconfig.channels = channels;
recordconfig.rate = rate;
recordconfig.period_size = period_size;
recordconfig.period_count = period_count;
recordconfig.audio_cb = record_audio_cb;
recordconfig.format = "S16_LE";
recordconfig.backupfilename = NULL;
recordconfig.backupfile_waveformat = 0;
// todo write something
printf("++++++++++++++++++++++++++\n");
printf("device name is %s\n", recordconfig.device_name);
printf("Channle is %d\n", recordconfig.channels);
printf("rate name is %d\n", recordconfig.rate);
printf("period_size name is %d\n", recordconfig.period_size);
printf("++++++++++++++++++++++++++\n");
n_debug("Begin to init netease_voice modules!\n");
resetAdc();
#ifdef BACKUP_ORIG_AUDIO
recordconfig.audio_cb = NULL;
recordconfig.backupfilename = argv[1];
Neteasae_record_start(&recordconfig);
while (1)
usleep(1000000);
#endif
// Base module init
BaseInit();
#if USED_NETEASE_FMAE
ret = Netease_audiobypass_init(&audiobypassconfig, NULL,
AUDIO_BYPASS_CHANNEL_MSC_IAT);
@ -696,12 +767,12 @@ void main(int argc, char **argv) {
#ifdef ENABLE_OEM_DBUS
pthread_create(&tid, NULL, Netease_dbus_oem_start, NULL);
#else
// pthread_create(&tid, NULL, Netease_Dbus_Start_Sync, NULL);
pthread_create(&tid, NULL, Netease_Dbus_Start_Sync, NULL);
#endif
// Netease_yunxin_test();
#if 1
while (1) {
#if 0
while (1) {
if (1 == Netease_nduilite_init(Duilite_wakeup_cb, Duilite_doa_cb,
Duilite_beforming_cb, Duilite_vad_cb)) {
n_toast("Nduilite init success, exit!\n");
@ -715,7 +786,7 @@ void main(int argc, char **argv) {
while (1)
usleep(1000000);
#endif
#endif
while (1) {
if (strlen(getUuid()) == 0 || strlen(getYxToken()) == 0) {

View File

@ -395,11 +395,10 @@ void Netease_nduilite_writeaudio(const void *audioData,
return;
}
#ifdef BOARD_DMIC
//n_debug("Write nduilite data, len:%d\n", audio_len);
Dmic_data_convert(audioData, audio_len);
ret = duilite_fespa_feed(fespa, audioData, audio_len);
#else
#if 0
newbuf = (char *)malloc(audio_len + 60);
if (newbuf == NULL) {

View File

@ -28,6 +28,7 @@ when who why
#include <string.h>
#include <unistd.h>
#include "base.h"
#include "formats.h"
#include "record.h"
@ -44,7 +45,7 @@ when who why
#define ALSA_PCM_NEW_HW_PARAMS_API
#define AUDIO_QUEUE_BUFF_LEN (1024 * 10)
#define QUEUE_BUFF_MULTIPLE 500
#define QUEUE_BUFF_MULTIPLE 100
/* ------------------------------------------------------------------------
** Types
@ -67,6 +68,7 @@ static Proc_CAESetShowLog api_cae_set_show_log;
static Proc_CAEDestroy api_cae_destroy;
static off64_t fdcount = 0;
static snd_output_t *sndlog;
/* ------------------------------------------------------------------------
** Function Definitions
@ -80,6 +82,7 @@ void _record_stop(void *record_hd);
static void end_wave(int fd);
static void begin_wave(RecordData *record, int fd, size_t cnt);
void _record_stop(void *record_hd);
static int init_params(struct pcm_config *pcm_cfg, int init_queue);
/*
* make sure we write all bytes or return an error
@ -312,33 +315,98 @@ static void begin_wave(RecordData *record, int fd, size_t cnt) {
static void *RecordThread(void *param) {
RecordData *record = (RecordData *)param;
int ret = 0;
int i = 0;
long long max_file_size = 2147483648LL;
// cpu_set_t mask;
n_toast("RecordThread record:%p, running:%d\n", record, record->runing);
n_toast("record->pcm_cfg:%p\n", record->pcm_cfg);
n_toast("record->pcm_cfg->adc:%p\n", record->pcm_cfg->adc);
// CPU_ZERO(&mask);
// CPU_SET(0,&mask);
// ret = sched_setaffinity(0, sizeof(mask), &mask);
// printf("sched_setaffinity return = %d\n", ret);
if (record->backupfilefd > 0 && record->pcm_cfg->backupfile_waveformat > 0) {
if (record->backupfilefd > 0 &&
record->pcm_cfg->backupfile_waveformat > 0) {
begin_wave(record, record->backupfilefd, (size_t)max_file_size);
fdcount = 0;
}
if (record->finalfilefd > 0 && record->pcm_cfg->backupfile_waveformat > 0) {
begin_wave(record, record->backupfilefd, (size_t)max_file_size);
}
while (!!record->runing) {
if (pcm_read(record) == record->chunk_size) {
if (record->backupfilefd > 0) {
xwrite(record->backupfilefd, record->buffer,
record->chunk_bytes);
fdcount += record->chunk_bytes;
if (getWorkMode() == WorkMode_R311_PV1) {
if (pcm_read(record->pcm_cfg->adc) ==
record->pcm_cfg->adc->chunk_size) {
if (pcm_read(record) == record->chunk_size) {
// Write adc data to dmic data, in first two channel
for (i = 0; i < record->chunk_size; i++) {
// printf("copy from %p to %p, size:%d, frame:%d\n",
// (record->pcm_cfg->adc->buffer +
// i *
// record->pcm_cfg->adc->bits_per_frame
// / 8), (record->buffer + i *
// record->bits_per_frame / 8), 2 *
// record->significant_bits_per_sample /
// 8, i);
// ch:1-6 dmic
// ch:7-8 adc
memmove(
(void *)(record->buffer +
i * record->bits_per_frame / 8),
(void *)(record->buffer +
i * record->bits_per_frame / 8 +
2 * record->significant_bits_per_sample /
8),
6 * record->significant_bits_per_sample / 8);
// printf("copy to 0x%p, size:%d\n", (record->buffer +
// i * record->bits_per_frame / 8 +
// 6 * record->significant_bits_per_sample /
// 8), 2 * record->significant_bits_per_sample / 8);
memcpy(
(void *)(record->buffer +
i * record->bits_per_frame / 8 +
6 * record->significant_bits_per_sample /
8),
(void *)(record->pcm_cfg->adc->buffer +
i * record->pcm_cfg->adc->bits_per_frame /
8),
record->pcm_cfg->adc->bits_per_frame / 8);
// memcpy((void *)(record->buffer +
// i * record->bits_per_frame / 8),
// (void *)(record->pcm_cfg->adc->buffer +
// i *
// record->pcm_cfg->adc->bits_per_frame
// / 8),
// 2 * record->significant_bits_per_sample / 8);
}
if (record->backupfilefd > 0) {
xwrite(record->backupfilefd, record->buffer,
record->chunk_bytes);
fdcount += record->chunk_bytes;
}
queue_write(record->queue, record->buffer,
record->chunk_bytes);
} else {
fprintf(stderr, "short read, read %d frames/n", ret);
LOG_EX(LOG_Error, "ALSA Short Read, Read %d Frames: %d\n",
ret);
}
} else {
// read dmic data and throw
pcm_read(record);
printf("Read adc codec error!\n");
}
queue_write(record->queue, record->buffer, record->chunk_bytes);
} else {
fprintf(stderr, "short read, read %d frames/n", ret);
LOG_EX(LOG_Error, "ALSA Short Read, Read %d Frames: %d\n", ret);
printf("Unknow work mode!\n");
exit(0);
}
}
if (record->backupfilefd > 0 && record->pcm_cfg->backupfile_waveformat > 0) {
if (record->backupfilefd > 0 &&
record->pcm_cfg->backupfile_waveformat > 0) {
end_wave(record->backupfilefd);
record->backupfilefd = 0;
n_debug("Write backup file end finish!\n");
@ -359,11 +427,61 @@ static void show_available_sample_formats(snd_pcm_t *handle,
}
int Neteasae_record_start(struct pcm_config *pcm_cfg) {
pthread_attr_t thread_attr;
struct sched_param thread_param;
struct pcm_config *tmp;
printf("Begin to init netease record!\n");
snd_output_stdio_attach(&sndlog, stderr, 0);
switch (getWorkMode()) {
case WorkMode_R311_PV1:
// dmic codec
pcm_cfg->device_name = "hw:1,0";
pcm_cfg->channels = 8;
pcm_cfg->rate = 16000;
pcm_cfg->period_size = 1535;
pcm_cfg->format = "S16_LE";
printf("Begin to init dmic!\n");
init_params(pcm_cfg, 1);
tmp = (struct pcm_config *)calloc(1, sizeof(struct pcm_config));
if (tmp == NULL) {
printf("alloc fail!\n");
exit(0);
} else {
printf("Begin to init adc codec!\n");
// adc codec
tmp->device_name = "hw:2,0";
tmp->channels = 2;
tmp->rate = 16000;
tmp->period_size = 1535;
tmp->format = "S16_LE";
init_params(tmp, 0);
}
pcm_cfg->adc = tmp->recordata;
pcm_cfg->recordata->adc = tmp;
pthread_attr_init(&thread_attr);
pthread_attr_setschedpolicy(&thread_attr, SCHED_RR);
thread_param.sched_priority = sched_get_priority_max(SCHED_RR);
pthread_attr_setschedparam(&thread_attr, &thread_param);
pthread_create(&pcm_cfg->recordata->tid_pcm_read, &thread_attr,
RecordThread, (void *)pcm_cfg->recordata);
pthread_create(&pcm_cfg->recordata->tid_queue_read, NULL,
QueueReadThread, (void *)pcm_cfg->recordata);
break;
default:
printf("Unknow mode!\n");
exit(0);
}
}
static int init_params(struct pcm_config *pcm_cfg, int init_queue) {
int rc;
int size;
int ret = NETEASE_SUCCESS;
pthread_attr_t thread_attr;
struct sched_param thread_param;
snd_pcm_hw_params_t *params;
snd_pcm_sw_params_t *swparams;
unsigned int val, val2;
@ -374,6 +492,7 @@ int Neteasae_record_start(struct pcm_config *pcm_cfg) {
RecordData *record = (RecordData *)malloc(sizeof(RecordData));
if (NULL == record) {
printf("Malloc fail for record data!\n");
return NETEASE_ERROR_OUT_OF_MEMORY;
}
memset(record, 0, sizeof(RecordData));
@ -381,7 +500,6 @@ int Neteasae_record_start(struct pcm_config *pcm_cfg) {
pcm_cfg->recordata = record;
record->pcm_cfg = pcm_cfg;
record->cb = pcm_cfg->audio_cb;
snd_output_stdio_attach(&record->log, stderr, 0);
//设置录音参数参数
rc = snd_pcm_open(&record->handle, pcm_cfg->device_name,
@ -460,12 +578,12 @@ int Neteasae_record_start(struct pcm_config *pcm_cfg) {
rc = snd_pcm_hw_params(record->handle, params);
if (rc < 0) {
n_error("unable to set hw parameters: %s/n", snd_strerror(rc));
// snd_pcm_hw_dump(params, stdout);
// snd_pcm_hw_dump(params, sndlog);
ret = NETEASE_ERROR_FAIL;
goto error;
}
// snd_pcm_hw_params_dump(params, stdout);
snd_pcm_dump(record->handle, record->log);
snd_pcm_dump(record->handle, sndlog);
/* Use a buffer large enough to hold one period */
record->bits_per_sample = snd_pcm_format_physical_width(record->format);
record->significant_bits_per_sample = snd_pcm_format_width(record->format);
@ -484,14 +602,19 @@ int Neteasae_record_start(struct pcm_config *pcm_cfg) {
goto error;
}
record->queue_buff = (char *)malloc(
sizeof(audio_queue_t) + record->chunk_bytes * QUEUE_BUFF_MULTIPLE + 1);
if (NULL == record->queue_buff) {
ret = NETEASE_ERROR_OUT_OF_MEMORY;
goto error;
if (init_queue > 0) {
record->queue_buff = (char *)malloc(
sizeof(audio_queue_t) + record->chunk_bytes * QUEUE_BUFF_MULTIPLE + 1);
if (NULL == record->queue_buff) {
ret = NETEASE_ERROR_OUT_OF_MEMORY;
goto error;
}
record->queue = queue_init(record->queue_buff,
record->chunk_bytes * QUEUE_BUFF_MULTIPLE + 1);
} else {
record->queue_buff = NULL;
record->queue = NULL;
}
record->queue = queue_init(record->queue_buff,
record->chunk_bytes * QUEUE_BUFF_MULTIPLE + 1);
snd_pcm_sw_params_current(record->handle, swparams);
snd_pcm_sw_params_set_avail_min(record->handle, swparams,
@ -505,11 +628,6 @@ int Neteasae_record_start(struct pcm_config *pcm_cfg) {
goto error;
}
pthread_attr_init(&thread_attr);
pthread_attr_setschedpolicy(&thread_attr, SCHED_RR);
thread_param.sched_priority = sched_get_priority_max(SCHED_RR);
pthread_attr_setschedparam(&thread_attr, &thread_param);
record->runing = 1;
if (pcm_cfg->backupfilename != NULL) {
@ -523,11 +641,21 @@ int Neteasae_record_start(struct pcm_config *pcm_cfg) {
n_debug("Create backup file:%s, fd:%d\n", pcm_cfg->backupfilename,
record->backupfilefd);
}
if (pcm_cfg->finalfilename != NULL) {
if (!lstat(pcm_cfg->finalfilename, &statbuf)) {
if (S_ISREG(statbuf.st_mode))
remove(pcm_cfg->finalfilename);
n_debug("Remove file:%s\n", pcm_cfg->finalfilename);
}
record->finalfilefd =
open(pcm_cfg->finalfilename, O_TRUNC | O_WRONLY | O_CREAT, 06444);
n_debug("Create final file:%s, fd:%d\n", pcm_cfg->finalfilename,
record->finalfilefd);
}
n_toast("Record_start record :%p\n", record);
pthread_create(&record->tid_pcm_read, &thread_attr, RecordThread,
(void *)record);
pthread_create(&record->tid_queue_read, NULL, QueueReadThread,
(void *)record);
goto exit;
error:
@ -574,4 +702,117 @@ void Netease_record_stop(struct pcm_config *config) {
if (config != NULL && config->recordata != NULL) {
config->recordata->runing = 0;
}
}
void device_list(void) {
snd_ctl_t *handle;
int card, err, dev, idx;
snd_ctl_card_info_t *info;
snd_pcm_info_t *pcminfo;
snd_pcm_stream_t stream = SND_PCM_STREAM_CAPTURE;
snd_ctl_card_info_alloca(&info);
snd_pcm_info_alloca(&pcminfo);
card = -1;
if (snd_card_next(&card) < 0 || card < 0) {
n_error("no soundcards found...");
return;
}
printf("**** List of %s Hardware Devices ****\n",
snd_pcm_stream_name(stream));
while (card >= 0) {
char name[32];
sprintf(name, "hw:%d", card);
if ((err = snd_ctl_open(&handle, name, 0)) < 0) {
n_error("control open (%i): %s", card, snd_strerror(err));
goto next_card;
}
if ((err = snd_ctl_card_info(handle, info)) < 0) {
n_error("control hardware info (%i): %s", card, snd_strerror(err));
snd_ctl_close(handle);
goto next_card;
}
dev = -1;
while (1) {
unsigned int count;
if (snd_ctl_pcm_next_device(handle, &dev) < 0)
n_error("snd_ctl_pcm_next_device");
if (dev < 0)
break;
snd_pcm_info_set_device(pcminfo, dev);
snd_pcm_info_set_subdevice(pcminfo, 0);
snd_pcm_info_set_stream(pcminfo, stream);
if ((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) {
if (err != -ENOENT)
n_error("control digital audio info (%i): %s", card,
snd_strerror(err));
continue;
}
printf(("card %i: %s [%s], device %i: %s [%s]\n"), card,
snd_ctl_card_info_get_id(info),
snd_ctl_card_info_get_name(info), dev,
snd_pcm_info_get_id(pcminfo),
snd_pcm_info_get_name(pcminfo));
count = snd_pcm_info_get_subdevices_count(pcminfo);
printf((" Subdevices: %i/%i\n"),
snd_pcm_info_get_subdevices_avail(pcminfo), count);
for (idx = 0; idx < (int)count; idx++) {
snd_pcm_info_set_subdevice(pcminfo, idx);
if ((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) {
n_error("control digital audio playback info (%i): %s",
card, snd_strerror(err));
} else {
printf((" Subdevice #%i: %s\n"), idx,
snd_pcm_info_get_subdevice_name(pcminfo));
}
}
}
snd_ctl_close(handle);
next_card:
if (snd_card_next(&card) < 0) {
n_error("snd_card_next");
break;
}
}
}
void pcm_list(void) {
void **hints, **n;
char *name, *descr, *descr1, *io;
const char *filter;
if (snd_device_name_hint(-1, "pcm", &hints) < 0)
return;
n = hints;
// filter = stream == SND_PCM_STREAM_CAPTURE ? "Input" : "Output";
filter = "Input";
while (*n != NULL) {
name = snd_device_name_get_hint(*n, "NAME");
descr = snd_device_name_get_hint(*n, "DESC");
io = snd_device_name_get_hint(*n, "IOID");
if (io != NULL && strcmp(io, filter) != 0)
goto __end;
printf("%s\n", name);
if ((descr1 = descr) != NULL) {
printf(" ");
while (*descr1) {
if (*descr1 == '\n')
printf("\n ");
else
putchar(*descr1);
descr1++;
}
putchar('\n');
}
__end:
if (name != NULL)
free(name);
if (descr != NULL)
free(descr);
if (io != NULL)
free(io);
n++;
}
snd_device_name_free_hint(hints);
}