4. 音频测试源播放到声卡
任务目标
构建一条最小GStreamer管道,使用audiotestsrc生成测试音频信号,经autoaudiosink输出到系统默认声卡,并通过volume元素实时调节音量。最终通过命令行参数控制音量和波形类型,验证声卡出声且音量可调。
环境依赖
- GStreamer核心库及基础插件:
gstreamer-1.0、gst-plugins-base、gst-plugins-good(audiotestsrc位于good插件包) - ALSA或PulseAudio系统声卡驱动(
autoaudiosink自动探测) - 安装命令(Debian/Ubuntu):
sudo apt install gstreamer1.0-tools gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-alsa
完整实现
以下C程序构建管道:audiotestsrc → volume → autoaudiosink。通过命令行参数指定波形类型(sine/square/saw)和音量(0.0~1.0),并支持键盘交互实时调节音量。
// play_test_tone.c
#include <gst/gst.h>
#include <stdio.h>
#include <string.h>
static GstElement *volume = NULL;
static gboolean bus_call(GstBus *bus, GstMessage *msg, gpointer data) {
switch (GST_MESSAGE_TYPE(msg)) {
case GST_MESSAGE_ERROR: {
GError *err = NULL;
gchar *debug = NULL;
gst_message_parse_error(msg, &err, &debug);
g_printerr("Error: %s\n", err->message);
g_error_free(err);
g_free(debug);
g_main_loop_quit((GMainLoop *)data);
break;
}
case GST_MESSAGE_EOS:
g_main_loop_quit((GMainLoop *)data);
break;
default:
break;
}
return TRUE;
}
static gboolean keyboard_cb(GIOChannel *src, GIOCondition cond, gpointer data) {
gchar buf[16];
gsize len;
g_io_channel_read_line(src, &buf, &len, NULL, NULL);
gdouble vol = 0.0;
if (sscanf(buf, "%lf", &vol) == 1) {
vol = CLAMP(vol, 0.0, 1.0);
g_object_set(volume, "volume", vol, NULL);
g_print("音量已设为: %.2f\n", vol);
} else {
g_print("输入无效,请输入0.0~1.0之间的数值\n");
}
return TRUE;
}
int main(int argc, char *argv[]) {
gst_init(&argc, &argv);
// 解析参数: 波形类型(默认sine) 音量(默认0.5)
const gchar *wave = "sine";
gdouble vol = 0.5;
if (argc > 1) wave = argv[1];
if (argc > 2) vol = atof(argv[2]);
vol = CLAMP(vol, 0.0, 1.0);
GMainLoop *loop = g_main_loop_new(NULL, FALSE);
// 创建元素
GstElement *pipeline = gst_pipeline_new("test-pipeline");
GstElement *src = gst_element_factory_make("audiotestsrc", "src");
volume = gst_element_factory_make("volume", "volume");
GstElement *sink = gst_element_factory_make("autoaudiosink", "sink");
if (!pipeline || !src || !volume || !sink) {
g_printerr("元素创建失败,请检查插件是否安装\n");
return -1;
}
// 设置属性
g_object_set(src, "wave", wave, "freq", 440, NULL);
g_object_set(volume, "volume", vol, NULL);
// 组装管道
gst_bin_add_many(GST_BIN(pipeline), src, volume, sink, NULL);
if (!gst_element_link_many(src, volume, sink, NULL)) {
g_printerr("管道连接失败\n");
gst_object_unref(pipeline);
return -1;
}
// 总线监听
GstBus *bus = gst_element_get_bus(pipeline);
gst_bus_add_watch(bus, bus_call, loop);
gst_object_unref(bus);
// 键盘监听(stdin)
GIOChannel *io = g_io_channel_unix_new(fileno(stdin));
g_io_add_watch(io, G_IO_IN, keyboard_cb, NULL);
g_print("波形: %s, 初始音量: %.2f\n", wave, vol);
g_print("输入0.0~1.0数值实时调节音量,Ctrl+C退出\n");
gst_element_set_state(pipeline, GST_STATE_PLAYING);
g_main_loop_run(loop);
// 清理
g_io_channel_unref(io);
gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(pipeline);
g_main_loop_unref(loop);
return 0;
}
编译与运行
# 编译
gcc play_test_tone.c -o play_test_tone $(pkg-config --cflags --libs gstreamer-1.0)
# 运行(默认正弦波440Hz,音量0.5)
./play_test_tone
# 指定方波,音量0.8
./play_test_tone square 0.8
# 指定锯齿波,音量0.2
./play_test_tone saw 0.2
验证方法
- 出声验证:运行程序后应听到对应波形的声音(正弦波为单音,方波为更尖锐的同频音,锯齿波为明亮音色)。若无声,检查系统音量及声卡设备:
aplay -l确认声卡存在,pactl list sinks确认默认输出。 - 音量调节验证:程序运行后,在终端输入
0.0应静音,输入1.0为最大音量,输入0.3等中间值应听到音量明显变化。输入非法字符(如abc)应提示无效。 - 波形切换验证:分别以
sine、square、saw参数运行,应听到音色差异。若波形参数拼写错误,程序会报错退出(GStreamer属性设置失败)。
常见问题
- 无声输出:先执行
gst-launch-1.0 audiotestsrc num-buffers=100 ! autoaudiosink测试基础管道。若仍无声,检查系统音频服务(PulseAudio/Alsa)是否正常运行。 - 音量调节无效果:确认输入的是0~1之间的浮点数(如
0.5),整数1会被解析为1.0。若输入2会被自动钳位到1.0。 - 编译错误:确认已安装
libgstreamer1.0-dev开发包,且pkg-config能正确返回GStreamer编译参数。