added WAV file writer

This commit is contained in:
Ahmet Inan 2018-03-10 20:10:54 +01:00
commit 52b16be64a
3 changed files with 120 additions and 0 deletions

View file

@ -25,3 +25,11 @@ Implemented are the follwing [Window functions](https://en.wikipedia.org/wiki/Wi
Some constants we need
### [pcm.hh](pcm.hh)
Interface for reading and writing [PCM](https://en.wikipedia.org/wiki/Pulse-code_modulation) data
### [wav.hh](wav.hh)
Read and write [WAV](https://en.wikipedia.org/wiki/WAV) files

28
pcm.hh Normal file
View file

@ -0,0 +1,28 @@
/*
Interface for reading and writing PCM data
Copyright 2018 Ahmet Inan <inan@aicodix.de>
*/
#ifndef PCM_HH
#define PCM_HH
namespace DSP {
template <typename TYPE>
struct WritePCM
{
virtual void write(TYPE *, int, int) = 0;
virtual void silence(int) = 0;
};
template <typename TYPE>
struct ReadPCM
{
virtual void read(TYPE *, int, int) = 0;
};
}
#endif

84
wav.hh Normal file
View file

@ -0,0 +1,84 @@
/*
Read and write WAV files
Copyright 2018 Ahmet Inan <inan@aicodix.de>
*/
#ifndef WAV_HH
#define WAV_HH
#include <fstream>
#include "pcm.hh"
namespace DSP {
template <typename TYPE>
class WriteWAV : public WritePCM<TYPE>
{
std::ofstream os;
int bytes, channels;
int offset, factor, min, max;
void writeLE(int v, int b)
{
for (int i = 0; i < b; ++i)
os.put(255 & (v >> (8 * i)));
}
public:
WriteWAV(const char *name, int rate, int bytes, int channels) : os(name, std::ios::binary | std::ios::trunc), bytes(bytes), channels(channels)
{
switch (bytes) {
case 1:
offset = 128;
factor = 127;
min = 0;
max = 255;
break;
default:
bytes = 2;
offset = 0;
factor = 32767;
min = -32768;
max = 32767;
}
os.write("RIFF", 4); // ChunkID
writeLE(36, 4); // ChunkSize
os.write("WAVE", 4); // Format
os.write("fmt ", 4); // Subchunk1ID
writeLE(16, 4); // Subchunk1Size
writeLE(1, 2); // AudioFormat
writeLE(channels, 2); // NumChannels
writeLE(rate, 4); // SampleRate
writeLE(rate * channels * bytes, 4); // ByteRate
writeLE(channels * bytes, 2); // BlockAlign
writeLE(8 * bytes, 2); // BitsPerSample
os.write("data", 4); // Subchunk2ID
writeLE(0, 4); // Subchunk2Size
}
~WriteWAV()
{
int size = int(os.tellp()) - 44;
os.seekp(4);
writeLE(36 + size, 4); // ChunkSize
os.seekp(40);
writeLE(size, 4); // Subchunk2Size
}
void write(TYPE *buf, int num, int stride = 1)
{
for (int n = 0; n < num; ++n) {
for (int c = 0; c < channels; ++c) {
TYPE v = TYPE(offset) + TYPE(factor) * buf[stride * n + c];
writeLE(std::nearbyint(std::clamp(v, TYPE(min), TYPE(max))), bytes);
}
}
}
void silence(int num)
{
for (int i = 0; i < num * channels; ++i)
writeLE(offset, bytes);
}
};
}
#endif