// .cpp file
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <inttypes.h>
#include <stdint.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Wav.h"
#include "types.h"
using namespace std;
uint32_t size = 0;
int bits_per_sample;
int sample_rate2;
AudioLib::Wav::Wav() {
}
AudioLib::Wav::Wav(const int N, const int M) : AudioLib::Signal() {
/*TO DO TO DO TO DO TO DO*/
}
AudioLib::Wav::Wav(string theFile, ReadType type) {
ifstream file (theFile.c_str());
if(!this->_checkFileExists(file))
{
cerr << " :: Cannot Read (WAV) File ::";
exit(0);
}
if(!this->readWav(file, type))
{
cerr << "An error occured";
exit(0);
}
}
vector<double> const& AudioLib::Wav::Signal() const {
return this->rawSignal;
}
inline bool AudioLib::Wav::readHeader(ifstream& file) {
s_riff_hdr riff_hdr;
s_chunk_hdr chunk_hdr;
long padded_size; // Size of extra bits
vector<uint8_t> fmt_data; // Vector to store the FMT data.
s_wavefmt *fmt = NULL;
file.read(reinterpret_cast<char*>(&riff_hdr), sizeof(riff_hdr));
if (!file) return false;
if (memcmp(riff_hdr.id, "RIFF", 4) != 0) return false;
//cout << "size=" << riff_hdr.size << endl;
//cout << "type=" << string(riff_hdr.type, 4) << endl;
if (memcmp(riff_hdr.type, "WAVE", 4) != 0) return false;
{
do
{
file.read(reinterpret_cast<char*>(&chunk_hdr), sizeof(chunk_hdr));
if (!file) return false;
padded_size = ((chunk_hdr.size + 1) & ~1);
if (memcmp(chunk_hdr.id, "fmt ", 4) == 0)
{
if (chunk_hdr.size < sizeof(s_wavefmt)) return false;
fmt_data.resize(padded_size);
file.read(reinterpret_cast<char*>(&fmt_data[0]), padded_size);
if (!file) return false;
fmt = reinterpret_cast<s_wavefmt*>(&fmt_data[0]);
sample_rate2 = fmt->sample_rate;
if (fmt->format_tag == 1) // PCM
{
if (chunk_hdr.size < sizeof(s_pcmwavefmt)) return false;
s_pcmwavefmt *pcm_fmt = reinterpret_cast<s_pcmwavefmt*>(fmt);
bits_per_sample = pcm_fmt->bits_per_sample;
}
else
{
if (chunk_hdr.size < sizeof(s_wavefmtex)) return false;
s_wavefmtex *fmt_ex = reinterpret_cast<s_wavefmtex*>(fmt);
if (fmt_ex->extra_size != 0)
{
if (chunk_hdr.size < (sizeof(s_wavefmtex) + fmt_ex->extra_size)) return false;
uint8_t *extra_data = reinterpret_cast<uint8_t*>(fmt_ex + 1);
// use extra_data, up to extra_size bytes, as needed...
}
}
//cout << "extra_size=" << fmt_ex->extra_size << endl;
}
else if (memcmp(chunk_hdr.id, "data", 4) == 0)
{
// process chunk data, according to fmt, as needed...
size = padded_size;
if(bits_per_sample == 16)
{
//size = padded_size / 2;
}
data = new char[size];
file.read(data, size);
file.ignore(padded_size);
if (!file) return false;
}
else
{
// process other chunks as needed...
file.ignore(padded_size);
if (!file) return false;
}
}while (!file.eof());
return true;
}
}
inline bool AudioLib::Wav::readWav(ifstream &file, ReadType type) {
if(!this->readHeader(file))
{
return 0;
}
IntN< 16>::type x;
switch(type)
{
case NATIVE:
/* to do to do to do to do to do to do */
break;
case DOUBLE:
sample_rate = sample_rate2;
if(bits_per_sample == 8)
{
uint8_t c;
//cout << size;
for(unsigned i=0; (i < size); i++)
{
c = (unsigned)(unsigned char)(data[i]);
double t = (c-128)/128.0;
rawSignal.push_back(t);
}
}
else if(bits_per_sample == 16)
{
for (int i = 0; i < size; i += 2)
{
int c = (data[i + 1] << 8) | data[i];
double t = c/32768.0;
//cout << t << endl;
rawSignal.push_back(t);
}
}else{
cerr << "Cannot Initalise correct 'bits_per_sample' in reference to function: 'readWav' line: 67";
}
break;
default: return false; break;
}
return true;
}
AudioLib::Wav& AudioLib::Wav::Emphasize()
{
Signal::Emphasize();
return *this;
}
AudioLib::Wav& AudioLib::Wav::Compress()
{
Signal::Compress();
return *this;
}
int AudioLib::Wav::getSampleRate() {
return this->sample_rate;
}
inline bool AudioLib::Wav::_checkFileExists(ifstream &file) {
return true;
}
// wav.h
#include <iostream>
#include <vector>
#include <fstream>
#include "types.h"
#include "../Signal/Signal.h"
using namespace std;
#ifndef _Wav_h
#define _Wav_h
enum ReadType {
NATIVE = 0, DOUBLE,
};
namespace AudioLib {
class Wav : public Signal {
public:
Wav();
Wav(const int N, const int M);
Wav(string theFile, ReadType type);
vector<double> const& Signal() const;
inline bool readHeader(ifstream& file);
inline bool readWav(ifstream &file, ReadType type);
inline bool _checkFileExists(ifstream &file);
int getSampleRate();
Wav& Emphasize();
Wav& Compress();
private:
#pragma pack(push, 1)
struct s_riff_hdr
{
char id[4];
uint32_t size;
char type[4];
};
struct s_chunk_hdr
{
char id[4];
uint32_t size;
};
struct s_wavefmt
{
uint16_t format_tag;
uint16_t channels;
uint32_t sample_rate;
uint32_t avg_bytes_sec;
uint16_t block_align;
};
struct s_wavefmtex
{
s_wavefmt fmt;
uint16_t bits_per_sample;
uint16_t extra_size;
};
struct s_pcmwavefmt
{
s_wavefmt fmt;
uint16_t bits_per_sample;
};
#pragma pack(pop)
char* data;
int sample_rate;
};
}
#endif
// Makefile
# Location of the Python Header files
# This is system dependant.
PYTHON_VERSION = 2.7
PYTHON_INCLUDE = /usr/include/python$(PYTHON_VERSION)
CFLAGS += -O3
CFLAGS += -std=c++11
CFLAGS += -pg -D_DEBUG -g -c -Wall
# location of the Boost Python include files and library
BOOST_INC = /usr/include
BOOST_LIB = /usr/lib
WAV_TARGET =
WAV_SOURCE = n
# Compile the .wav Python and Cpp file
$(WAV_TARGET).so: $(WAV_TARGET).o
g++ -shared -Wl,--export-dynamic $(WAV_TARGET).o -L$(BOOST_LIB) -lboost_python -lboost_python -L/usr/lib/python$(PYTHON_VERSION)/config -lpython$(PYTHON_VERSION) -o $(WAV_TARGET).so
$(WAV_TARGET).o: $(WAV_TARGET).hpp
g++ $(CFLAGS) -I$(PYTHON_INCLUDE) -I$(BOOST_INC) -fPIC -c $(WAV_TARGET).cpp