IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> WAVE音乐格式解析(讲解加代码) -> 正文阅读

[嵌入式]WAVE音乐格式解析(讲解加代码)

之前一直想用单片机的adc播放音乐,一直有这个念头,网上找了很多的代码都很复杂,就想自己写一个兼容性高的,一眼就能看懂的WAVE解析的代码。以前基本功太差,现在感觉天清了雨晴了,我又觉得我行了!(狗头)

熬了两宿,对着两幅图把之前立的flag给补上了一部分。今天真的是写的太烦了,下边付了一份自己写的代码,代码目前的状态也就是能用吧!不稳定,bug超多,file safe啥的也没做,以后闲的蛋疼的时候在慢慢改。

代码先奉上,讲解日后心情好的时候补上。

?

?

?wave.c

#include <stdio.h>
#include<stdlib.h>
#include <string.h>
#include "wave.h"


void printf_c(void * data,unsigned char num)
{
	unsigned int i = 0;
	char name[num];
	memcpy(name,data,num);
	for(i=0;i<num;i++)
        printf("%c",name[i]);
    printf("\n");
}

int wave_asf(wave *ral_wave)
{
	unsigned int read_len = 0;
	unsigned int read_len_sizeof = 0;
	unsigned int ChunkID = 0;
	unsigned int local_offset = 0;
	unsigned char * extern_data;
	Wave_RIFF *baseframe;
	Wave_Base *miniframe;
	Wave_FMT *wavefmt;
	WAVE_DATA *wavedata;

	baseframe = (Wave_RIFF*)calloc(sizeof(Wave_RIFF),sizeof(char));
	miniframe = (Wave_Base*)calloc(sizeof(Wave_Base),sizeof(char));
	wavefmt   = (Wave_FMT*) calloc(sizeof(Wave_FMT),sizeof(char));
	wavedata  = (WAVE_DATA*)calloc(sizeof(WAVE_DATA),sizeof(char));

	read_len = fread(baseframe, 1, sizeof(Wave_RIFF), ral_wave->fp);
	if(read_len<sizeof(Wave_RIFF))
		printf("read file false!\n");
	local_offset = local_offset + read_len;

	bit8to32(&ChunkID,baseframe->ChunkID);

	if(ChunkID != RIFF_id)
		printf("file no wave!\n");

	while(TURE){

		memset(miniframe,0,sizeof(Wave_Base));
		ChunkID = 0;

		// 获取chunk_id
		read_len = fread(miniframe, 1, sizeof(Wave_Base), ral_wave->fp);
		if(read_len<sizeof(Wave_Base))
			printf("read file false!\n");
		local_offset = local_offset + read_len;
		bit8to32(&ChunkID,miniframe->ChunkID);

		switch(ChunkID){
		case fmt_id:
			read_len = fread(&read_len_sizeof, 1,sizeof(int) , ral_wave->fp);
			local_offset = local_offset + read_len;
			read_len = fread(wavefmt, 1,read_len_sizeof , ral_wave->fp);
			local_offset = local_offset + read_len;

			ral_wave->AudioFormate  = wavefmt->AudioFormate;
			ral_wave->BitePerSample = wavefmt->BitePerSample;
			ral_wave->BlockAilgn    = wavefmt->BlockAilgn;
			ral_wave->ByteRate      = wavefmt->ByteRate;
			ral_wave->NumChannels   = wavefmt->NumChannels;
			ral_wave->SampleRate    = wavefmt->SampleRate;
			ral_wave->ChunkSize     = read_len_sizeof;

			break;
		case data_id:
			read_len = fread(wavedata, 1,sizeof(WAVE_DATA) , ral_wave->fp);
			local_offset = local_offset + read_len;

			ral_wave->Subchunck2Size = wavedata->Subchunck2Size;

			goto out_while;

		default:
			read_len = fread(&read_len_sizeof, 1,sizeof(int) , ral_wave->fp);
			local_offset = local_offset + read_len;

			extern_data = (unsigned char*)calloc(read_len_sizeof,sizeof(char));

			read_len = fread(extern_data, 1,read_len_sizeof , ral_wave->fp);
			local_offset = local_offset + read_len;

			// 文件指针后移
			free(extern_data);

			break;
			}
	}
out_while:
	free(baseframe);
	free(miniframe);
	free(wavefmt);
	free(wavedata);
	ral_wave->DataOffset = 	local_offset;
	printf("ral_wave->DataOffset %x\n",ral_wave->DataOffset);
	printf("hello world~\n");
	return 0;
}

int channel_select(wave *ral_wave)
{
	switch(ral_wave->AudioFormate){
	case 1:
		return 1;

		break;
	case 2:
		// 不支持其他
		break;
	default:
		// 不支持其他
		break;
	}
	return 0;
}


