C ++ Чтение части данных файла WAV

Я планирую создать программу, которая будет визуализировать звуковую форму WAV-файла.

До сих пор я начал с правильного прочтения заголовочной части указанного wav-файла. Код, который я использую, будет таким:

#include <iostream>
#include <string>
#include <fstream>

using namespace std;
using std::string;
using std::fstream;

typedef struct  WAV_HEADER{
char                RIFF[4];        // RIFF Header      Magic header
unsigned long       ChunkSize;      // RIFF Chunk Size
char                WAVE[4];        // WAVE Header
char                fmt[4];         // FMT header
unsigned long       Subchunk1Size;  // Size of the fmt chunk
unsigned short      AudioFormat;    // Audio format 1=PCM,6=mulaw,7=alaw, 257=IBM Mu-Law, 258=IBM A-Law, 259=ADPCM
unsigned short      NumOfChan;      // Number of channels 1=Mono 2=Sterio
unsigned long       SamplesPerSec;  // Sampling Frequency in Hz
unsigned long       bytesPerSec;    // bytes per second
unsigned short      blockAlign;     // 2=16-bit mono, 4=16-bit stereo
unsigned short      bitsPerSample;  // Number of bits per sample
char                Subchunk2ID[4]; // "data"  string
unsigned long       Subchunk2Size;  // Sampled data length

}wav_hdr;

// Function prototypes
int getFileSize(FILE *inFile);

int main(int argc,char *argv[]){
wav_hdr wavHeader;
FILE *wavFile;
int headerSize = sizeof(wav_hdr),filelength = 0;

string answer;

do{
string input;
string answer;

const char* filePath;

cout << "Pick wav file from the Windows Media File: ";
cin >> input;
cin.get();

cout << endl;

path = "C:\\Windows\\Media\\" + input + ".wav";
filePath = path.c_str();

wavFile = fopen( filePath , "r" );

if(wavFile == NULL){
printf("Can not able to open wave file\n");
//exit(EXIT_FAILURE);
}

fread(&wavHeader,headerSize,1,wavFile);
filelength = getFileSize(wavFile);
fclose(wavFile);

cout << "File is                    :" << filelength << " bytes." << endl;

cout << "RIFF header                :" << wavHeader.RIFF[0]
<< wavHeader.RIFF[1]
<< wavHeader.RIFF[2]
<< wavHeader.RIFF[3] << endl;

cout << "WAVE header                :" << wavHeader.WAVE[0]
<< wavHeader.WAVE[1]
<< wavHeader.WAVE[2]
<< wavHeader.WAVE[3]
<< endl;

cout << "FMT                        :" << wavHeader.fmt[0]
<< wavHeader.fmt[1]
<< wavHeader.fmt[2]
<< wavHeader.fmt[3]
<< endl;

cout << "Data size                  :" << wavHeader.ChunkSize << endl;

// Display the sampling Rate form the header
cout << "Sampling Rate              :" << wavHeader.SamplesPerSec << endl;
cout << "Number of bits used        :" << wavHeader.bitsPerSample << endl;
cout << "Number of channels         :" << wavHeader.NumOfChan << endl;
cout << "Number of bytes per second :" << wavHeader.bytesPerSec << endl;
cout << "Data length                :" << wavHeader.Subchunk2Size << endl;
cout << "Audio Format               :" << wavHeader.AudioFormat << endl;
// Audio format 1=PCM,6=mulaw,7=alaw, 257=IBM Mu-Law, 258=IBM A-Law, 259=ADPCMcout << "Block align                :" << wavHeader.blockAlign << endl;

cout << "Data string                :" << wavHeader.Subchunk2ID[0]
<< wavHeader.Subchunk2ID[1]
<< wavHeader.Subchunk2ID[2]
<< wavHeader.Subchunk2ID[3]
<< endl;

cout << endl << endl << "Try something else? (y/n)";
cin >> answer;
//cin.get();
cout << endl << endl;

}while( answer == "y" );getchar();
return 0;
}
// find the file size
int getFileSize(FILE *inFile){
int fileSize = 0;
fseek(inFile,0,SEEK_END);

fileSize=ftell(inFile);

fseek(inFile,0,SEEK_SET);
return fileSize;
}

Я пробовал это несколько раз, и данные, которые он дает, кажутся непротиворечивыми через различные файлы wav в папке Media в папке Windows.

Следующим шагом будет сохранение фактических данных файла WAV в векторе. Тем не менее, я совершенно не знаю, как это сделать. Онлайн решения, которые я нашел, зашли так далеко, как чтение файла заголовка.

Любые идеи о том, как хранить (и, надеюсь, отображать) фактические данные файла WAV?
Спасибо!

11

Решение

Это изображение взято из Стэнфордский курс

Формат файла WAV

Таким образом, вы можете видеть, что аудиоданные появляются сразу после того, как заголовки, которые вы уже прочитали, и будут Subchunk2Size байты аудиоданных.

Псевдокод для этого будет

ReadRIFF();
ReadFMT();
int32 chunk2Id = Read32(BigEndian);
int32 chunk2Size = Read32(LittleEndian);
for (int i = 0; i < chunk2Size; i++)
{
audioData[i] = ReadByte();
}

