首页 > 编程语言 >c++ 计算mp3时长

c++ 计算mp3时长

时间:2024-07-13 16:30:25浏览次数:12  
标签:layer return int frame c++ char mp3 size 时长

#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>


using namespace std;


struct ID3V2
{
	char tag[3];
	char version;
	char subVersion;
	char flag;
	char size[4];
};

const int bitrateIndex[16][5] = {
	{
		0,
		0,
		0,
		0,
		0
	},
	{
		32,
		32,
		32,
		32,
		8
	},
	{
		64,
		48,
		40,
		48,
		16
	},
	{
		96,
		56,
		48,
		56,
		24
	},
	{
		128,
		64,
		56,
		64,
		32
	},
	{
		160,
		80,
		64,
		80,
		40
	},
	{
		192,
		96,
		80,
		96,
		48
	},
	{
		224,
		112,
		96,
		112,
		56
	},
	{
		256,
		128,
		112,
		128,
		64
	},
	{
		288,
		160,
		128,
		144,
		80
	},
	{
		320,
		192,
		160,
		160,
		96
	},
	{
		352,
		224,
		192,
		176,
		112
	},
	{
		384,
		256,
		224,
		192,
		128
	},
	{
		416,
		320,
		256,
		224,
		144
	},
	{
		448,
		384,
		320,
		256,
		160
	},
	{
		0,
		0,
		0,
		0,
		0
	}
};

const int sampleRate[4][3] = {
	{
		44100,
		22050,
		11025
	},
	{
		48000,
		24000,
		12000
	},
	{
		32000,
		16000,
		8000
	},
	{
		0,
		0,
		0
	}
};

class AudioFile {
public:
	AudioFile(char* file) {
		this->ifs.open(file, ios::in);

		if (!this->ifs.is_open()) {
			cout << "cannot open file" << endl;
			return;
		}
	}
	void read(void* p, int size) {
		this->filePos += size;
		ifs.read((char*)p, size);
	}
	void seek(long pos) {
		this->filePos = pos;
		ifs.clear();
		ifs.seekg(pos);
	}
	int pos() {
		return this->filePos;
	}
	bool eof() {
		return this->ifs.eof();
	}
	~AudioFile()
	{
		ifs.close();
	}
private:
	ifstream ifs;
	int filePos = 0;
};

class Analyser {
private:
	double sampleCount = 0;
	int HEADER_SIZE = 4;
	void* frame;
public:
	Analyser() {
		//this->frame = malloc(this->HEADER_SIZE);
		this->frame = new char[this->HEADER_SIZE];
	}
	int getVersion(unsigned short info) {
		return (info & 0xF00) >> 11;
	}
	int getLayer(unsigned short info) {
		switch ((info & 0x600) >> 9) {
		case 1:
			return 3;
		case 2:
			return 2;
		case 3:
			return 1;
		}
	}
	int parseSize(char size[4]) {
		int a = size[0] * 2097152;
		int b = size[1] * 16384;
		int c = size[2] * 128;
		int d = size[3];
		return a + b + c + d;
	}
	int getSampleRate(int frequency) {
		return (frequency & 0x0F) >> 2;
	}
	int translateSampleRate(int version, int y) {
		return sampleRate[y][version - 1];
	}
	int getBitrate(unsigned char bit) {
		return (bit & 0xF0) >> 4;
	}
	int translateBitrate(int version, int layer, int y) {
		int x = -1;
		switch (version)
		{
		case 1:
			x = layer - 1;
			break;
		case 2:
			if (layer == 1)
				x = 3;
			else
				x = 4;
		default:
			printf("cannot determine bitrate x !");
			return -1;
		}

		return bitrateIndex[y][x];
	}
	int getPadding(char rawPad) {
		return (rawPad & 0x0F) >> 1;
	}
	int calFrameSize(int layer, int bitRate, int sampleRate, int padding) {
		if (layer == 1)
			return (12000 * bitRate / sampleRate + padding) * 4;

		return 144000 * bitRate / sampleRate + padding;
	}
	int getDuration() {
		return this->sampleCount;
	}
	bool calDuration(AudioFile* af) {
		af->read(this->frame, this->HEADER_SIZE);
		if (this->frame == NULL)
			throw "NULL pointer exception!";

		auto info = *(unsigned short*)(this->frame);
		if ((info & 0xF0FF) != 0xF0FF)return false;
		if (af->eof()) return false;

		auto version = this->getVersion(info);
		auto layer = this->getLayer(info);

		auto bi = this->translateBitrate(version, layer, this->getBitrate(*(char*)((char*)this->frame + 2)));
		auto pad = this->getPadding(*((char*)this->frame + 2));
		auto sample = this->translateSampleRate(version, this->getSampleRate(*((char*)this->frame + 2)));
		auto frameSize = this->calFrameSize(layer, bi, sample, pad);

		this->sampleCount += (layer == 1 ? 384 : 1152) / (double)sample;

		auto next = af->pos() + frameSize - this->HEADER_SIZE;

		//cout << this->sampleCount << " --> " << sample << " -->" << " next: " << next << endl;

		af->seek(next);
        
		return true;
	}

};


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

	const char* au = { "C:/Users/djatm/Music/all out of love.mp3" };

	AudioFile* af = new AudioFile((char*)au);

	int id3Size = sizeof(ID3V2);

	ID3V2* id3v2 = (ID3V2*)malloc(id3Size);
	af->read(id3v2, id3Size);
	if (id3v2 == NULL) {
		return;
	}
	if (id3v2->tag[0] != 'I' || id3v2->tag[1] != 'D' || id3v2->tag[2] != '3') {
		delete af;
		cout << "cannot parse tag!" << endl;
		return;
	}

	Analyser* an = new Analyser();

	int headerEnd = an->parseSize(id3v2->size) + 10;

	af->seek(headerEnd);

	while (an->calDuration(af));

	cout << "duration: " << an->getDuration() << endl;

	delete af;

	return 0;
}