// 声道,采样率分离
void channal_sbisample(wave *ral_wave)
{
	unsigned int read_len;
//	printf("ral_wave->ByteRate %d\n",ral_wave->ByteRate);
//	printf("ral_wave->BitePerSample %d\n",ral_wave->BitePerSample);
//	printf("ral_wave->BlockAilgn %d\n",ral_wave->BlockAilgn);
//	printf("ral_wave->NumChannels %d\n",ral_wave->NumChannels);
//	printf("ral_wave->SampleRate %d\n",ral_wave->SampleRate);

	// ByteRate == SampleRate * NumChannels * BitsPerSample/8
	// BlockAlign == NumChannels * BitsPerSample/8
	if(ral_wave->NumChannels == 1){
		switch(ral_wave->BitePerSample){
		case 8:
			printf("channel 1,8 bit\n");
			break;
		case 16:
			printf("channel 1,16 bit\n");
			break;
		default:
			printf("chanel 1 error!\n");
			break;
		}
	}
	else if(ral_wave->NumChannels == 2){
		switch(ral_wave->BitePerSample){
		case 8:
			printf("channel 2,8 bit\n");
			break;
		case 16:
			printf("channel 2,16 bit\n");
			c2b16 loca_c2b16;
			read_len = fread(&loca_c2b16, 1,sizeof(c2b16) , ral_wave->fp);
			printf("%d %d  read_len %d\n",sizeof(c2b16),sizeof(short),read_len);
			printf("loca_c2b16.L_c2b16 %x,loca_c2b16.R_c2b16 %x\n",loca_c2b16.L_c2b16,loca_c2b16.R_c2b16);
			ral_wave->DataOffset = ral_wave->DataOffset + read_len;
			printf("ral_wave->DataOffset %x\n",ral_wave->DataOffset);
			// 直接写道到DAC?
			break;
		default:

			printf("chanel 2 error!\n");
			break;
		}
	}
	else{
		printf("error!\n");
	}
}

int main(void)
{
	wave *do_wave;
	do_wave = (wave*)calloc(sizeof(wave),sizeof(char));
	do_wave->fp = fopen("D:\\wave\\test.wav", "r");
	wave_asf(do_wave);
	if(channel_select(do_wave)!=1)
		return 0;
	for(int i = 0;i<1000;i++)
	channal_sbisample(do_wave);
	fclose(do_wave->fp);
	free(do_wave);
    return 0;
}

?wave.h

/*
 * wave.h
 *
 *  Created on: 2021年7月22日
 *      Author: uida0349
 */

#ifndef WAVE_H_
#define WAVE_H_

#define TURE  1
#define FALSE 0

// 将四个8bit的拼接成32bit的
#define bit8to32(a,b)    {*a = b[3];*a = ((*a)<<8)|b[2];*a = ((*a)<<8)|b[1];*a = ((*a)<<8)|b[0];}

/**
 * 此处用于存储WAV的id信息
 * */
enum WAV_ID{
	RIFF_id = 0x46464952,
	fmt_id  = 0x20746d66,
	data_id = 0x61746164,
};

typedef struct wave_base{
	//char           ExtentsID[4];
	unsigned char  ChunkID[4];
}Wave_Base;
typedef struct wave_riff{
	//char           ExtentsID[4];
	unsigned char  ChunkID[4];
	unsigned int   ChunkSize;
	unsigned char  Format[4];
}Wave_RIFF;
typedef struct wave_fmt{
    // fmt Bolck
    unsigned short AudioFormate;
    unsigned short NumChannels;
    unsigned int   SampleRate;
    unsigned int   ByteRate;
    unsigned short BlockAilgn;
    unsigned short BitePerSample;
}Wave_FMT;
typedef struct wave_data{
	// data Block
	unsigned int   Subchunck2Size;
}WAVE_DATA;
typedef struct wave_Extents{
    char           ExtentsID[4];
    unsigned int   ExtentsSize;
    unsigned int   ExtentsDataLength;
    void *         ExtentsData;
}Extents_data;

typedef struct wave_demo{
	FILE           *fp;
    // RIFF Bolck
    char           ChunkID[4];
    unsigned int   ChunkSize;
    char           Format[4];

    // fmt Bolck
    char           Subchunk1ID[4];
    unsigned int   Subchunk1Size;
    unsigned short AudioFormate;
    unsigned short NumChannels;
    unsigned int   SampleRate;
    unsigned int   ByteRate;
    unsigned short BlockAilgn;
    unsigned short BitePerSample;

    // extents Block
    Extents_data   *ExtentsFrames;

    // data Block
    char           Subchunck2ID[4];
    unsigned int   Subchunck2Size;
    // data offset
    unsigned int   DataOffset;
}wave;

// 存储单声道8bit的数据
typedef unsigned char c1b8;
// 存储单声道16bit的数据
typedef unsigned short c1b16;
// 存储双声道8bit的数据
typedef struct {
	unsigned char L_c2b8;
	unsigned char R_c2b8;
}c2b8;
	// 存储双声道16bit的数据
typedef struct {
	unsigned short L_c2b16;
	unsigned short R_c2b16;
}c2b16;
#endif /* WAVE_H_ */

下一步的计划,一直到单片机里边,再加个timer,调度啥的,争取早点实现单片机片上DAC播放WAVE的想法。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章           查看所有文章
加:2021-07-24 11:39:31  更:2021-07-24 11:42:05 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 18:33:27-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码