您尚未登录。

楼主 # 2022-08-19 14:40:15

gaocangjian
会员
注册时间: 2022-08-08
已发帖子: 32
积分: 39

播放WAV文件报错! (Broken pipe)

在模仿全志例程的时候遇到了一个问题,具体如下:

我可以用aplay播放wav文件,但是在工程中无法播放,每次执行到
       err = snd_pcm_writei(playback_handle, buf , BUF_LEN/4);
会弹出错误 write to audio interface failed (Broken pipe) "损坏的管道?"

播放WAV的函数是抄的全志洗衣机那个例子,
网上很多帖子都有提到过类似这段代码,但是没有多余什么讲解 sad。自己看大概是读出wav文件的wave_header_t,
根据结构成员配置打开的pcm设备,最后snd_pcm_writei实现播放,而我的错误就是该函数返回的。
具体如下:

int play_wav_music(const char * partname)
{
	int i;	int err;
	wav;
	int headwavcntp;
	snd_pcm_t *playback_handle;	snd_pcm_hw_params_t *hw_params;
	FILE *fp = NULL;
	snd_pcm_format_t pcm_fmt;
	char buf[BUF_LEN];

	/* 打开 wav 文件 */
	fprintf(stderr, "open file : %s\n", partname);
	fp = fopen(partname, "r");
	if (fp == NULL) {
		fprintf(stderr, "open test pcm file err\n");
		return -1;
	}

	/* 读文件头结构体 */
	headwavcntp = fread(&wav, 1, sizeof(wave_header_t), fp);
	if(headwavcntp != sizeof(wave_header_t)){
		printf("read wav file head error!\n");
		fclose(fp);
		return -1;
	}

	/* 	打印 读到的文件信息 */
	printf("read wav file head success \n");
	printf("bps = %d\n", wav.uBitsPerSample);
	printf("chn = %d\n", wav.uChannels);
	printf("fs = %d\n", wav.uSampleRate);
	
	/* 判断 是8bit还是16bit */
	if(wav.uBitsPerSample == 8){
		pcm_fmt = SND_PCM_FORMAT_S8;
	}else if(wav.uBitsPerSample == 16){
		pcm_fmt = SND_PCM_FORMAT_S16_LE;
	}else{
		printf("uBitsPerSample not support!\n");
		fclose(fp);
		return -1;
	}
		if((err = snd_pcm_open(&playback_handle,  "default", SND_PCM_STREAM_PLAYBACK, 0)) < 0){
			fprintf(stderr, "cannot open audio device record.pcm (%s)\n",  snd_strerror(err));
			fclose(fp);
			return -1;
		}
		if((err = snd_pcm_hw_params_malloc(&hw_params)) < 0){
			fprintf(stderr, "cannot allocate hardware parameter structure (%s)\n",snd_strerror(err));
			goto play_wav_out;
		}
		if((err = snd_pcm_hw_params_any(playback_handle, hw_params)) < 0){
			fprintf(stderr, "cannot initialize hardware parameter structure (%s)\n", snd_strerror(err));
			goto play_wav_out;
		}
		if((err = snd_pcm_hw_params_set_access(playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0){
			fprintf(stderr, "cannot allocate hardware parameter structure (%s)\n",snd_strerror(err));
			goto play_wav_out;
		}
		if((err = snd_pcm_hw_params_set_format(playback_handle, hw_params, pcm_fmt)) < 0){
			fprintf(stderr, "cannot allocate hardware parameter structure (%s)\n",snd_strerror(err));
			goto play_wav_out;
		}
		if((err = snd_pcm_hw_params_set_rate(playback_handle, hw_params, wav.uSampleRate, 0)) < 0){
			fprintf(stderr , "cannot set sample rate (%s)\n", snd_strerror(err));
			goto play_wav_out;
		}
		if((err = snd_pcm_hw_params_set_channels(playback_handle, hw_params, wav.uChannels)) <0){
			fprintf(stderr, "cannot set channel count (%s)\n", snd_strerror(err));
			goto play_wav_out;
		}
		if((err = snd_pcm_hw_params(playback_handle, hw_params)) < 0){
			fprintf(stderr, "cannot set parameters (%s)\n", snd_strerror(err));
			goto play_wav_out;
		}
		snd_pcm_hw_params_free(hw_params);

		while (!feof(fp)) {
			err = fread(buf, 1, BUF_LEN, fp);
			if (err < 0){
				fprintf(stderr, "read pcm from file err\n");
				goto play_wav_out;
			}
			err = snd_pcm_writei(playback_handle, buf , BUF_LEN/4);
			if (err < 0){
				fprintf(stderr, "write to audio interface failed (%s)\n", /* 我就是在这里弹出的错误 */
				snd_strerror(err));
				goto play_wav_out;
			}
		}

play_wav_out:
	fprintf(stderr, "close file\n");
	fclose(fp);
	fprintf(stderr, "close dev\n");
	snd_pcm_close(playback_handle);	fprintf(stderr, "ok\n");
	return 0;
}

/proc/asound/devies 内容如下:

root@TinaLinux:/proc/asound# cat devices
  0: [ 0]   : control
 16: [ 0- 0]: digital audio playback
 24: [ 0- 0]: digital audio capture
 33:        : timer

设备目录下也正常:

root@TinaLinux:/dev/snd# ls -l
crw-rw----    1 root     root      116,   0 Jan  1 00:00 controlC0
crw-rw----    1 root     root      116,  24 Jan  1 00:00 pcmC0D0c
crw-rw----    1 root     root      116,  16 Jan  1 00:00 pcmC0D0p
crw-rw----    1 root     root      116,  33 Jan  1 00:00 timer

也把snd_pcm_open()函数中的设备名 改变过 现在使用的是默认值 ''default",
改过 "hw:0,0" "plughw:0,0" "default:0" 输出错误信息是一样的。

完整的错误信息是这样的/*怕出不必要的问题,没有播放SD卡上的文件,这个开机.wav在启动过程中 通过壳命令播放过*/:

open file : /etc/kaiji.wav  
read wav file head success 
bps = 16
chn = 1
fs = 32000
write to audio interface failed (Broken pipe)
close file
close dev

现在无从下爪,大佬们帮看下应该怎么处理,或者给个思路也好。为去读aplay的源码看看,2000多行,估计问题比较大! hmm

把报错部分的摘出来:

while (!feof(fp)) {
	err = fread(buf, 1, BUF_LEN, fp);
	if (err < 0){
		fprintf(stderr, "read pcm from file err\n");
				goto play_wav_out;
	}
	err = snd_pcm_writei(playback_handle, buf , BUF_LEN/4);
	if (err < 0){
		fprintf(stderr, "write to audio interface failed (%s)\n", /*就在这里输出的 str = "Broken pipe"*/
		snd_strerror(err));
		goto play_wav_out;
	}
}

离线

楼主 #2 2022-08-19 16:02:59

gaocangjian
会员
注册时间: 2022-08-08
已发帖子: 32
积分: 39

Re: 播放WAV文件报错! (Broken pipe)

哇酷小二 说:

有没有试过 tinyplay 呢?

---------------------------------------------------------------------
可用哦,一切正常!~~~tiny那几个测试程序都可以用,启动时的开机声音就是tinyplay播放的。
aplay也正常工作。

离线

楼主 #3 2022-08-19 16:08:21

gaocangjian
会员
注册时间: 2022-08-08
已发帖子: 32
积分: 39

Re: 播放WAV文件报错! (Broken pipe)

现在怀疑 在调用int play_wav_music(const char * partname) 这个函数前是不是应该有一定的初始化动作。但是,在全志提供的例子中,并没有。并且他的例子在我的板子上也没有声音。。。
怀疑要么需要初始化,或者是某个配置文件没有配置。。。。
现在在看aplay和tinyplay的代码,tinyplay相对代码少一点。但是他是通过函数指针把snd_pcm_......相关函数重新包了一次的。
aplay因为牵扯到命令行解释啥的..代码很多。。先看看tinyplay吧。

离线

楼主 #5 2022-08-19 16:19:21

gaocangjian
会员
注册时间: 2022-08-08
已发帖子: 32
积分: 39

Re: 播放WAV文件报错! (Broken pipe)

@哇酷小二
--------------------------------------
额,这还真的可以试试。

离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn