基于Linux下的开源wavplay播放器

tinyalsa工具使用——tinycap,tinyplay,tinymix 1,tinycap 2,tinyplay 3,tinymix及分析 1,tinycap hello_world:/ # tinycap Usage: tinycap file.wav [-D card] [-d device] [-c channels] [-r ... 阅读详情
***************************************************************************************************************************
作者:EasyWave                                                                                 时间:2013.02.05

类别:Linux 应用之wavplay播放器                                                      声明:转载,请保留链接

注意:如有错误,欢迎指正。这些是我学习的日志文章......

***************************************************************************************************************************

       因为客户需要用到wav文件来测试播放我们的平台,而客户的应用程序,用在我们的平台上,会有一些问题,所以,我需要从网络上找开源的wav的播放器,终于在网络上找到了wavplay播放器.虽然是基于OSS架构的wav的播放器,不过没有关系,自己还是先来熟悉这个开源的代码吧, 最新的版本是2.0版本,源码的下载地址如下:

http://sourceforge.net/projects/wavplay/?source=dlp 节后抽个时间将其移植到ARM平台上去,这个小软件不管是用来测试,还是用来移植到实际的项目,对我们来说,都是很好的一个参考源码。你说是不?

一:wav文件格式 [引用网络,已做过修改]

      wave文件作为多媒体中使用的声波文件格式之一,它是以RIFF格式为标准的。RIFF是英文Resource Interchange File Format的缩写,每个WAVE文件的头四个字节便是“RIFF”,WAVE文件是由若干个Chunk组成的。按照在文件中的出现位置包括:RIFF WAVE Chunk, Format Chunk, Fact Chunk(可选), Data Chunk。如下图所示:

 

        其中除了Fact Chunk外,其他三个Chunk是必须的。每个Chunk有各自的ID,位于Chunk最开始位置,作为标示,而且均为4个字节。并且紧跟在ID后面的是Chunk大小(去除ID和Size所占的字节数后剩下的其他字节数目),4个字节表示,低字节表示数值低位,高字节表示数值高位。下面具体介绍各个Chunk内容。注意: 所有数值表示均为低字节表示低位,高字节表示高位。

1):RIFF WAVE Chunk

以'FIFF'作为标示,然后紧跟着为size字段,该size是整个wav文件大小减去ID和Size所占用的字节数,即FileLen - 8 = Size。然后是Type字段,为'WAVE',表示是wav文件。

2):Format Chunk

以'fmt '作为标示。一般情况下Size为16,此时最后附加信息没有;如果为18,则最后多了2个字节的附加信息。主要由一些软件制成的wav格式中含有该2个字节的附加信息。

3):Fact Chunk

Fact Chunk是可选字段,一般当wav文件由某些软件转化而成,则包含该Chunk。

4):Data Chunk

Data Chunk是真正保存wav数据的地方,以'data'作为该Chunk的标示。然后是数据的大小。紧接着就是wav数据。根据Format Chunk中的声道数以及采样bit数,wav数据的bit位置可以分成以下几种形式:

二:wav文件格式解码

具体的代码,可以仔细研究wavplay的源码中的wavfile.c和wavfile.h文件,这两个文件主要是对wav文件格式进行解码,具体的部分代码如下:

/* $Id: wavfile.c,v 1.3 2009/11/30 15:02:31 ve3wwg Exp $
 * Copyright: wavfile.c (c) Erik de Castro Lopo  erikd@zip.com.au
 *
 * wavfile.c - Functions for reading and writing MS-Windoze .WAV files.
 *
 * This  program is free software; you can redistribute it and/or modify it
 * under the  terms  of  the GNU General Public License as published by the
 * Free Software Foundation.
 * 
 * This  program  is  distributed  in  the hope that it will be useful, but
 * WITHOUT   ANY   WARRANTY;   without   even  the   implied   warranty  of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
 * Public License for more details (licensed by file COPYING or GPLv*).
 * 
 * This code was originally written to manipulate Windoze .WAV files
 * under i386 Linux (erikd@zip.com.au).
 *
 * ve3wwg@gmail.com
 */	
static const char rcsid[] = "$Id: wavfile.c,v 1.3 2009/11/30 15:02:31 ve3wwg Exp $";

#include  	<stdio.h>
#include	<errno.h>
#include	<sys/types.h>
#include	<unistd.h>
#include  	<string.h>

#include "wavplay.h"

#define		BUFFERSIZE   		1024
#define		PCM_WAVE_FORMAT   	1

#define		TRUE			1
#define		FALSE			0

