用ADC编码PCM数据录制WAV格式音频文件

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_27508477/article/details/83277189

因为PCM文件直接保存采样的量化值,所以按照规定格式,先编写头,再写音频数据就可以了。
这里是录制一个6s长度的WAV音频文件,PCM格式,单声道,44.1kHz采样频率,88200的音频码率,16bit的数据,算下来的数据大小是88200*6=529.200KB。

//(数据字段包含数据的大小。如无扩展块,则值为16;有扩展块,则值为= 16 + 2字节扩展块长度 + 扩展块长度或者值为18(只有扩展块的长度为2字节,值为0)
char header[]= {82,73,70,70, //"RIFF"
                0x54,0x13,8,0,//FileSize-8
                87,65,86,69,//"WAVE"
                102,109,116,32,//"fmt "
                16,0,0,0,//数据段16bit
                1,0,//PCM格式
                1,0,//单声道																				2,0,//双声道
                68,172,0,0,//采样率44.1kHz
                136,88,1,0,//音频码率=采样率*通道数*bit数/8					16,177,2,0,//音频码率=采样率*通道数*bit数/8
                2,0,//采样一次占1个字节															4,0,//采样一次占4个字节
                16,0,//每个通道8bit数据															16,0,//每个通道16bit数据
                100,97,116,97,//"data"
                0x30,0x13,8,0//数据长度	6s
               };


void writeWave()
{
    FIL *f_test;
    u8 buffer[100];
    u8 data[4];
    unsigned long int t;
    long int adcValue;
    UINT bw;
    unsigned int FATFSNumSize;
    f_test=(FIL*)mymalloc(SRAMIN,sizeof(FIL));
    if(f_test==NULL)
    {
        printf("申请内存失败\r\n");
        return;
    }
    for(t=0; t<100; t++)	buffer[t]=0;
    printf("begin write:\r\n");
    f_unlink( "0:3.wav");
    f_open(f_test, "0:3.wav", FA_OPEN_ALWAYS | FA_WRITE);
    f_write(f_test,header,44, &bw);
    for(t=0; t<264600; t++)	//6s
    {
        TIM_SetCounter(TIM3,0);//重设TIM3定时器的计数器值
        adcValue=Get_Adc(ADC_Channel_10);	//12bit
        data[0]=((adcValue<<4)&0xFF);
        data[1]=(adcValue>>4);
        f_write(f_test,data,2, &bw);
        time=TIM_GetCounter(TIM3);
        while(time<23)	//50us 20kHz
        {
            time=TIM_GetCounter(TIM3); 			//计算所用时间
        }
    }
    f_close(f_test);
    printf("write ok\r\n");
    myfree(SRAMIN,f_test);	//释放内存
}

因为stm32的adc是12位精度的,所以强行左移4位,低位补零,然后存写入文件中。
每次采样16bit,采集264600次就是529.200KB了。
可能是咪头本身的频率响应不是很好,录制邓紫棋的喜欢你,播放出来感觉高频都没有了,听着像是一个男人的声音,而且还有一些沙沙的低噪。

u16 Get_Adc(u8 ch)   
{
	  	//设置指定ADC的规则组通道,一个序列,采样时间
		//ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_480Cycles );	//ADC1,ADC通道,480个周期,提高采样时间可以提高精确度			    
 	ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_56Cycles );	//ADC1,ADC通道,480个周期,提高采样时间可以提高精确度	
	ADC_SoftwareStartConv(ADC1);		//使能指定的ADC1的软件转换启动功能	
	 
	while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束

	return ADC_GetConversionValue(ADC1);	//返回最近一次ADC1规则组的转换结果
}

因为使用的是F4的板子,在ADC采样时,采样周期为ADC_SampleTime_480Cycles 时,采样时间会超过1000000/44100=22.67us,所以这里降低了采样周期,也可能是造成后面效果的原因之一。

附邓紫棋-喜欢你.wav文件的信息头:

/* love you
file size:21552932

RIFF chunck:RIFF
RIFF size:21552958
RIFF data:WAVE
	Format sub-chunck:fmt
	Format size:16
	Format data:
		Format tag:1
		Format channel:1
		Format fmt_samplehz:44100
		Format fmt_bytepsec:88200
		Format fmt_bytesample:2
		Format fmt_bitpsample:16
	Data sub_chunk:data
	Data size:21552888
	Data data:
82,73,70,70,62,223,72,1,87,65,86,69,102,109,116,32,16,0,0,0,1,0,1,0,68,172,0,0,136,88,1,0,2,0,16,0,100,97,116,97,248,222,72,1,
*/

猜你喜欢

转载自blog.csdn.net/qq_27508477/article/details/83277189