I am quite new to audio processing and my C++ programming skills are also on basic level. I have to create recording function and I receive data signal from device in form of callback. I would like someone to assist me with basic theory how should I manage WAV memory because I am lost. For now my code looks like this:
Functions I am currently using:
template <typename T>
void write(std::ofstream& stream, const T& t) {
stream.write((const char*)&t, sizeof(T));
}
template <typename T>
void writeFormat(std::ofstream& stream) {
write<short>(stream, 1);
}
template <>
void writeFormat<float>(std::ofstream& stream) {
write<short>(stream, 3);
}
template <typename SampleType>
void writeWAVData(
char const* outFile,
SampleType* buf,
size_t bufSize,
int sampleRate,
short channels)
{
std::ofstream stream(outFile, std::ios::binary|ios::app|ios::ate);
stream.write("RIFF", 4); // Start writting RIFF
write<int>(stream, 0); // (file-size)-8 - FOR NOW IGNORED
stream.write("WAVE", 4); // File type
stream.write("fmt ", 4); // Start Writting format chunk "fmt"
write<int>(stream, 16); // Chunk Data Size 16 + extra format bytes
writeFormat<SampleType>(stream); // Format (compression code)
write<short>(stream, channels); // Channels
write<int>(stream, sampleRate); // Sample Rate
write<int>(stream, sampleRate * channels * sizeof(SampleType)); // Byterate (byte/per sec)
write<short>(stream, channels * sizeof(SampleType)); // Frame size (block align)
write<short>(stream, 8 * sizeof(SampleType)); // Bits per sample
stream.write("data", 4); // Start writting chunk for extra format bytes
stream.write((const char*)&bufSize, 0); // - FOR NOW IGNORED
stream.write((const char*)buf, 0); // - FOR NOW IGNORED
}
General idea what I want to do is:
- Create *.wav file.
- Write header chunk.
- Add new data at the end of file as long user doesn't stop it.
- When user clicks stop, go back to the header memory and edit field under "RIFF" and "data" chunks with right value.
First Question: So I have buffer storing 256 samples so in loop, every 256 I try to write buffer with new data to the file like in code below. After reading *.wav documentaiton http://www.sonicspot.com/guide/wavefiles.html I understand that *.wav file should have RIFF header at start of each chunk. But if I write buffer with 256 samples and place RIFF chunk before it what's difference if I would enter 512 samples instead? Does every sample need RIFF chunk before it?
for (int j = 0 ; j < 256 ; j++)
{
if (j == 255)
writeWAVData("mySound0.wav", (int*)bufferInfos[0].buffers[doubleBufferIndex], buffSize, 44100, 1);
}
Where:
- bufferInfos[] - holds table of various buffers but I want to save data from only one now
- bufferInfos[0].buffers[doubleBufferIndex] - is a pointer to first buffer data block
- doubleBufferIndex - index of pan, takes values 0-1, left, right, left, right etc
Second question: is about channel parameter because it's a bit confusing. My signal consists of values received in turns: left pan, right pan, left pan, right pan... so that would mean I have 2 channels - left and right?
Third question: My signal from device is 24bit... shouldn't I just write in the bits per sample 24 then or how should it include this information.