typedef  struct
{	u_long     dwSize ;
	u_short    wFormatTag ;
	u_short    wChannels ;
	u_long     dwSamplesPerSec ;
	u_long     dwAvgBytesPerSec ;
	u_short    wBlockAlign ;
	u_short    wBitsPerSample ;
} WAVEFORMAT ;

typedef  struct
{	char    	RiffID [4] ;
	u_long    	RiffSize ;
	char    	WaveID [4] ;
	char    	FmtID  [4] ;
	u_long    	FmtSize ;
	u_short   	wFormatTag ;
	u_short   	nChannels ;
	u_long		nSamplesPerSec ;
	u_long		nAvgBytesPerSec ;
	u_short		nBlockAlign ;
	u_short		wBitsPerSample ;
	char		DataID [4] ;
	u_long		nDataBytes ;
} WAVE_HEADER ;

/*=================================================================================================*/

char*  findchunk (char* s1, char* s2, size_t n) ;

/*=================================================================================================*/


static  WAVE_HEADER  waveheader =
{	{ 'R', 'I', 'F', 'F' },
		0,
	{ 'W', 'A', 'V', 'E' },
	{ 'f', 'm', 't', ' ' },
		16,								/* FmtSize*/
		PCM_WAVE_FORMAT,						/* wFormatTag*/
		0,								/* nChannels*/
		0,
		0,
		0,
		0,
	{ 'd', 'a', 't', 'a' },
		0
} ; /* waveheader*/

static ErrFunc v_erf;				/* wwg: Error reporting function */

/*
 * Error reporting function for this source module:
 */
static void
err(const char *format,...) {
	va_list ap;

	if ( v_erf == NULL )
		return;				/* Only report error if we have function */
	va_start(ap,format);
	v_erf(format,ap);			/* Use caller's supplied function */
	va_end(ap);
}

int  WaveWriteHeader (int wavefile, int channels, u_long samplerate, int sampbits, u_long samples, ErrFunc erf)
{ 	u_long		databytes ;
	u_short		blockalign ;

	v_erf = erf;				/* wwg: Set error reporting function */

	if ( wavefile < 0 ) {
		err("Invalid file descriptor");
		return WW_BADOUTPUTFILE ;
	}

	sampbits   = (sampbits == 16) ? 16 : 8 ;

	blockalign = ((sampbits == 16) ? 2 : 1) * channels ;
	databytes  = samples * (u_long) blockalign ;

	waveheader.RiffSize 	   = sizeof (WAVE_HEADER) + databytes - 8 ;
	waveheader.wFormatTag      = PCM_WAVE_FORMAT ;
	waveheader.nChannels       = channels ;
	waveheader.nSamplesPerSec  = samplerate ;
	waveheader.nAvgBytesPerSec = samplerate * (u_long) blockalign ;
	waveheader.nBlockAlign     = blockalign ;
	waveheader.wBitsPerSample  = sampbits ;
	waveheader.nDataBytes      = databytes;

	if (write (wavefile, &waveheader, sizeof (WAVE_HEADER)) != sizeof (WAVE_HEADER)) {
		err("%s",strerror(errno));	/* wwg: report the error */
		return  WW_BADWRITEHEADER ;
	}

  return 0 ;
} ; /* WaveWriteHeader*/

