简述

在 Qt 之 WAV文件解析 中给出了WAV文件属性的计算,具体包括文件大小、音频时长、比特率等属性,这里我们再次验证一下这些属性值的计算 。

在计算之前,我们要知道一下wav文件中的三个参数 采样频率、音频通道数、每次采样得到的样本位数 ,这三个参数用来表示声音,同时决定了wav文件的音质,大小。下面简单介绍一下这三个参数。

采样频率

指每秒钟取得声音样本的次数。采样的过程就是抽取某点的频率值,很显然,在一秒中内抽取的点越多,获取得频率信息更丰富,为了复原波形,采样频率越高,声音的质量也就越好,声音的还原也就越真实,但同时它占的资源比较多。由于人耳的分辨率很有限,太高的频率并不能分辨出来。22050 的采样频率是常用的,44100已是CD音质,超过48000或96000的采样对人耳已经没有意义。

音频通道数

声音的通道的数目。常见的单声道和立体声(双声道),现在发展到了四声环绕(四声道)和5.1声道。如果是双声道,采样就是双份的,文件也差不多要大一倍。

每次采样得到的样本位数

采样位数可以理解为声卡处理声音的解析度。这个数值越大,解析度就越高,录制和回放的声音就越真实。 采样位数也叫采样大小或量化位数。它是用来衡量声音波动变化的一个参数,也就是声卡的分辨率或可以理解为声卡处理声音的解析度。它的数值越大,分辨率也就越高,录制和回放的声音就越真实。


计算公式

波形数据传输速率(每秒平均字节数) = 采样频率 × 音频通道数 × 每次采样得到的样本位数 / 8

比特率(kbs) = 波形数据传输速率 × 8 / 1000

WAV文件所占大小(字节) = 波形数据传输速率 × 音频文件时长

音频文件时长(秒) = WAV文件所占容量 / 波形数据传输速率

关于以上几个属性我们可以右击wav文件查看文件属性看到这几个值。见下图。

从上述两幅图中我们可以知道这个wav文件的总大小为6947字节比特率为88kbs时间为0s,是不是很诧异,为什么这里时间为0呢?实际上windows这里只是按整数显示音频时长,那么真正的时间怎么计算呢?

这里我们已经知道了wav文件的大小,看上述公式,我们还要知道波形数据传输速率波形数据传输速率而又是由采样频率 、 音频通道数 、 每次采样得到的样本位数 来决定,那么这些参数怎么获取到呢?

看过Qt 之 解析wav文件的头信息(详细分析、对比不同wav文件的数据)这篇文章就应该知道如何去解析一个wav文件,并获取所有的文件头信息,如果不知道文件头信息是什么,请参考Qt 之 WAV文件解析。

好了,既然对于一个wav文件,我们能够获取到所有的头信息,那么接下来就来验证以上公式计算的结果。

上图为wav文件的头信息数据,我们可以看到波形数据传输速率nBytesPerSecond)的值为11025,文件总大小为6947字节,音频数据大小为6903字节,文件头信息为44字节。

音频文件时长(秒) = WAV文件所占容量 / 波形数据传输速率 = 6903 / 11025 = 0.626122 s

比特率(kbs) = 波形数据传输速率 × 8 / 1000 = 11025 × 8 / 1000 = 88 kbs

这里为什么精确到小数点后六位,其实也是为了与程序记录的时间做对比,这里也要特别注意:实际上 WAV文件所占容量 为 WAV文件中 音频数据大小 ,而并非WAV文件总大小 , 但是 文件头信息所占字节非常小,所以就算是将这块大小加上进行计算,对最后的计算结果影响也非常小。下面我们就用QAudioOutput 来播放这个wav文件,同时记录播放时间 。

代码之路

