linux播放到设备,linux - 将字节流式传输到ALSA播放设备 - 堆栈内存溢出

在尝试通过 ALSA 将音频数据块写入播放设备时遇到问题,导致音频重复播放片段。代码示例展示了如何从 WAV 文件读取数据并在 ALSA 中进行播放,但当数据分块发送时,播放出现错误。较大的块大小导致较少的重复,而较小的块大小则增加重复频率。问题在于如何正确地流式传输音频数据以避免不期望的重复。
摘要由CSDN通过智能技术生成

我在使用libasound将随机字节写入ALSA播放设备时遇到了很多麻烦。 最终,我的目标是能够通过网络路由回放流并让它在远程设备上播放。

此问题中提供的代码将WAV文件读入内存并通过snd_pcm_writei将其写入驱动程序并且可以正常工作。 但是,这段代码与我正在尝试做的事情之间的关键区别在于我没有立即获得所有数据。 我希望在数据可用时对其进行流式处理。

调整上面的示例代码以满足我的需求,我最终得到了这样的结论:

#include

#include

#include

static snd_pcm_t *PlaybackHandle;

int init_playback(const char *device, int samplerate, int channels) {

int err;

printf("Init parameters: %s %d %d\n", device, samplerate, channels);

if((err = snd_pcm_open(&PlaybackHandle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {

printf("Can't open audio %s: %s\n", device, snd_strerror(err));

return -1;

}

if ((err = snd_pcm_set_params(PlaybackHandle, SND_PCM_FORMAT_S16, SND_PCM_ACCESS_RW_INTERLEAVED, channels, samplerate, 1, 500000)) < 0) {

printf("Can't set sound parameters: %s\n", snd_strerror(err));

return -1;

}

return 0;

}

int play_bytes(const void *bytes, int len) {

snd_pcm_uframes_t frames, count;

snd_pcm_uframes_t bufsize, period_size;

frames = 0;

count = 0;

snd_pcm_prepare(PlaybackHandle);

snd_pcm_get_params(PlaybackHandle, &bufsize, &period_size);

printf("bufsize=%d\n", (int) bufsize);

do {

int remaining = len - count;

int buflen = remaining < bufsize ? remaining : bufsize;

frames = snd_pcm_writei(PlaybackHandle, bytes + count, buflen);

// If an error, try to recover from it

if (frames == -EPIPE) {

printf("EPIPE\n");

snd_pcm_prepare(PlaybackHandle);

}

if (frames < 0) {

printf("Recovering\n");

frames = snd_pcm_recover(PlaybackHandle, frames, 0);

}

if (frames < 0)

{

printf("Error playing wave: %s\n", snd_strerror(frames));

break;

}

// Update our pointer

count += frames;

//printf("count=%d len=%d\n", (int)count, len);

} while (count < len);

// Wait for playback to completely finish

if (count == len)

snd_pcm_drain(PlaybackHandle);

return 0;

}

int close_playback() {

snd_pcm_close(PlaybackHandle);

return 0;

}

int main(int argc, char **argv) {

if(argc < 1) {

printf("Usage: %s \n", argv[0]);

return -1;

}

int fd;

unsigned long long len;

fd = open(argv[1], O_RDONLY);

// Find the length

len = lseek(fd, 0, SEEK_END);

// Skip the first 44 bytes (header)

lseek(fd, 44, SEEK_SET);

len -= 44;

char *data = malloc(len);

read(fd, data, len);

init_playback("default", 44100, 2);

play_bytes(data, len);

close_playback();

return 0;

}

这段代码可以用gcc playback.c -o playback -lasound 。 我正在使用的WAV文件可以在这里找到。

当我运行此代码片段时,我根据bufsize对输入数据进行分块,根据块大小,在播放中会重复播放音频片段。 较大的块大小产生的重复次数少于小块大小。 将此与音频的声音结合起来,我相信在每个块的末尾都会重复一个小片段。

我使用的参数是:

样本:44100

频道:2

为什么一次性发送整个WAV文件工作,而发送它的块不起作用? 如何将音频数据块发送给驱动程序并使其正常播放?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值