在这篇文章中,我们将探讨如何在C+++中读取WAV格式的音频文件。音频文件是计算机科学和编程中的一个重要组成部分,正确使用音频可以为娱乐应用程序增添乐趣,或者在业务应用程序中提醒用户重要事件或状态变化。在这篇文章中,我们将解释WAV格式音频文件的基本概念,以及如何在C+中读取WAV格式音频文件。
WAV格式音频文件格式
音频文件有多种格式——存储模拟声音的数字表示方法各不相同。最常用的格式包括MP3、OGG和FLAC文件,这些音频格式使用压缩技术使音频文件更小。最原始的原始格式是WAV文件。WAV格式(*.WAV或*.WAV)是一种记录数字形式的声音,其音量随时间变化的数据。
在C+++ Builder中,使用FMX.Media.hpp头文件,可以轻松录制WAV文件。要录制声音,必须使用MultiDevice应用程序。
如何在C++中录制WAV格式音频文件
录制WAV声音在C+中,我们参考了“Learn How To Easily Record Sound In Powerful Modern C+++ On Windows”文章。
如何在C++中读取WAV格式音频文件
如果你正在读取二进制文件,首先应了解其结构类型,以便正确读取。WAV格式音频文件格式(*.WAV)是音频文件标准,用于记录音频位流在内存或驱动器上的位流。在C+中,可以轻松读取WAV波形音频文件,现在可以显示或编辑波形文件。
Wave File format Ref <a href=httpsoundfilesapporgdocWaveFormat target= blank rel=noopener nofollow title=>httpsoundfilesapporgdocWaveFormat<a>
Wave File format Ref <a href=httpsoundfilesapporgdocWaveFormat target= blank rel=noopener nofollow title=>httpsoundfilesapporgdocWavFormat<a>
Wave头的结构定义如下:
// WAVE file header structure
struct Twavheader
{char chunk_ID[4]; // 4 riff_mark[4];uint32_t chunk_size; // 4 file_size;char format[4]; // 4 wave_str[4];char sub_chunk1_ID[4]; // 4 fmt_str[4];uint32_t sub_chunk1_size; // 4 pcm_bit_num;uint16_t audio_format; // 2 pcm_encode;uint16_t num_channels; // 2 sound_channel;uint32_t sample_rate; // 4 pcm_sample_freq;uint32_t byte_rate; // 4 byte_freq;uint16_t block_align; // 2 block_align;uint16_t bits_per_sample; // 2 sample_bits;char sub_chunk2_ID[4]; // 4 data_str[4];uint32_t sub_chunk2_size; // 4 sound_size;
}; // 44 bytes TOTAL
以下是读取WAV格式音频文件的函数:
void read_wav_file(std::string fname)
{// 打开WAV文件std::ifstream wavfile(fname, std::ios::binary);if(wavfile.is_open()){// 读取WAV头Twavheader wav;wavfile.read(reinterpret_cast<char*&wav), sizeof(Twavheader));// 如果文件是有效的WAV文件if(std::string(wav.format,4)!="WAVE"\|wav.chunk\_ID,4)!="RIFF")wavfile.close();std::cerr<<"Not a WAVE or RIFF!"<<std::endl;return;}// Properties of WAV Filestd::cout << "FileName:" << fname << std::endl;std::cout << "File size:" << wav.chunk_size+8 << std::endl;std::cout << "Resource Exchange File Mark:" << std::string(wav.chunk_ID, 4) << std::endl;std::cout << "Format:" << std::string(wav.format, 4) << std::endl;std::cout << "Channels: " << wav.num_channels << std::endl;std::cout << "Sample Rate: " << wav.sample_rate << " Hz" << std::endl;std::cout << "Bits Per Sample: " << wav.bits_per_sample << " bits" << std::endl;// Read wave datastd::vector<int16_t> audio_data( wav.sub_chunk2_size / sizeof(int16_t) );wavfile.read(reinterpret_cast<char*>( audio_data.data() ), wav.sub_chunk2_size );wavfile.close(); // Close audio file// Display some audio samplesconst size_t numofsample = 20;std::cout <<"Listin first " << numofsample << " Samples:" << std::endl;for (size_t i = 0; i < numofsample && i < audio_data.size(); ++i){std::cout << i << ":" << audio_data[i] << std::endl;} std::cout << std::endl;}
}
这个函数首先打开WAV文件,然后读取WAV头。如果文件是有效的WAV文件,函数将读取头信息并检查文件是否有效。
最后可以如此使用:
read_wav_file("D:\\sample.wav");
以下是读取WAV格式音频文件的完整C++示例:
#include <iostream>
#include <fstream>
#include <vector>
#include <cstdint>struct Twavheader
{char chunk_ID[4]; // 4 riff_mark[4];uint32_t chunk_size; //4 file_size;char format[4]; //4 wave_str[4];char sub_chunk1_ID[4]; //4 fmt_str[4];uint32_t sub_chunk1_size; //4 pcm_bit_num;uint16_t audio_format; //2 pcm_encode;uint16_t num_channels; //2 sound_channel;uint32_t sample_rate; //4 pcm_sample_freq;uint32_t byte_rate; //4 byte_freq;uint16_t block_align; //2 block_align;uint16_t bits_per_sample; //2 sample_bits;char sub_chunk2_ID[4]; //4 data_str[4];uint32_t sub_chunk2_size; //4 sound_size;
};// 444 bytes TOTAL// WAV文件结构
void read_wav_file(std::string fname)
{// 打开WAV文件std::ifstream wavfile(fname, std::ios::binary);if(wavfile.is_open()){// 读取WAV头Twavheader wav;wavfile.read(reinterpret_cast<char*>(&wav), sizeof(Twavheader));// 如果文件是有效的WAV文件if(std::string(wav.format,4)!="WAVE" || std::string(wav.chunk_ID,4)!="RIFF"){wavfile.close();std::cerr << "Not a WAVE or RIFF!" << std::endl;return;}// 属性WAV文件std::cout << "FileName:" << fname << std::endl;std::cout << "File size:" << wav.chunk_size+8 << std::endl;std::cout << "Resource Exchange File Mark:" << std::string(wav.chunk_ID,4) << std::endl;std::cout << "Format:" << std::string(wav.format,4) << std::endl;std::cout << "Channels: " << wav.num_channels << std::endl;std::cout << "Sample Rate: " << wav.sample_rate << std::endl;std::cout << "Bits Per Sample: " << wav.bits_per_sample << std::endl;// 读取波形数据std::vector<int16_t> audio_data(wav.sub_chunk2_size/sizeof(int16_t)); // 4 pcm_bit_numwavfile.read(reinterpret_cast<char*>(audio_data.data()), wav.sub_chunk2_size);wavfile.close(); // 关闭音频文件// 显示一些音频样本const size_t numofsample = 20;std::cout << "Listing first " << numofsample << " Samples:" << std::endl;for(size_t i = 0; i < numofsample && i < audio_data.size(); ++i){std::cout << i << ":" << audio_data[i] << std::endl;}std::cout << std::endl;}
}
//------------------------------------------------------------------------------
int main()
{read_wav_file("D:\\sample.wav");system("pause");return 0;
}
最后输出如下:
FileName:D:\sample.wav
File size:563756
Resource Exchange File Mark:RIFF
Format:WAVE
Channels: 2
Sample Rate: 44100 Hz
Bits Per Sample: 16 bits
Listing first 20 Samples:
0:-1934
1:-1934
2:-1276
3:-1276
4:-241
5:-241
6:598
7:598
8:282
9:282
10:242
11:242
12:314
13:314
14:208
15:208
16:-128
17:-128
18:-1226
19:-1226