// 播放wav文件
void MyAudioInput::onPlay()
{sourceFile.setFileName(WAV_RECORD_FILENAME);sourceFile.open(QIODevice::ReadOnly);// 设置播放音频格式;QAudioFormat format;format.setSampleRate(11025);format.setChannelCount(1);format.setSampleSize(8);format.setCodec("audio/pcm");// wav文件即按照这个字节存储顺序保存数据;format.setByteOrder(QAudioFormat::LittleEndian);format.setSampleType(QAudioFormat::UnSignedInt);QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());//qDebug() << info.supportedCodecs();if (!info.isFormatSupported(format)){qWarning() << "Raw audio format not supported by backend, cannot play audio.";return;}m_audioOutput = new QAudioOutput(format, this);connect(m_audioOutput, SIGNAL(stateChanged(QAudio::State)), this, SLOT(handleStateChanged(QAudio::State)));m_audioOutput->start(&sourceFile);m_time.start();
}// 播放状态更新;
void MyAudioInput::handleStateChanged(QAudio::State state)
{switch (state) {case QAudio::IdleState:// Finished playing (no more data)qDebug() << "elapsedUSecs:" << m_audioOutput->elapsedUSecs();qDebug() << "time : " << m_time.elapsed();onStopPlay();break;case QAudio::StoppedState:// Stopped for other reasonsif (m_audioOutput->error() != QAudio::NoError) {// Error handling}break;default:break;}
}
// 关闭播放;
void MyAudioInput::onStopPlay()
{if (m_audioOutput != NULL){m_audioOutput->stop();sourceFile.close();delete m_audioOutput;m_audioOutput = NULL;}
}

代码中我分别用了QAudioOutput类的elapsedUSecs方法和QTime类的elapsed方法来记录wav文件音频时长。以下是两个方法的介绍。


elapsedUSecs() 输出为微妙
elapsed() 输出为毫秒

通过记录得到以下数据:

m_audioOutput->elapsedUSecs() : 636000
m_time.elapsed() : 635

m_audioOutput->elapsedUSecs() : 639000
m_time.elapsed() : 638

m_audioOutput->elapsedUSecs() : 642000
m_time.elapsed() : 641

m_audioOutput->elapsedUSecs() : 639000
m_time.elapsed() : 639

而我们的计算结果为: 0.626122 s = 626.122 ms = 626122 us , 显然程序中获取的时间大于计算的时间,这也很好理解,因为程序的运行需要消耗一定的时间,所以记录的时间存在很小的误差(误差范围大致在0.009s ~ 0.016s),如果电脑性能更好这个误差就越小。

特别注意

这里我们用QAudioOutput类来计算wav文件时长,这里我们要给QAudioOutput类对象设置播放格式QAudioFormat ,设置的格式必须与解析出来的文件头信息中的 采样频率、音频通道数、每次采样得到的样本位数、编码格式等严格保持一致,否则不仅播放出来的声音不清楚,记录的音频时长也有问题


通过以上发现,我们的计算公式是成立的。基本上我们可以在wav文件头信息中获取wav文件的全部信息,唯一就是wav**文件时长**需要通过文件头中的信息进行计算得到。所以如果我们想要做一个播放器,在播放器上显示一个wav文件的时长,我们就需要先解析wav文件的头信息,通过计算得到文件时长。

更多参考

Qt 之 WAV文件解析

Qt之实现录音播放及raw(pcm)转wav格式

Qt 之 解析wav文件的头信息(详细分析、对比不同wav文件的数据)

Qt 之 WAV文件属性计算(比特率、文件大小、文件时长)相关推荐

  1. java 读取音频/视频 文件时长

    java 读取音频/视频 文件时长 支持mp3,mp4,mov,m4a,wav 格式文件 源码 https://github.com/opensourceteams/java-maven-projec ...

  2. 2021-09-10 java 读取音频/视频 文件时长

    java 读取音频/视频 文件时长 pom.xml <dependency><groupId>org</groupId><artifactId>jaud ...

  3. Android 录音文件有杂音,录音文件时长比实际时长长问题解决

    问题:在使用Android的AudioRecord进行录音时,录制生成的录音文件的时长比实际录制时间长,且录制的音频有一部分是有杂音或者没有声音的. 安卓出现录音问题还可以参考另一篇文章 Androi ...

  4. php获取音频的时长,PHP编程获取音频文件时长的方法【基于getid3类】

    本文实例讲述了PHP编程获取音频文件时长的方法.分享给大家供大家参考,具体如下: 问题: 昨天在新增论坛功能的时候,移动端显示音频文件需要知道是多长的音频: 具体解决方案如下: 首先就是数据库中增加保 ...

  5. java 获取音频文件时长

    需要导入jar包:jave 1.0.2 jar 如果是maven项目,在pom.xml文件中添加: <dependency><groupId>it.sauronsoftware ...

  6. NVT SDK 67X获取文件时长的一种方式

    NVT SDK 67X获取文件时长的一种方式 #define FILE_BUF_SIZE (64+1) static CHAR Video_FILE_BUF[FILE_BUF_SIZE] = {0}; ...

  7. M3U8文件格式说明及解决大量拼接ts文件时长不对问题

    M3U8 文件简介 m3u8 文件实质是一个播放列表(playlist),其可能是一个媒体播放列表(Media Playlist),或者是一个主列表(Master Playlist).但无论是哪种播放 ...

  8. Java 获取opus 音频文件时长

    当时为了获取时长花费好长时间,所以现在写出这文章以免后面有遇到该问题不止如何解决花费太长时间.话不多说,上代码 需要的依赖包有 <!-- https://mvnrepository.com/ar ...

  9. Python获取mp3音频文件时长方法汇总

    '''pymediainfo: pip3 install pymediainfo 版本:5.1.0不支持网络音频 ''' class pymediainfoTest():@classmethoddef ...

最新文章

  1. C语言单链表实现FCFS算法,数据结构与算法复习题(含答案).doc
  2. ASP.Net请求处理机制初步探索之旅 - Part 2 核心
  3. win10安装RabbitMQ
  4. 自考计算机成绩,自考成绩计算机中是什么意思?
  5. MySQL总结4_多表查询
  6. ZZULIOJ1026
  7. php批量打印页面,SETE批量打印
  8. 硬件工程师学习英语必备
  9. php页面增加js代码,php刷新当前页面_php js实现页面数据刷新的代码
  10. 以寡治众各个击破,超大文件分片上传之构建基于Vue.js3.0+Ant-desgin+Tornado6纯异步IO高效写入服务
  11. 网络1711班 C语言第七次作业批改总结
  12. linux scl,scl命令
  13. 用trace32分析内核死机
  14. vue中设置移动的盒子
  15. Mac电脑系统降级至10.15 Catalina(2020末代intel)
  16. Jabber 技 术 概 况
  17. 第一周------继续
  18. Ubuntu 16.04通过命令行连接Wi-Fi
  19. Pipe Comet
  20. 电话机器人源码和系统部署

热门文章

  1. 三年级计算机群鸭戏水教案导入,信息技术教案_群鸭戏水教学设计.docx
  2. 60名亿万富豪现身上海奢侈品展(组图)
  3. 关于窗口状态变化(显示、关闭、最小化、最大化等)的快捷键
  4. 好物推荐 | 新一代一线通投影仪方案
  5. php上传照片作品,你需要知道你的作品怎么拍才好看!一张火起来的照片是好的宣传...
  6. JavaScript 粘贴事件 paste
  7. HTML超链接的作用是什么,设置超链接有什么作用_什么是超链接?
  8. 学习WEB开发,从此我爱上了火狐的FireBug
  9. shell脚本——变量定义
  10. #微软学生开发者峰会