'No sound in the output track when i'm writing into .wav file
I'm quite new in C++ and i'm trying to parse .wav file in order to add some audioeffects on it then. So, at first I'm trying to read and parse input .wav file and then write it into output .wav file. The output file has same size in explorer and some duration in audioplayer, but the sound is absent when it's playing. What's wrong with it?
Here my code.
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
struct WavHeader
{
char chunkId[4]; // RIFF, FMT, DATA, e.t.c.
unsigned long ChunkSize; // Chunk Size
};
struct RiffHeader : WavHeader
{
char format[4]; // WAVE Header
};
struct FmtHeader : WavHeader
{
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
};
struct DataHeader : WavHeader
{
};
struct Wav
{
RiffHeader RiffHeader;
FmtHeader FmtHeader;
DataHeader DataHeader;
vector<char> Data;
};
/// <summary>
/// Read/write .wav files.
/// </summary>
class WavFileManager
{
public:
/// <summary>
/// Read whole .wav file.
/// </summary>
/// <param name="path">Path to file.</param>
Wav ReadAll(const string& path)
{
ifstream file(path);
if (!file)
{
throw runtime_error("Can't open file: " + path);
}
Wav* wavFile = new Wav();
wavFile->RiffHeader = ReadHeader<RiffHeader>(file);
if (wavFile->RiffHeader.format != "WAVE\0")
{
// throw runtime_error("Wrong format. File: " + path);
}
wavFile->FmtHeader = ReadHeader<FmtHeader>(file);
if (!TrySkipChunksBefore(file, "data"))
{
throw runtime_error("Can't find wav data. File: " + path);
}
wavFile->DataHeader = ReadHeader<DataHeader>(file);
vector<char>& data = wavFile->Data;
data.reserve(wavFile->DataHeader.ChunkSize);
for (int i = 0; i < wavFile->DataHeader.ChunkSize; i++)
{
char buffer;
file.read((char*)&buffer, sizeof(char));
data.push_back(buffer);
}
reverse(data.begin(), data.end());
file.close();
return *wavFile;
}
/// <summary>
/// Read header of .wav file.
/// </summary>
/// <param name="file">File stream.</param>
/// <returns>Header of type T.</returns>
template<typename T>
T ReadHeader(ifstream& file)
{
T header;
int headerSize = sizeof(T);
file.read((char*)&header, headerSize);
return header;
}
/// <summary>
/// Read data chunk of .wav file.
/// </summary>
/// <param name="file">File stream.</param>
/// <param name="size">Chunk size.</param>
/// <returns>Array of bytes.</returns>
char* ReadChunk(ifstream& file, unsigned long size)
{
char* chunk = new char[size];
file.read(chunk, size);
return chunk;
}
/// <summary>
/// Check if .wav header has following chunkId.
/// </summary>
/// <param name="header">.wav header.</param>
/// <param name="chunkId">Id to compare.</param>
bool HasChunkID(const WavHeader& header, const char chunkId[4])
{
return ((header.chunkId[0] == chunkId[0]) &&
(header.chunkId[1] == chunkId[1]) &&
(header.chunkId[2] == chunkId[2]) &&
(header.chunkId[3] == chunkId[3]));
}
/// <summary>
/// Skip all chunks before reqired chunk.
/// </summary>
/// <param name="file">File stream.</param>
/// <param name="chunkId">Id of required chunk.</param>
bool TrySkipChunksBefore(ifstream& file, const char chunkId[4])
{
while (!file.eof())
{
streampos pos = file.tellg();
WavHeader header = ReadHeader<WavHeader>(file);
char* chunk = ReadChunk(file, header.ChunkSize);
if (HasChunkID(header, chunkId))
{
file.clear();
file.seekg(pos);
return true;
}
delete[] chunk;
}
return false;
}
/// <summary>
/// Write all data into file.
/// </summary>
/// <param name="data">Wav to write.</param>
/// <param name="path">Path to output file.</param>
void WriteAll(Wav data, const string& path)
{
ofstream file(path, ios::binary);
file.write((char*)&data.RiffHeader, sizeof(RiffHeader));
file.write((char*)&data.FmtHeader, sizeof(FmtHeader));
file.write((char*)&data.DataHeader, sizeof(DataHeader));
reverse(data.Data.begin(), data.Data.end());
for (int i = 0; i < data.Data.size(); i++)
{
file.write((char*)&data.Data[i], sizeof(char));
}
file.close();
}
};
int main()
try
{
auto* mgr = new WavFileManager();
auto wav = mgr->ReadAll ("input.wav");
mgr->WriteAll(wav, "output.wav");
}
catch (runtime_error& e)
{
cerr << "Error! " << e.what() << '\n';
}
Solution 1:[1]
Problem resolved were easy.
ifstream file(path, ios::binary);
instead of
ifstream file(path);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | oleg_mekhovnikov |