int  WaveReadHeader  (int wavefile, int* channels, u_long* samplerate, int* samplebits, u_long* samples, u_long* datastart,ErrFunc erf)
{	static  WAVEFORMAT  waveformat ;
	static	char   buffer [ BUFFERSIZE ] ;		/* Function is not reentrant.*/
	char*   ptr ;
	u_long  databytes ;

	v_erf = erf;					/* wwg: Set error reporting function */

	if (lseek (wavefile, 0L, SEEK_SET)) {
		err("%s",strerror(errno));		/* wwg: Report error */
		return  WR_BADSEEK ;
	}

	read (wavefile, buffer, BUFFERSIZE) ;

	if (findchunk (buffer, "RIFF", BUFFERSIZE) != buffer) {
		err("Bad format: Cannot find RIFF file marker");	/* wwg: Report error */
		return  WR_BADRIFF ;
	}

	if (! findchunk (buffer, "WAVE", BUFFERSIZE)) {
		err("Bad format: Cannot find WAVE file marker");	/* wwg: report error */
		return  WR_BADWAVE ;
	}

	ptr = findchunk (buffer, "fmt ", BUFFERSIZE) ;

	if (! ptr) {
		err("Bad format: Cannot find 'fmt' file marker");	/* wwg: report error */
		return  WR_BADFORMAT ;
	}

	ptr += 4 ;	/* Move past "fmt ".*/
	memcpy (&waveformat, ptr, sizeof (WAVEFORMAT)) ;

	if (waveformat.dwSize < (sizeof (WAVEFORMAT) - sizeof (u_long))) {
		err("Bad format: Bad fmt size");			/* wwg: report error */
		return  WR_BADFORMATSIZE ;
	}

	if (waveformat.wFormatTag != PCM_WAVE_FORMAT) {
		err("Only supports PCM wave format");			/* wwg: report error */
		return  WR_NOTPCMFORMAT ;
	}

	ptr = findchunk (buffer, "data", BUFFERSIZE) ;

	if (! ptr) {
		err("Bad format: unable to find 'data' file marker");	/* wwg: report error */
		return  WR_NODATACHUNK ;
	}

	ptr += 4 ;	/* Move past "data".*/
	memcpy (&databytes, ptr, sizeof (u_long)) ;

	/* Everything is now cool, so fill in output data.*/

	*channels   = waveformat.wChannels ;
	*samplerate = waveformat.dwSamplesPerSec ;
	*samplebits = waveformat.wBitsPerSample ;
	*samples    = databytes / waveformat.wBlockAlign ;
	
	*datastart  = ((u_long) (ptr + 4)) - ((u_long) (&(buffer[0]))) ;

	if (waveformat.dwSamplesPerSec != waveformat.dwAvgBytesPerSec / waveformat.wBlockAlign) {
		err("Bad file format");			/* wwg: report error */
		return  WR_BADFORMATDATA ;
	}

	if (waveformat.dwSamplesPerSec != waveformat.dwAvgBytesPerSec / waveformat.wChannels / ((waveformat.wBitsPerSample == 16) ? 2 : 1)) {
		err("Bad file format");			/* wwg: report error */
		return  WR_BADFORMATDATA ;
	}

  return  0 ;
} ; /* WaveReadHeader*/

/*===========================================================================================*/

#if 0
char*  WaveFileError (int  errno)
{	switch (errno)
	{	case	WW_BADOUTPUTFILE	: return "Bad output file.\n" ;
		case	WW_BADWRITEHEADER 	: return "Not able to write WAV header.\n" ;
		
		case	WR_BADALLOC			: return "Not able to allocate memory.\n" ;
		case	WR_BADSEEK        	: return "fseek failed.\n" ;
		case	WR_BADRIFF        	: return "Not able to find 'RIFF' file marker.\n" ;
		case	WR_BADWAVE        	: return "Not able to find 'WAVE' file marker.\n" ;
		case	WR_BADFORMAT      	: return "Not able to find 'fmt ' file marker.\n" ;
		case	WR_BADFORMATSIZE  	: return "Format size incorrect.\n" ;
		case	WR_NOTPCMFORMAT		: return "Not PCM format WAV file.\n" ;
		case	WR_NODATACHUNK		: return "Not able to find 'data' file marker.\n" ;
		case	WR_BADFORMATDATA	: return "Format data questionable.\n" ;
		default           			:  return "No error\n" ;
	} ;
	return	NULL ;	
} ; /* WaveFileError*/
#endif
/*===========================================================================================*/

char* findchunk  (char* pstart, char* fourcc, size_t n)
{	char	*pend ;
	int		k, test ;

	pend = pstart + n ;

	while (pstart < pend)
	{ 	if (*pstart == *fourcc)       /* found match for first char*/
		{	test = TRUE ;
			for (k = 1 ; fourcc [k] != 0 ; k++)
				test = (test ? ( pstart [k] == fourcc [k] ) : FALSE) ;
			if (test)
				return  pstart ;
			} ; /* if*/
		pstart ++ ;
		} ; /* while lpstart*/

	return  NULL ;
} ; /* findchuck*/

/* $Source: /cvsroot/wavplay/code/wavfile.c,v $ */


具体的解码分析,俺就不分析了。不是很难的代码,至于其它部分的代码,就不贴出来了,可以自己去下载代码来分析,我下载的是1.5B版本,最新的是2.0版本。

Linux ALSA声卡驱动之五:移动设备中的ALSA(ASoC) 整理自: https://blog.csdn.net/DroidPhone/article/details/7165482 https://www.cnblogs.com/blogs-of-lxl/p/6538769.html 1. ASoC--ALSA System on Chip:   建立在标准ALSA驱动层上,为了更好地支持嵌入式处理器和移动设备 中的音频Codec的一套软件体系。在ASoc出现之前,内核对于SoC中的音频已经有部分的支持,不过会有 一些局限性:... 阅读详情

相关推荐

tinyalsa tinyplay播放音频报错