Если аудио стерео, у вас будет два аудиопотока в data, Если аудио сжато (mp3, aac и т. Д.), Вам сначала нужно его распаковать.

12

Другие решения

Я знаю, что это старый пост, но ваши параметры fread переключаются, вот более правильная версия (требуется g ++ — 4.7 или выше с флагом -std = c ++ 11, например, «g ++ -std = c ++ 11 WaveReader. cpp -o WaveReader «).

#include <iostream>
#include <string>
#include <fstream>
#include <cstdint>

using std::cin;
using std::cout;
using std::endl;
using std::fstream;
using std::string;

typedef struct  WAV_HEADER
{
/* RIFF Chunk Descriptor */
uint8_t         RIFF[4];        // RIFF Header Magic header
uint32_t        ChunkSize;      // RIFF Chunk Size
uint8_t         WAVE[4];        // WAVE Header
/* "fmt" sub-chunk */
uint8_t         fmt[4];         // FMT header
uint32_t        Subchunk1Size;  // Size of the fmt chunk
uint16_t        AudioFormat;    // Audio format 1=PCM,6=mulaw,7=alaw,     257=IBM Mu-Law, 258=IBM A-Law, 259=ADPCM
uint16_t        NumOfChan;      // Number of channels 1=Mono 2=Sterio
uint32_t        SamplesPerSec;  // Sampling Frequency in Hz
uint32_t        bytesPerSec;    // bytes per second
uint16_t        blockAlign;     // 2=16-bit mono, 4=16-bit stereo
uint16_t        bitsPerSample;  // Number of bits per sample
/* "data" sub-chunk */
uint8_t         Subchunk2ID[4]; // "data"  string
uint32_t        Subchunk2Size;  // Sampled data length
} wav_hdr;

// Function prototypes
int getFileSize(FILE* inFile);

int main(int argc, char* argv[])
{
wav_hdr wavHeader;
int headerSize = sizeof(wav_hdr), filelength = 0;

const char* filePath;
string input;
if (argc <= 1)
{
cout << "Input wave file name: ";
cin >> input;
cin.get();
filePath = input.c_str();
}
else
{
filePath = argv[1];
cout << "Input wave file name: " << filePath << endl;
}

FILE* wavFile = fopen(filePath, "r");
if (wavFile == nullptr)
{
fprintf(stderr, "Unable to open wave file: %s\n", filePath);
return 1;
}

//Read the header
size_t bytesRead = fread(&wavHeader, 1, headerSize, wavFile);
cout << "Header Read " << bytesRead << " bytes." << endl;
if (bytesRead > 0)
{
//Read the data
uint16_t bytesPerSample = wavHeader.bitsPerSample / 8;      //Number     of bytes per sample
uint64_t numSamples = wavHeader.ChunkSize / bytesPerSample; //How many samples are in the wav file?
static const uint16_t BUFFER_SIZE = 4096;
int8_t* buffer = new int8_t[BUFFER_SIZE];
while ((bytesRead = fread(buffer, sizeof buffer[0], BUFFER_SIZE / (sizeof buffer[0]), wavFile)) > 0)
{
/** DO SOMETHING WITH THE WAVE DATA HERE **/
cout << "Read " << bytesRead << " bytes." << endl;
}
delete [] buffer;
buffer = nullptr;
filelength = getFileSize(wavFile);

cout << "File is                    :" << filelength << " bytes." << endl;
cout << "RIFF header                :" << wavHeader.RIFF[0] << wavHeader.RIFF[1] << wavHeader.RIFF[2] << wavHeader.RIFF[3] << endl;
cout << "WAVE header                :" << wavHeader.WAVE[0] << wavHeader.WAVE[1] << wavHeader.WAVE[2] << wavHeader.WAVE[3] << endl;
cout << "FMT                        :" << wavHeader.fmt[0] << wavHeader.fmt[1] << wavHeader.fmt[2] << wavHeader.fmt[3] << endl;
cout << "Data size                  :" << wavHeader.ChunkSize << endl;

// Display the sampling Rate from the header
cout << "Sampling Rate              :" << wavHeader.SamplesPerSec << endl;
cout << "Number of bits used        :" << wavHeader.bitsPerSample << endl;
cout << "Number of channels         :" << wavHeader.NumOfChan << endl;
cout << "Number of bytes per second :" << wavHeader.bytesPerSec << endl;
cout << "Data length                :" << wavHeader.Subchunk2Size << endl;
cout << "Audio Format               :" << wavHeader.AudioFormat << endl;
// Audio format 1=PCM,6=mulaw,7=alaw, 257=IBM Mu-Law, 258=IBM A-Law, 259=ADPCM

cout << "Block align                :" << wavHeader.blockAlign << endl;
cout << "Data string                :" << wavHeader.Subchunk2ID[0] << wavHeader.Subchunk2ID[1] << wavHeader.Subchunk2ID[2] << wavHeader.Subchunk2ID[3] << endl;
}
fclose(wavFile);
return 0;
}

// find the file size
int getFileSize(FILE* inFile)
{
int fileSize = 0;
fseek(inFile, 0, SEEK_END);

fileSize = ftell(inFile);

fseek(inFile, 0, SEEK_SET);
return fileSize;
}
7

По вопросам рекламы [email protected]