From 8734b795e9c3a5b634d81259d49b468aab4a9d84 Mon Sep 17 00:00:00 2001 From: joysuff <338421459@qq.com> Date: Fri, 28 Jun 2024 22:31:15 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0key1=E5=BD=95=E9=9F=B3?= =?UTF-8?q?=EF=BC=8Ckey2=E8=B0=83=E5=A4=A7=E9=9F=B3=E9=87=8F=EF=BC=8Ckey3?= =?UTF-8?q?=E8=B0=83=E5=B0=8F=E9=9F=B3=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 11 ++-- control.c | 171 +++++++------------------------------------------ control.h | 44 +++++++++++++ key.c | 116 +++++++++++++++++++++++++++++++++ play.c | 149 ++++++++++++++++++++++++++++++++++++++++++ record.c | 116 +++++++++++++++++++++++++++++++++ record.h | 20 ++++++ 7 files changed, 475 insertions(+), 152 deletions(-) create mode 100644 control.h create mode 100644 key.c create mode 100644 play.c create mode 100644 record.c create mode 100644 record.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a7c32b..01d4d4f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,13 +1,14 @@ cmake_minimum_required(VERSION 3.0.0) project(voice_assistant VERSION 0.1.0 LANGUAGES C) -add_executable(voice_assistant main.c) +add_library(record STATIC record.c) +add_library(control STATIC control.c) -add_executable(control control.c) -target_link_libraries(control asound) +add_executable(voice_assistant main.c) -add_executable(record record.c) -target_link_libraries(record asound) add_executable(play play.c) target_link_libraries(play asound) + +add_executable(key key.c) +target_link_libraries(key gpiod record asound control) \ No newline at end of file diff --git a/control.c b/control.c index c5c6426..528f7fb 100644 --- a/control.c +++ b/control.c @@ -1,11 +1,8 @@ #include #include #include +#include "control.h" -// 设置音频采集开关的函数 -// card: 声卡名称 -// selem: 控制项名称 -// enable: 开关状态 int set_capture_switch(const char* card, const char* selem, bool enable) { int err; snd_mixer_t *handle; @@ -65,10 +62,6 @@ int set_capture_switch(const char* card, const char* selem, bool enable) { return 0; // 成功 } -// 设置音频回放开关的函数 -// card: 声卡名称 -// selem: 控制项名称 -// enable: 开关状态 int set_playback_switch(const char* card, const char* selem, bool enable) { int err; snd_mixer_t *handle; @@ -128,12 +121,7 @@ int set_playback_switch(const char* card, const char* selem, bool enable) { return 0; // 成功 } -// 获取音频采集音量 -// card: 声卡名称 -// selem: 控制项名称 -// 返回值: 当前音量 -int get_capture_volume(const char* card, const char* selem) -{ +int get_capture_volume(const char* card, const char* selem) { int err; snd_mixer_t *handle; snd_mixer_selem_id_t *sid; @@ -193,10 +181,6 @@ int get_capture_volume(const char* card, const char* selem) return volume; // 成功返回音量 } -// 获取音频回放通道音量 -// card: 声卡名称 -// selem: 控制项名称 -// 返回值: 当前音量 int get_playback_volume(const char* card, const char* selem) { int err; snd_mixer_t *handle; @@ -250,27 +234,14 @@ int get_playback_volume(const char* card, const char* selem) { snd_mixer_close(handle); return err; } - // 获取音量范围 - long min_volume, max_volume; - if ((err = snd_mixer_selem_get_playback_volume_range(elem, &min_volume, &max_volume)) < 0) { - fprintf(stderr, "snd_mixer_selem_get_playback_volume_range error: %s\n", snd_strerror(err)); - snd_mixer_close(handle); - return err; - } - volume = (volume - min_volume) * 100 / (max_volume - min_volume); + // 关闭混音器 snd_mixer_close(handle); return volume; // 成功返回音量 } -// 设置音频采集音量 -// card: 声卡名称 -// selem: 控制项名称 -// volume: 设置音量 -// 返回值: 成功返回设置后的音量,失败返回错误码 -int set_capture_volume(const char* card, const char* selem, long volume) -{ +int set_capture_volume(const char* card, const char* selem, long volume) { int err; snd_mixer_t *handle; snd_mixer_selem_id_t *sid; @@ -316,25 +287,6 @@ int set_capture_volume(const char* card, const char* selem, long volume) return -ENOENT; } - // 获取音量范围 - long min, max; - if ((err = snd_mixer_selem_get_capture_volume_range(elem, &min, &max)) < 0) - { - fprintf(stderr, "Unable to get capture volume range: %s\n", snd_strerror(err)); - snd_mixer_close(handle); - return err; - } - - if (volume < min) - { - volume = min; - } - - if (volume > max) - { - volume = max; - } - // 设置采集通道音量 if ((err = snd_mixer_selem_set_capture_volume_all(elem, volume)) < 0) { fprintf(stderr, "Unable to set capture volume: %s\n", snd_strerror(err)); @@ -345,139 +297,64 @@ int set_capture_volume(const char* card, const char* selem, long volume) // 关闭混音器 snd_mixer_close(handle); - return volume; // 成功 + return volume; // 成功返回设置的音量 } -// 设置音频回放通道音量 -// card: 声卡名称 -// selem: 控制项名称 -// volume: 设置音量 -// 返回值: 成功返回设置后的音量,失败返回错误码 -int set_playback_volume(const char* card, const char* selem, long volume) -{ +int set_playback_volume(const char* card, const char* selem, long volume) { int err; snd_mixer_t *handle; snd_mixer_selem_id_t *sid; - // 打开 Mixer 设备 + // 打开混音器 if ((err = snd_mixer_open(&handle, 0)) < 0) { - fprintf(stderr, "snd_mixer_open error: %s\n", snd_strerror(err)); + fprintf(stderr, "Mixer %s open error: %s\n", card, snd_strerror(err)); return err; } - // 附加指定的声卡 + // 附加控制接口到混音器 if ((err = snd_mixer_attach(handle, card)) < 0) { - fprintf(stderr, "snd_mixer_attach error: %s\n", snd_strerror(err)); + fprintf(stderr, "Mixer attach %s error: %s\n", card, snd_strerror(err)); snd_mixer_close(handle); return err; } - // 注册 Mixer 控制器 + // 注册混音器 if ((err = snd_mixer_selem_register(handle, NULL, NULL)) < 0) { - fprintf(stderr, "snd_mixer_selem_register error: %s\n", snd_strerror(err)); + fprintf(stderr, "Mixer register error: %s\n", snd_strerror(err)); snd_mixer_close(handle); return err; } - // 加载 Mixer 元素 + // 加载混音器元素 if ((err = snd_mixer_load(handle)) < 0) { - fprintf(stderr, "snd_mixer_load error: %s\n", snd_strerror(err)); + fprintf(stderr, "Mixer %s load error: %s\n", card, snd_strerror(err)); snd_mixer_close(handle); return err; } - // 分配一个简单元素 ID + // 分配简单元素ID snd_mixer_selem_id_alloca(&sid); + + // 设置简单元素的名称 snd_mixer_selem_id_set_name(sid, selem); // 查找简单元素 snd_mixer_elem_t *elem = snd_mixer_find_selem(handle, sid); if (!elem) { - fprintf(stderr, "snd_mixer_find_selem error\n"); - snd_mixer_close(handle); - return -1; - } - - // 获取音量范围 - long min_volume, max_volume; - if ((err = snd_mixer_selem_get_playback_volume_range(elem, &min_volume, &max_volume)) < 0) { - fprintf(stderr, "snd_mixer_selem_get_playback_volume_range error: %s\n", snd_strerror(err)); - snd_mixer_close(handle); - return err; - } - - printf("Volume range: %ld - %ld\n", min_volume, max_volume); - - // 限制输入音量在 0-100 范围内 - if (volume < 0) volume = 0; - if (volume > 100) volume = 100; - - // 将输入音量从 0-100 映射到实际音量范围 - long mapped_volume = min_volume + (volume * (max_volume - min_volume) / 100); - - printf("Setting volume to: %ld (mapped to %ld)\n", volume, mapped_volume); - - // 设置左声道和右声道音量 - if ((err = snd_mixer_selem_set_playback_volume_all(elem, mapped_volume)) < 0) { - fprintf(stderr, "snd_mixer_selem_set_playback_volume_all error: %s\n", snd_strerror(err)); + fprintf(stderr, "Unable to find simple control '%s',%i\n", selem, 0); snd_mixer_close(handle); - return err; + return -ENOENT; } - // 验证设置的音量 - long left_vol, right_vol; - if ((err = snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, &left_vol)) < 0) { - fprintf(stderr, "snd_mixer_selem_get_playback_volume error: %s\n", snd_strerror(err)); - snd_mixer_close(handle); - return err; - } - if ((err = snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, &right_vol)) < 0) { - fprintf(stderr, "snd_mixer_selem_get_playback_volume error: %s\n", snd_strerror(err)); + // 设置回放通道音量 + if ((err = snd_mixer_selem_set_playback_volume_all(elem, volume)) < 0) { + fprintf(stderr, "Unable to set playback volume: %s\n", snd_strerror(err)); snd_mixer_close(handle); return err; } - // 将实际音量转换回 0-100 范围 - long left_vol_mapped = (left_vol - min_volume) * 100 / (max_volume - min_volume); - long right_vol_mapped = (right_vol - min_volume) * 100 / (max_volume - min_volume); - - printf("Set volume: Left=%ld (mapped %ld), Right=%ld (mapped %ld)\n", left_vol, left_vol_mapped, right_vol, right_vol_mapped); - - // 关闭 Mixer 设备 + // 关闭混音器 snd_mixer_close(handle); - return volume; + return volume; // 成功返回设置的音量 } - -int main(int argc, char** argv) -{ - // 查看回放设备声音 - printf("Playback Vol: %d\n", get_playback_volume("hw:0", "Analog")); - // 设置回放设备声音 - printf("New Playback Vol: %d\n", set_playback_volume("hw:0", "Analog", atoi(argv[1]))); - // // 查看采集设备声音 - // printf("Capture Vol: %d\n", get_capture_volume("hw:0", "Capture")); - // // 设置采集设备声音 - // printf("New Capture Vol: %d\n", set_capture_volume("hw:0", "Capture", atoi(argv[2]))); - -// if (strcmp(argv[3], "on") == 0) -// { -// set_playback_switch("default","Master",true); -// } - -// if (strcmp(argv[3], "off") == 0) -// { -// set_playback_switch("default","Master",false); -// } - -// if (strcmp(argv[4], "on") == 0) -// { -// set_capture_switch("default","Capture",true); -// } - -// if (strcmp(argv[4], "off") == 0) -// { -// set_capture_switch("default","Capture",false); -// } - return 0; -} \ No newline at end of file diff --git a/control.h b/control.h new file mode 100644 index 0000000..768e9d0 --- /dev/null +++ b/control.h @@ -0,0 +1,44 @@ +#ifndef CONTROL_H +#define CONTROL_H + +#include + +// 设置音频采集开关的函数 +// card: 声卡名称 +// selem: 控制项名称 +// enable: 开关状态 +int set_capture_switch(const char* card, const char* selem, bool enable); + +// 设置音频回放开关的函数 +// card: 声卡名称 +// selem: 控制项名称 +// enable: 开关状态 +int set_playback_switch(const char* card, const char* selem, bool enable); + +// 获取音频采集音量 +// card: 声卡名称 +// selem: 控制项名称 +// 返回值: 当前音量 +int get_capture_volume(const char* card, const char* selem); + +// 获取音频回放通道音量 +// card: 声卡名称 +// selem: 控制项名称 +// 返回值: 当前音量 +int get_playback_volume(const char* card, const char* selem); + +// 设置音频采集音量 +// card: 声卡名称 +// selem: 控制项名称 +// volume: 设置音量 +// 返回值: 成功返回设置后的音量,失败返回错误码 +int set_capture_volume(const char* card, const char* selem, long volume); + +// 设置音频回放通道音量 +// card: 声卡名称 +// selem: 控制项名称 +// volume: 设置音量 +// 返回值: 成功返回设置后的音量,失败返回错误码 +int set_playback_volume(const char* card, const char* selem, long volume); + +#endif // CONTROL_H diff --git a/key.c b/key.c new file mode 100644 index 0000000..c6903d2 --- /dev/null +++ b/key.c @@ -0,0 +1,116 @@ +#include +#include +#include +#include +#include +#include +#include +#include "record.h" +#include "control.h" + +#define GPIO_LINE_KEY1 9 +#define GPIO_LINE_KEY2 7 +#define GPIO_LINE_KEY3 8 + +int main(void) { + struct gpiod_chip *chip; + struct gpiod_line *line_key1, *line_key2, *line_key3; + int value_key1, last_value_key1; + int value_key2, last_value_key2; + int value_key3, last_value_key3; + pid_t record_pid = -1; + + // 打开GPIO芯片 + chip = gpiod_chip_open_by_label("GPIOF"); + if (!chip) { + perror("打开GPIO芯片失败"); + return 1; + } + + // 获取GPIO线 + line_key1 = gpiod_chip_get_line(chip, GPIO_LINE_KEY1); + line_key2 = gpiod_chip_get_line(chip, GPIO_LINE_KEY2); + line_key3 = gpiod_chip_get_line(chip, GPIO_LINE_KEY3); + if (!line_key1 || !line_key2 || !line_key3) { + perror("获取GPIO线失败"); + gpiod_chip_close(chip); + return 1; + } + + // 将GPIO线设置为输入模式 + if (gpiod_line_request_input(line_key1, "key1") || + gpiod_line_request_input(line_key2, "key2") || + gpiod_line_request_input(line_key3, "key3")) { + perror("请求将GPIO线设置为输入模式失败"); + gpiod_chip_close(chip); + return 1; + } + + // 获取初始的GPIO线值 + last_value_key1 = gpiod_line_get_value(line_key1); + last_value_key2 = gpiod_line_get_value(line_key2); + last_value_key3 = gpiod_line_get_value(line_key3); + + // 无限循环检测GPIO线值的变化 + while (1) { + // 获取当前的GPIO线值 + value_key1 = gpiod_line_get_value(line_key1); + value_key2 = gpiod_line_get_value(line_key2); + value_key3 = gpiod_line_get_value(line_key3); + + // 检测key1的变化 + if (value_key1 != last_value_key1) { + if (value_key1 == 0) { + printf("key1 pressed\n"); + // 启动record进程 + record_pid = fork(); + if (record_pid == 0) { + signal(SIGTERM, handle_sigterm); + start_recording("hw:0,1", "output.pcm", SND_PCM_FORMAT_S16_LE, 2, 44100); + exit(0); + } + } else { + if (record_pid > 0) { + stop_recording(); + kill(record_pid, SIGTERM); + waitpid(record_pid, NULL, 0); + record_pid = -1; + } + } + last_value_key1 = value_key1; + } + + // 检测key2的变化 + if (value_key2 != last_value_key2) { + if (value_key2 == 0) { + printf("key2 pressed\n"); + } else { + long volume = get_playback_volume("hw:0", "Analog"); + volume += 5; + set_playback_volume("hw:0", "Analog", volume); + printf("Volume increased to %ld\n", volume); + } + last_value_key2 = value_key2; + } + + // 检测key3的变化 + if (value_key3 != last_value_key3) { + if (value_key3 == 0) { + printf("key3 pressed\n"); + } else { + long volume = get_playback_volume("hw:0", "Analog"); + volume -= 5; + set_playback_volume("hw:0", "Analog", volume); + printf("Volume decreased to %ld\n", volume); + } + last_value_key3 = value_key3; + } + + // 延时100毫秒,防止检测过于频繁 + usleep(100000); + } + + // 关闭GPIO芯片 + gpiod_chip_close(chip); + return 0; +} diff --git a/play.c b/play.c new file mode 100644 index 0000000..8e3a05d --- /dev/null +++ b/play.c @@ -0,0 +1,149 @@ +#include +#include +#include +#include // 用于处理错误码 + +//开始播放 +snd_pcm_t* play_start(const char* name, + snd_pcm_format_t format, + unsigned int channel, + unsigned int rate, + snd_pcm_uframes_t* period) +{ + snd_pcm_t *playback; // PCM设备句柄 + snd_pcm_hw_params_t *params; // PCM硬件参数 + int err; // 用于存储错误码 + int dir; + + // 打开PCM设备用于回放 + if ((err = snd_pcm_open(&playback, name, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { + fprintf(stderr, "Error opening PCM device %s: %s\n", name, snd_strerror(err)); + return NULL; + } + + // 分配参数对象,并用默认值填充 + snd_pcm_hw_params_alloca(¶ms); + snd_pcm_hw_params_any(playback, params); + + // 设置参数 + // 设置访问类型:交错模式 + if ((err = snd_pcm_hw_params_set_access(playback, params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { + fprintf(stderr, "Error setting access: %s\n", snd_strerror(err)); + snd_pcm_close(playback); + return NULL; + } + // 设置数据格式:16位小端 + if ((err = snd_pcm_hw_params_set_format(playback, params, format)) < 0) { + fprintf(stderr, "Error setting format: %s\n", snd_strerror(err)); + snd_pcm_close(playback); + return NULL; + } + // 设置声道数:立体声 + if ((err = snd_pcm_hw_params_set_channels(playback, params, channel)) < 0) { + fprintf(stderr, "Error setting channels: %s\n", snd_strerror(err)); + snd_pcm_close(playback); + return NULL; + } + // 设置采样率 + if ((err = snd_pcm_hw_params_set_rate_near(playback, params, &rate, &dir)) < 0) { + fprintf(stderr, "Error setting rate: %s\n", snd_strerror(err)); + snd_pcm_close(playback); + return NULL; + } + + printf("sample rate: %d Hz\n", rate); + + if ((err = snd_pcm_hw_params_set_period_size_near(playback, params, period, &dir)) < 0) { + fprintf(stderr, "Error setting period size: %s\n", snd_strerror(err)); + snd_pcm_close(playback); + return NULL; + } + + // 设置硬件参数 + if ((err = snd_pcm_hw_params(playback, params)) < 0) { + fprintf(stderr, "Error setting HW params: %s\n", snd_strerror(err)); + snd_pcm_close(playback); + return NULL; + } + + // 获取周期大小 + snd_pcm_hw_params_get_period_size(params, period, &dir); + + return playback; +} + +//停止播放 +void play_stop(snd_pcm_t* playback) +{ + snd_pcm_drain(playback); // 排空PCM设备 + snd_pcm_close(playback); // 关闭PCM设备 +} + +int main() +{ + snd_pcm_t *playback; // PCM设备句柄 + snd_pcm_uframes_t period = 999; // 每个周期的帧数 + char *buffer; // 缓冲区,用于存储从文件中读取的音频数据 + FILE *pcm_file; // 输出PCM文件 + int err; // 用于存储错误码 + + playback = play_start("hw:0,0", SND_PCM_FORMAT_S16_LE, 2, 44100, &period); + if (!playback) + { + return 1; + } + + printf("period: %d frames\n", period); + + buffer = (char *) malloc(snd_pcm_frames_to_bytes(playback, period)); // 分配缓冲区 + if (!buffer) { + perror("malloc"); + play_stop(playback); + return 1; + } + + // 打开输出文件 + pcm_file = fopen("output.pcm", "rb"); + if (!pcm_file) { + perror("Error opening output file"); + free(buffer); // 释放缓冲区 + play_stop(playback); // 关闭PCM设备 + return 1; + } + + // 录制数据 + printf("Playing... Press Ctrl+C to stop.\n"); + while (1) { + size_t bytes = fread(buffer, 1, snd_pcm_frames_to_bytes(playback, period), pcm_file); + if (bytes == 0) + { + if (ferror(pcm_file)) + { + perror("fread"); + continue; + } + + if (feof(pcm_file)) + { + break; + } + } + + snd_pcm_sframes_t frames = snd_pcm_writei(playback, buffer, snd_pcm_bytes_to_frames(playback, bytes)); + if (frames < 0) + { + fprintf(stderr, "Error from write: %s\n", snd_strerror(frames)); + if (frames == -EPIPE) + { + snd_pcm_prepare(playback); + } + } + } + + // 清理资源 + free(buffer); // 释放缓冲区 + fclose(pcm_file); // 关闭文件 + play_stop(playback); + + return 0; +} diff --git a/record.c b/record.c new file mode 100644 index 0000000..398e1b5 --- /dev/null +++ b/record.c @@ -0,0 +1,116 @@ +#include "record.h" + +snd_pcm_t *capture = NULL; +char *buffer = NULL; +FILE *pcm_file = NULL; +volatile sig_atomic_t keep_recording = 1; + +void handle_sigterm(int sig) { + keep_recording = 0; +} + +// 开始录音 +snd_pcm_t* record_start(const char* name, snd_pcm_format_t format, unsigned int channel, unsigned int rate, snd_pcm_uframes_t* period) { + snd_pcm_t *capture; + snd_pcm_hw_params_t *params; + int err; + int dir; + + if ((err = snd_pcm_open(&capture, name, SND_PCM_STREAM_CAPTURE, 0)) < 0) { + fprintf(stderr, "Error opening PCM device %s: %s\n", name, snd_strerror(err)); + return NULL; + } + + snd_pcm_hw_params_alloca(¶ms); + snd_pcm_hw_params_any(capture, params); + + if ((err = snd_pcm_hw_params_set_access(capture, params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { + fprintf(stderr, "Error setting access: %s\n", snd_strerror(err)); + snd_pcm_close(capture); + return NULL; + } + if ((err = snd_pcm_hw_params_set_format(capture, params, format)) < 0) { + fprintf(stderr, "Error setting format: %s\n", snd_strerror(err)); + snd_pcm_close(capture); + return NULL; + } + if ((err = snd_pcm_hw_params_set_channels(capture, params, channel)) < 0) { + fprintf(stderr, "Error setting channels: %s\n", snd_strerror(err)); + snd_pcm_close(capture); + return NULL; + } + if ((err = snd_pcm_hw_params_set_rate_near(capture, params, &rate, &dir)) < 0) { + fprintf(stderr, "Error setting rate: %s\n", snd_strerror(err)); + snd_pcm_close(capture); + return NULL; + } + printf("sample rate: %d Hz\n", rate); + + if ((err = snd_pcm_hw_params(capture, params)) < 0) { + fprintf(stderr, "Error setting HW params: %s\n", snd_strerror(err)); + snd_pcm_close(capture); + return NULL; + } + + snd_pcm_hw_params_get_period_size(params, period, &dir); + + return capture; +} + +void start_recording(const char *pcm_device, const char *output_file, snd_pcm_format_t format, unsigned int channels, unsigned int rate) { + snd_pcm_uframes_t period; + int err; + + capture = record_start(pcm_device, format, channels, rate, &period); + if (!capture) { + exit(1); + } + + printf("period: %lu frames\n", period); + + buffer = (char *) malloc(snd_pcm_frames_to_bytes(capture, period)); + if (!buffer) { + perror("malloc"); + snd_pcm_close(capture); + exit(1); + } + + pcm_file = fopen(output_file, "wb"); + if (!pcm_file) { + perror("Error opening output file"); + free(buffer); + snd_pcm_close(capture); + exit(1); + } + + printf("Recording... Release the button to stop.\n"); + while (keep_recording) { + snd_pcm_sframes_t frames = snd_pcm_readi(capture, buffer, period); + if (frames < 0) { + fprintf(stderr, "Error from read: %s\n", snd_strerror(frames)); + if (frames == -EPIPE) { + snd_pcm_prepare(capture); + } + } + + fwrite(buffer, snd_pcm_frames_to_bytes(capture, frames), 1, pcm_file); + } +} + +void stop_recording() { + // 清理资源 + if (buffer) { + free(buffer); + buffer = NULL; + } + if (pcm_file) { + fclose(pcm_file); + pcm_file = NULL; + } + if (capture) { + snd_pcm_drain(capture); + snd_pcm_close(capture); + capture = NULL; + } + printf("Recording stopped.\n"); +} diff --git a/record.h b/record.h new file mode 100644 index 0000000..7d732c8 --- /dev/null +++ b/record.h @@ -0,0 +1,20 @@ +#ifndef RECORD_H +#define RECORD_H + +#include +#include +#include +#include +#include + +extern snd_pcm_t *capture; +extern char *buffer; +extern FILE *pcm_file; +extern volatile sig_atomic_t keep_recording; + +void handle_sigterm(int sig); +snd_pcm_t* record_start(const char* name, snd_pcm_format_t format, unsigned int channel, unsigned int rate, snd_pcm_uframes_t* period); +void start_recording(const char *pcm_device, const char *output_file, snd_pcm_format_t format, unsigned int channels, unsigned int rate); +void stop_recording(); + +#endif // RECORD_H -- Gitee