tinyplay 使用usb声卡设备播放音频文件时候报错,这个文件用aplay播放是正常的。原因是音频文件格式和声卡支持的格式不一致。这里只需要把wav文件格式改为 48k 双通道,就行了。

JCYAO_的博客 1720

arecord、aplay 实现录音和播放(linux)

arecord、aplay 实现录音和播放(linux) ​ 1.查看录音设备 $ arecord -l 2.录音 $ arecord -D hw:2,0 -d 10 -r 48000 -f S16_LE test.wav 参数解析 -D 指定了录音设备,2,0 是card 2 device 0的意思 -d 指定录音的时长,单位时秒(如果不加,可以使用Ctrl + C结束录音) -f 指定录音格式,通过上面的信息知道只支持 cd cdr dat -r 指定了采样率,单位时Hz -t 指定生成的文件格

休息一下接着来的博客 3179

深入解析wav音乐播放器源码

本文还有配套的精品资源,点击获取 简介:wav格式音乐播放器源码解析 1. wav格式基础与音频解码流程 音频技术是数字多媒体领域中的基础,而WAV格式作为早期PC上最常见的音频格式,它的重要性不言而喻。在这一章节中,我们从WAV格式的基础讲起,逐步深入到音频解码的全过程,旨在为读者提供一套清晰的音频解码技术框架。 1.1 wav格式概述 WAV...

weixin_31419153的博客 971

全志V3s学习记录(11)音频、视频使用总结

文章目录一、buildroot编译文件系统测试装好吗?开发板上测试mplayer测试aplay测试arecord测试tinyalsa测试alsamixer二、mplay播放视频三、播放wav、MP3音频四、录音 一、buildroot编译文件系统 测试装好吗? 开发板上测试mplayer # mplayer MPlayer 1.3.0-4.9.4 (C) 2000-2016 MPlayer Team Usage: mplayer [options] [url|path/]filename Basic

似水流年 4213

MATLAB WAV 文件播放器:从读取到播放的完整指南

本文还有配套的精品资源,点击获取 简介:MATLAB 是一款强大的音频处理工具,本指南将详细介绍如何使用 MATLAB 开发一个 WAV 文件播放器。从 WAV 文件格式的理解到音频数据的读取、时域波形的绘制、频谱分析和播放,我们将逐步讲解每个步骤。此外,我们还提供了包含源代码和示例文件的压缩包,供你实践和探索。通过本指南,你将掌握 MATLAB 处理音频数据的强大功能,为...

weixin_36364707的博客 2115

WAVE音频(WAV文件)播放器

WAVE音频(WAV文件)播放器,用于播放.WAV文件,本程序使用VC++6.0 C++ MFC编写,有需要的人可以参考。

基于linux的mplay的mp3程序,基于Linux下的开源wavplay播放器

因为客户需要用到wav文件来测试播放我们的平台,而客户的应用程序,用在我们的平台上,会有一些问题,所以,我需要从网络上找开源的wav的播放器,终于在网络上找到了wavplay播放器.虽然是基于OSS架构的wav的播放器,不过没有关系,自己还是先来熟悉这个开源的代码吧, 最新的版本是2.0版本,源码的下载地址如下:http://sourceforge.net/projects/wavplay/?so...

weixin_33314238的博客 447

简单的linux下wav播放器

在Linux下对wav格式的文件进行了音频的解码并将数据丢到声卡中播放,实现了播放,暂停,快进,快退,音量调节和上下曲切换的功能。使用多线程技术,并有控制台界面,代码量小简单易懂,方便初学者学习。要将wav格式音乐和本代码放在同一目录下。

linux tinyalsa 1.1.1 tinyplay 出错解决

3308调试audio 使用tinyplay pcm open 出错 # tinyplay /userdata/rec1_16k.wav -D 1 -c 1 -r 16000 -p 100 failed to open for pcm 1,0 但是使用aplay却没有问题 # aplay /userdata/rec1_16k.wav -c 1 -r 16000 -D hw:1,0 Playing WAVE '/userdata/rec1_16k.wav' : Signed 16 bit Little.

u013463707的专栏 2223

这是一个wavplay播放器

这是一款linux使用播放mp3的软件,测试音频驱动使用的。

wavplay-开源

该项目是用于播放“ wav”文件Linux wavplay命令行实用程序。

matlab wavplay怎么用,MATLAB中,wavplay与sound两个命令有什么区别呢?

区别wavplay():播放wav声音文件。当然,也可以把处理后的wav文件保存后再用其它工具播放。sound函数的输入参量是音频数据向量、采样频率和转换位数。2.处理流程分析和处理音频信号 首先要对声音信号进行采集MATLAB的数据采集工具箱提供了一整套命令和函数,通过调用这些函数和命令,可直接控制声卡进行数据采Windows自带的录音机程序也可驱动声卡来采集语音信号 并能保存为WAV...

