aplay 源码分析

ffmpeg -formats 
ffmpeg -sample_fmts
ffmpeg -i ../english14.mp3 -ar 44100 -ac 2 -sample_fmt s16 -f wav english14.wav
ffmpeg -i ../english14.mp3 -ar 44100 -ac 2 -sample_fmt s16 -f s16le english14.pcm

其中针对PCM个数的数据aplay正确的播放格式为:
aplay -r 48000 -c 2 english14.pcm 
下面都是错误的格式,声音不能正常识别
aplay -c 2 english14.pcm 
aplay -r 48000 english14.pcm 
aplay english14.pcm



/home/suiyuan626/share/alsa-utils-1.2.6/aplay/aplay -v -t raw -f S16_LE -r 48000 -c 2 english14.pcm

此处的aplay来自alsa-utils-1.2.6中源码编译
suiyuan626@ubuntu:~/share/ffmpeg/ffmpeg/doc/examples/data$ /home/suiyuan626/share/alsa-utils-1.2.6/aplay/aplay -v -f S16_LE -r 48000 -c 2 english14.pcm 
Playing raw data 'english14.pcm' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo
ALSA <-> PulseAudio PCM I/O Plugin
Its setup is:
  stream       : PLAYBACK
  access       : RW_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 16
  buffer_size  : 24000
  period_size  : 6000
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : GETTIMEOFDAY
  period_step  : 1
  avail_min    : 6000
  period_event : 0
  start_threshold  : 24000
  stop_threshold   : 24000
  silence_threshold: 0
  silence_size : 0
  boundary     : 6755399441055744000
^CAborted by signal Interrupt...
上面的命令中使用 -f -r -c 参数

参数 -f ,其主要配置的是 根据用户给定的参数格式找出PCM.h中定义的采样个事,采样率和通道数

		case 'f':
			force_sample_format = 1;
			if (strcasecmp(optarg, "cd") == 0 || strcasecmp(optarg, "cdr") == 0) {
				if (strcasecmp(optarg, "cdr") == 0)
					rhwparams.format = SND_PCM_FORMAT_S16_BE;
				else
					rhwparams.format = file_type == FORMAT_AU ? SND_PCM_FORMAT_S16_BE : SND_PCM_FORMAT_S16_LE;
				rhwparams.rate = 44100;
				rhwparams.channels = 2;
			} else if (strcasecmp(optarg, "dat") == 0) {
				rhwparams.format = file_type == FORMAT_AU ? SND_PCM_FORMAT_S16_BE : SND_PCM_FORMAT_S16_LE;
				rhwparams.rate = 48000;
				rhwparams.channels = 2;
			} else {
				rhwparams.format = snd_pcm_format_value(optarg);
				if (rhwparams.format == SND_PCM_FORMAT_UNKNOWN) {
					error(_("wrong extended format '%s'"), optarg);
					prg_exit(EXIT_FAILURE);
				}
			}
			break;

		case 'r':
			tmp = parse_long(optarg, &err);
			if (err < 0) {
				error(_("invalid rate argument '%s'"), optarg);
				return 1;
			}
			if (tmp < 1000)
				tmp *= 1000;
			rhwparams.rate = tmp;
			if (tmp < 2000 || tmp > 768000) {
				error(_("bad speed value %i"), tmp);
				return 1;
			}
			break

		case 'c':
			rhwparams.channels = parse_long(optarg, &err);
			if (err < 0) {
				error(_("invalid channels argument '%s'"), optarg);
				return 1;
			}
			if (rhwparams.channels < 1 || rhwparams.channels > 256) {
				error(_("value %i for channels is invalid"), rhwparams.channels);
				return 1;
			}
			break;

使用aplay要么record,要么播放文件,从stream的定义中可以知道
/** PCM stream (direction) */
typedef enum _snd_pcm_stream {
	/** Playback stream */
	SND_PCM_STREAM_PLAYBACK = 0,
	/** Capture stream */
	SND_PCM_STREAM_CAPTURE,
	SND_PCM_STREAM_LAST = SND_PCM_STREAM_CAPTURE
} snd_pcm_stream_t;



static void header(int rtype, char *name)
{
	if (!quiet_mode) {
		if (! name)
			name = (stream == SND_PCM_STREAM_PLAYBACK) ? "stdout" : "stdin";
		fprintf(stderr, "%s %s '%s' : ",
			(stream == SND_PCM_STREAM_PLAYBACK) ? _("Playing") : _("Recording"),
			gettext(fmt_rec_table[rtype].what),
			name);
		fprintf(stderr, "%s, ", snd_pcm_format_description(hwparams.format));
		fprintf(stderr, _("Rate %d Hz, "), hwparams.rate);
		if (hwparams.channels == 1)
			fprintf(stderr, _("Mono"));
		else if (hwparams.channels == 2)
			fprintf(stderr, _("Stereo"));
		else
			fprintf(stderr, _("Channels %i"), hwparams.channels);
		fprintf(stderr, "\n");
	}
}


有没有设置-I参数,故执行playback()函数进行播放,同时我们可以添加参数 -t 来执行播放文件类型

        	case 't':
			if (strcasecmp(optarg, "raw") == 0)
				file_type = FORMAT_RAW;
			else if (strcasecmp(optarg, "voc") == 0)
				file_type = FORMAT_VOC;
			else if (strcasecmp(optarg, "wav") == 0)
				file_type = FORMAT_WAVE;
			else if (strcasecmp(optarg, "au") == 0 || strcasecmp(optarg, "sparc") == 0)
				file_type = FORMAT_AU;
			else {
				error(_("unrecognized file format %s"), optarg);
				return 1;
			}
			break;

static void playback(char *name)
{
	int loaded = 0;

	pbrec_count = LLONG_MAX;
	fdcount = 0;
	if (!name || !strcmp(name, "-")) {
		fd = fileno(stdin);
		name = "stdin";
	} else {
		init_stdin();
		if ((fd = open(name, O_RDONLY, 0)) == -1) {
			perror(name);
			prg_exit(EXIT_FAILURE);
		}
	}
  printf("name:%s,file_type:%d\n",name,file_type);
	
	switch(file_type) {
	case FORMAT_AU:
		playback_au(name, &loaded);
		break;
	case FORMAT_VOC:
		playback_voc(name, &loaded);
		break;
	case FORMAT_WAVE:
		playback_wave(name, &loaded);
		break;
	case FORMAT_RAW:
		playback_raw(name, &loaded);
		break;
	default:
		/* parse the file header */
	 printf("file_type:%d\n",file_type);
		if (playback_au(name, &loaded) < 0 &&
		    playback_voc(name, &loaded) < 0 &&
		    playback_wave(name, &loaded) < 0)
			playback_raw(name, &loaded); /* should be raw data */
		break;
        }

	if (fd != fileno(stdin))
		close(fd);
}
其四个函数的额处理差异,主要是处理了文件头,比如播放的为PCM或者WAV格式的文件,而给定的参数-t au/voc 将不会进行播放。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

家有工程师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值