Add Music fluctuations project and Chinese plan docs
This commit is contained in:
223
MVS/Music fluctuations/source/audio/WavFileReader.cpp
Normal file
223
MVS/Music fluctuations/source/audio/WavFileReader.cpp
Normal file
@@ -0,0 +1,223 @@
|
||||
#include"WavFileReader.h"
|
||||
|
||||
WavFileReader::WavFileReader(){}
|
||||
|
||||
WavFileReader::~WavFileReader()
|
||||
{
|
||||
CloseFile();
|
||||
}
|
||||
|
||||
|
||||
bool WavFileReader::OpenFile(const std::string& p_fileName)
|
||||
{
|
||||
if (p_fileName == m_fileName) {
|
||||
std::cerr << "已经打开了该WAV文件" << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
m_file = std::ifstream(p_fileName, std::ios::binary);
|
||||
if (!m_file) {
|
||||
std::cerr << "无法打开WAV文件" << std::endl;
|
||||
return false;
|
||||
}
|
||||
if (ProcessWavFile()) {
|
||||
m_fileName = p_fileName;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
m_file.close();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void WavFileReader::CloseFile()
|
||||
{
|
||||
if (m_file) { m_file.close(); }
|
||||
m_fileName = "";
|
||||
}
|
||||
|
||||
bool WavFileReader::ProcessWavFile()
|
||||
{
|
||||
/*处理文件头部分*/
|
||||
WavRIFF riff;
|
||||
WavFormat format;
|
||||
|
||||
m_file.seekg(0, std::ios::end);
|
||||
m_fileSize = m_file.tellg();
|
||||
m_file.seekg(0, std::ios::beg);
|
||||
|
||||
m_file.read(reinterpret_cast<char*>(&riff), sizeof(WavRIFF));
|
||||
if (strncmp(riff.id, "RIFF", 4) != 0 || strncmp(riff.waveFlag, "WAVE", 4) != 0){
|
||||
std::cerr << "不是有效的WAV文件!" << std::endl;
|
||||
CloseFile();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_file.read(reinterpret_cast<char*>(&format), sizeof(WavFormat));
|
||||
if (strncmp(format.id, "fmt ", 4) != 0){
|
||||
std::cerr << "format读取失败!" << std::endl;
|
||||
CloseFile();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (format.formatTag != 1){
|
||||
std::cerr << "数据格式非pcm,程序不支持!" << std::endl;
|
||||
CloseFile();
|
||||
return false;
|
||||
}
|
||||
|
||||
/*处理文件后部数据*/
|
||||
while (m_file.tellg() < m_fileSize){
|
||||
WavChunk chunk;
|
||||
m_file.read(reinterpret_cast<char*>(&chunk), sizeof(WavChunk));
|
||||
if (strncmp(chunk.id, "LIST", 4) == 0){
|
||||
std::cout << "LIST" << std::endl;
|
||||
//ProcessLIST(chunk.dataLength);
|
||||
m_file.seekg(chunk.dataLength, std::ios::cur);
|
||||
continue;
|
||||
}
|
||||
else if (strncmp(chunk.id, "data", 4) == 0){
|
||||
std::cout << "data" << std::endl;
|
||||
m_dataOffset = m_file.tellg();
|
||||
m_dataLength = chunk.dataLength;
|
||||
m_file.seekg(chunk.dataLength, std::ios::cur);
|
||||
continue;
|
||||
}
|
||||
else{
|
||||
m_file.seekg(chunk.dataLength, std::ios::cur);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
m_fileLength = riff.fileLength + 8;
|
||||
m_channels = format.channels;
|
||||
m_sampleRate = format.samplesPerSec;
|
||||
m_bitsPerSample = format.bitsPerSample;
|
||||
m_bytesPerSec = format.avgBytesPerSec;
|
||||
m_lastingTime = (float)m_dataLength / m_bytesPerSec;
|
||||
m_sampleNum = m_dataLength / (m_bitsPerSample / 8);
|
||||
}
|
||||
|
||||
|
||||
//TODO::
|
||||
void WavFileReader::ProcessLIST(int listLength){
|
||||
while (listLength > 0){
|
||||
//if (strncmp(id, "INFO", 4) == 0){
|
||||
//char* info = new char[chunk.dataLength];
|
||||
//m_file.read(info, chunk.dataLength);
|
||||
//TODO:处理INFO
|
||||
|
||||
//delete[] info;
|
||||
//}
|
||||
//else if (strncmp(id, "adtl", 4) == 0) {
|
||||
//char* adtl = new char[chunk.dataLength];
|
||||
//m_file.read(adtl, chunk.dataLength);
|
||||
//TODO:处理adtl
|
||||
|
||||
//delete[] adtl;
|
||||
//}
|
||||
//else {
|
||||
//char* custom = new char[chunk.dataLength];
|
||||
//m_file.read(custom, chunk.dataLength);
|
||||
//TODO:处理自定义块
|
||||
|
||||
//delete[] custom;
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int WavFileReader::ReadData(char* p_buffer, int p_position, int p_readLength){
|
||||
if (!m_file) {
|
||||
std::cerr << "该WAV文件不存在" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
int filePosition = m_dataOffset + p_position;
|
||||
if(filePosition>m_fileSize){
|
||||
return 0;
|
||||
}
|
||||
m_file.seekg(m_dataOffset + p_position, std::ios::beg);
|
||||
m_file.read(p_buffer, p_readLength);
|
||||
int realLength = m_file.gcount();
|
||||
return realLength;
|
||||
}
|
||||
|
||||
void WavFileReader::SetPosition(int p_position){
|
||||
if (m_file){
|
||||
m_file.seekg(p_position, std::ios::beg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int WavFileReader::GetPosition(){
|
||||
if (!m_file)
|
||||
return -1;
|
||||
return m_file.tellg();
|
||||
}
|
||||
|
||||
int WavFileReader::GetFileLength(){
|
||||
if (!m_file)
|
||||
return -1;
|
||||
return m_fileLength;
|
||||
}
|
||||
|
||||
int WavFileReader::GetDataLength()
|
||||
{
|
||||
if (!m_file)
|
||||
return -1;
|
||||
return m_dataLength;
|
||||
}
|
||||
|
||||
int WavFileReader::GetChannels(){
|
||||
if (!m_file)
|
||||
return -1;
|
||||
return m_channels;
|
||||
}
|
||||
|
||||
int WavFileReader::GetSampleRate(){
|
||||
if (!m_file)
|
||||
return -1;
|
||||
return m_sampleRate;
|
||||
}
|
||||
|
||||
int WavFileReader::GetBytesPerSec(){
|
||||
if (!m_file)
|
||||
return -1;
|
||||
return m_bytesPerSec;
|
||||
}
|
||||
|
||||
int WavFileReader::GetBitsPerSample(){
|
||||
if (!m_file)
|
||||
return -1;
|
||||
return m_bitsPerSample;
|
||||
}
|
||||
|
||||
float WavFileReader::GetLastingTime(){
|
||||
if (!m_file)
|
||||
return -1;
|
||||
return m_lastingTime;
|
||||
}
|
||||
|
||||
int WavFileReader::GetSampleNum(){
|
||||
if (!m_file)
|
||||
return -1;
|
||||
return m_sampleNum;
|
||||
}
|
||||
|
||||
int16_t WavFileReader::GetSampleValue(int p_index) {
|
||||
if (p_index >= m_sampleNum || !m_file)
|
||||
return -1;
|
||||
unsigned int bytesPerSample = m_bitsPerSample / 8;
|
||||
char* sampleBytes = new char[bytesPerSample];
|
||||
ReadData(sampleBytes, p_index * bytesPerSample, bytesPerSample);
|
||||
int16_t sampleValue = 0;
|
||||
for (int i = 0; i < bytesPerSample; ++i) {
|
||||
sampleValue |= static_cast<int16_t>(static_cast<unsigned char>(sampleBytes[i])) << (8 * i);
|
||||
}
|
||||
//
|
||||
delete[] sampleBytes;
|
||||
return sampleValue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user