weixin_32073375的博客 3061

matlab开发-wavplay

matlab开发-wavplay。wavplay.m使用matlab 5调用仅在win32下运行的dll。

wavplay控件应用之SigmaStudio

WavPlay插件应用与音频播放

zhui-meng6的博客 779

android+音乐节拍检测,科学网—音乐节拍跟踪或音乐节拍检测软件,LilyBeats alpha - 石自强的博文...

我们设计并实现了一种用于实时跟踪音乐节拍的软件。该软件可以用于智能灯方案提供商,为其提供灯光随音乐变化的核心解决方案。首先给出软件的下载链接:或者音乐节拍是乐曲中表示固定单位时值和强弱规律的组织形式,亦称拍子。它有两个特性:周期性和连续性。节拍周期性表现为节拍结构,是乐曲中周期性出现的节奏序列。节拍连续性表现为音乐的平均速度,其单位为bpm(beat per minute每分钟音乐节拍的个数)。音...

weixin_39571403的博客 1401

Windows环境下Elasticsearch与JDK版本兼容性实战指南

本文详细解析了Windows环境下Elasticsearch与JDK版本的兼容性问题,提供了从版本匹配检查到安装部署的完整实战指南。重点介绍了Elasticsearch 8.x需JDK 17+等关键版本对应关系,并分享多版本JDK共存方案及性能优化技巧,帮助开发者高效避坑。

weixin_29250403的博客 421

未定义函数或变量 'wavplay'。原因:2014a已经移除函数

官网找到说明,已经移除该函数 https://ww2.mathworks.cn/matlabcentral/fileexchange/71798-wavplay?s_tid=srchtitle 用 sound 可以听到声音 应该可以下载文件继续使用这一函数 ...

Never Give Up 6042

ESP32之 ESP-IDF + Clion 开发环境搭建(二)—— Linux版

本文介绍了 Linux 下,使用Clion IDE 用官方 ESP-IDF 开发包进行 ESP32 开发的环境搭建

Augtons 的博客 6098

wav音频文件格式解析【个人笔记】(自用)

目录 1. WAV格式 2. WAV的二进制格式解析 2.1 WAV文件格式 2.2 C语言解析wav文件 3. WAV文件语音数据的组织结构 4. 总结 回到顶部 1. WAV格式 wav是微软开发的一种音频文件格式,注意,wav文件格式是无损音频文件格式,相对于其他音频格式文件数据是没有经过压缩的,通常文件也相对比较大些。、 支持多种音频数字,取样频率和声道,标准格式化的WAV文件和CD格式一样,也是44.1K的取样频率,16位量化数字,因此在声音文件质量和CD相差无几!

qq_41607336的博客 9000

VS2022配置Qt6

VS2022配置QT教程

Life is a struggle ! 6361

(11-3-03)多任务与元强化学习:综合实战:基于元强化学习的迷宫导航系统(3)

本文介绍了策略网络隐空间可视化的实现方法及其在强化学习中的应用。通过设计visualize_latent_space函数,使用t-SNE算法将高维隐空间特征降维至二维进行可视化,直观展示策略网络在不同任务中的特征分布。文章详细阐述了实现流程:状态收集、t-SNE降维和可视化绘图,并提供了完整的Python代码示例。实验结果表明,该方法能有效分析策略网络的学习过程与适应能力,为优化模型提供重要依据。同时,文章还介绍了主程序的完整流程,包括环境初始化、元智能体训练与评估、学习策略比较等环节,最后对实验结果进行可

码农三叔 1041

linux 播放wav文件

from : http://blog.chinaunix.net/uid-9672747-id-3309602.html #include #include #include #include #include #include #include #include typedef struct _WAVEFILE_HEADER//波形文件头结构体 { char Ch

Adrian 博客 6261

OpenClaw(Clawdbot/Moltbot)如何正确的配置浏览器,实现对浏览器的自动化操作功能(浏览器状态为running:false怎么办)

OpenClaw(Clawdbot/Moltbot)浏览器自动化功能无效?🤖 本文详细介绍如何解决这个问题🔧,让你的OpenClaw(Clawdbot/Moltbot)真正具备"睁眼看世界"的能力,支持网页搜索、点击操作和截图等功能 ✅

XiaoqiangClub的博客 8110
上一篇: 基于android2.3.5系统:Andriod与Linux交叉编译工具[二]
下一篇: 基于Linux开源VOIP系统LinPhone[三]
wang-bob
博客等级 码龄20年 356粉丝 112原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值