1. 程式人生 > >用ADC編碼PCM資料錄製WAV格式音訊檔案

用ADC編碼PCM資料錄製WAV格式音訊檔案

因為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,
*/