我想为我的项目实现特定的功能,包括在后台连续播放sample-default.wav
并在某些特定条件匹配时播放sample-specific.wav
文件。我真正想要的是,当sample-specific.wav
文件运行时,sample-default.wav
文件的容量变为0(或者简单地,我想在sample-default.wav
运行时使sample-specific.wav
文件静音)
我正在尝试使用alsa-library
for c来实现此功能。我几乎尝试了所有方法来实现这一目标,但似乎没有任何效果。
我正在尝试使用dmix
的{{1}}插件添加两个虚拟声音设备,而将alsa
用作系统声音。我搜索了google,发现需要编辑default
文件来创建其他声音设备。
我添加了两个声音设备,分别名为/etc/asound.conf
和notification
。我当前的sample-sound
文件看起来类似于以下文件:-
/etc/asound.conf
这对于pcm.notification {
type dmix
ipc_key 1024
slave {
pcm "hw:1,0"
}
}
ctl.notification {
type hw
card 2
}
pcm.sample-sound {
type dmix
ipc_key 1025
slave {
pcm "hw:1,0"
}
}
ctl.sample-sound {
type hw
card 3
}
来说是完美的,即当我通过以下命令使用aplay
播放sample-default.wav
文件时:-
aplay
它可以工作,但是当我尝试运行以下代码以在aplay -D plug:notification sample-default.wav
设备上使用sample-default.wav
来播放alsa library
时:-
notification
它可以成功编译,但是会引发运行时错误:-
#include <stdio.h>
#include <stdlib.h>
#include <alsa/asoundlib.h>
#include <pthread.h>
void default_sound (char * str) {
snd_pcm_t *handle;
snd_pcm_hw_params_t *params;
snd_pcm_uframes_t frames;
/* Open PCM device for playback */
int status = snd_pcm_open(&handle, "notification", SND_PCM_STREAM_PLAYBACK, 0);
if (status < 0) {
printf("Unable to open pcm deveice%s\n", snd_strerror(status));
return;
}
/* Allocate a hardware parameter obejct */
snd_pcm_hw_params_alloca(¶ms);
/* Fill it with default values */
snd_pcm_hw_params_any(handle, params);
/* Set the desired hardware parameters */
/* Interleaved mode */
snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
/* Signed 16-bit little-endian format */
snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
/* Single Channel (mono) */
snd_pcm_hw_params_set_channels(handle, params, 1);
/* sampling rate */
unsigned int sample_rate = 16000;
int dir;
snd_pcm_hw_params_set_rate_near(handle, params, &sample_rate, &dir);
/* set period size to 32 frames */
frames = 32;
snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);
/* Write the parameters to the driver */
status = snd_pcm_hw_params(handle, params);
if(status < 0) {
printf("Unable to set hw params: %s\n", snd_strerror(status));
return;
}
/* Use a buffer large enough to hold one period */
snd_pcm_hw_params_get_period_size(params, &frames, &dir);
int size = frames * 2;
char *buffer = (char *)malloc(size);
int readfd = open("sample-call.wav", O_RDONLY);
if(readfd < 0) {
printf("Error in opening wav file\n");
exit(1);
}
int readval;
while(readval = read(readfd, buffer, size) > 0) {
status = snd_pcm_writei(handle, buffer, frames);
if(status == -EPIPE) {
printf("underrun occured\n");
snd_pcm_prepare(handle);
}
else if(status < 0) {
printf("Error from writei: %s\n", snd_strerror(status));
}
}
snd_pcm_drain(handle);
snd_pcm_close(handle);
free(buffer);
}
int main() {
pthread_t pthread_id;
int status = pthread_create(&pthread_id, NULL, default_sound, "running");
if (status != 0) {
printf("Error in creating thread\n");
}
pthread_join(pthread_id, NULL);
return 0;
}
我不知道上面的代码出了什么问题。
如果上面的代码工作正常,那么我将在两个设备(8211 segmentation fault (core dumped) ./play-multiple-sound
和notification
)上播放两个声音文件,并使用我拥有的sample-sound
库控制这些设备的音量已经实施。
过去几周我一直在努力实现这一目标,但似乎没有一种解决方案适合我,因此请帮我解决这个问题,如果您知道更好的方法,请提出建议。