如有不足还望指出!!!

标签:layer,return,int,frame,c++,char,mp3,size,时长
From: https://www.cnblogs.com/laremehpe/p/18300281

相关文章

  • 【C++编程】数组、函数、结构体、指针、类
    数组:存储一个固定大小的相同类型元素的顺序集合声明、初始化:typearrayName[size0][size1]...={{value00,value01,...},{value10,value11,...},...};intmy_array[2][3]={{1,2,3},{4,5,6}};访问数组元素:arrayName[index0][index1]...;intget_eleme......
  • 【洛谷】P5728 【深基5.例5】旗鼓相当的对手——C++
    本题感想:本题主要是应该避免重复比较,以a,b,c,d为例,我们假设先a不动,依次比较d,c,b或者b,c,d,然后假设b不动,依次比较c,d,最后假设c不动,比较d,这样这道题就差不多解决了#include<iostream>#include<cmath>usingnamespacestd;intmain(){inta[1010][3],s[1010]={0......
  • 全栈物联网项目:结合 C/C++、Python、Node.js 和 React 开发智能温控系统(附代码示例)
    1.项目概述本文详细介绍了一个基于STM32微控制器和AWSIoT云平台的智能温控器项目。该项目旨在实现远程温度监控和控制,具有以下主要特点:使用STM32F103微控制器作为主控芯片,负责数据采集、处理和控制逻辑采用DHT22数字温湿度传感器,精确采集环境温湿度数据通过ESP8266WiF......
  • C++数组 字符串
    是什么:相同类型元素的集合写法:intexample[3]//数组在声明大小时必须为常数数组名example是个指针类型如int*ptr=example;数组索引的工作原理:example[3]//从首地址位置偏移数组类型大小(int是4字节)乘索引值(4*3)个字节//从当前字节位置往后读四个字节;可能出现的错误:ex......
  • 解决Microsoft Visual C++ runtime package找不到问题
    使用了Dism++进行电脑清理,不小心选择了下面两个内容:尤其是第二个packagecache绝对不能清空,否则不知道哪个软件就不能运行了,报MicrosoftvisualC++runtime问题.然后再安装各个版本MicrosoftvisualC++redis仍会报同样的问题,死循环了.网上有各种解决方案,有......
  • C++中的可见性 指针 笔记
    含义:谁能看到他们谁能调用?谁能使用?可见性的修饰符:private含义:只有其所在的类可以访问,被修饰的变量但是friend关键字可以让类或者函数成为朋友(友元)可以在别处访问私有成员protected含义:所在的类和层次结构中的所有子类可以访问这些符号例子:classprintable{prot......
  • 【C++】内存分区模型 - 内存四区
    补充内容:c++编译过程:编译预处理、编译优化、汇编、链接①编译预处理:处理以“#”开头的指令,产生“.i”文件;【如头文件、define宏定义等】②编译优化:将源码".cpp"文件翻译成“.s”汇编代码;【如词法语法语义分析,代码优化等】③汇编:将汇编代码“.s”翻译成机器指令“.o”或".ob......
  • 南外c++集训枚举题:关灯
    根据标题可知这道题一定是一道枚举题这道题考虑使用dfs,处理特殊处理第一层,每次加答案时选最优值。给出代码:点击查看代码#include<bits/stdc++.h>usingnamespacestd;intn,m;charmat[20][110];intdfs(intcnt,intpos,inttmp)//cnt:楼层pos:哪里的楼梯tmp走到楼梯......
  • 2024年06月CCF-GESP编程能力等级认证C++编程三级真题解析
    本文收录于专栏《C++等级认证CCF-GESP真题解析》,专栏总目录:点这里。订阅后可阅读专栏内所有文章。一、单选题(每题2分,共30分)第1题小杨父母带他到某培训机构给他报名参加CCF组织的GESP认证考试的第1级,那他可以选择的认证语言有()种。A.1B.2C.3D.4答案:C第2......
  • 嵌入式C++、Qt/QML和MQTT:智能工厂设备监控系统的全流程介绍(附代码示例)
    1.项目概述本项目旨在开发一套先进的智能工厂设备监控系统,集成嵌入式技术、工业通信协议和人机界面等多项技术,实现对工厂设备的全方位实时监控、高精度数据采集和智能化分析。该系统将显著提升工厂设备的运行效率,大幅降低维护成本,并为管理层决策提供可靠的数据支持。主要功......