-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwav.h
157 lines (107 loc) · 3.92 KB
/
wav.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#ifndef WAV_H__
#define WAV_H__
#include <algorithm> // std::max
#include <sndfile.hh>
#include <stdio.h> // check() error printing
#include <string>
#include "array_ops.h" // for normalization (max())
//#include "Buffer.h" // Just to avoid changing the input: copy the data and perform normaliztion on the copy
#include "MatrixDeclaration.h" // Version for matrix of outputs write
#include "Buffers.h"
/** Reads a .wav file from disk. STUB: better use manually */
/*int read_mono_wav (const char *filename)
{
SndfileHandle file(filename);
printf("File %s has %u samples at a sample rate of %u.\n", filename, (uint)file.frames(), (uint)file.samplerate());
// STUB
return 0;
}*/
const double EPSILON = std::numeric_limits<double>::epsilon();
/// Check for the validity of a sound file and print the error report if an error occured.
namespace wav
{
int ok(SndfileHandle s)
{
if (s.error())
{
printf("\nError opening soundfile::%s\n\n", s.strError());
return 0;
}
return 1;
}
int mono(SndfileHandle s)
{
if (s.channels() == 1)
return 1;
else
return 0;
}
/** Writes a .wav file to disk.
If explicit_normalization == 0, the normalization factor is found automatically. Set a specific value in case you want to perform the normalization across several wav files.
*/
template <class T>
bool write_mono (const std::string &filename, const T *data, uint size, const int sample_rate_Hz, T explicit_normalization = 0)
{
const int format=SF_FORMAT_WAV | SF_FORMAT_PCM_16;
const int channels=1;
// Normalization performed on the copy and not on the data itself.
Guarantee(explicit_normalization >= 0, "Normalization must be > 0.");
T max;
if (explicit_normalization < EPSILON) // == 0
max = array_ops::max_abs(data, size);
else
max = explicit_normalization;
Buffer<T> data_copy(data, size); // Could be more efficient by not allocating before testing if normalization is required.
// If it is so close to 1: no point in normalizing
if (std::abs(max-1) > EPSILON)
data_copy /= max;
// Write the data to disk
SndfileHandle outfile(filename, SFM_WRITE, format, channels, sample_rate_Hz);
if (not outfile)
return false;
outfile.write(data_copy(), size);
return true;
}
// Every row in the matrix counts as a .wav for output.
template <class T>
bool write (const std::string &name, const Matrix<T> &data, const int sample_rate_Hz, const bool global_normalization = true)
{
const uint N_waves = data.rows();
const uint samples = data.cols();
Matrix<T> data_copy(data);
if (global_normalization)
data_copy /= array_ops::max_abs(data.raw(), data.size());
for (uint n=0; n < N_waves; ++n)
{
bool write = 0;
if (global_normalization)
write = wav::write_mono(name+std::to_string(n)+".wav", data_copy(n), samples, sample_rate_Hz, 1.0);
else
write = wav::write_mono(name+std::to_string(n)+".wav", data_copy(n), samples, sample_rate_Hz); // Let it normalize
if (! write)
return false;
}
return true;
}
template <class T>
bool write (const std::string &name, const Buffers<T> &data, const int sample_rate_Hz, const bool global_normalization = true)
{
const uint N_waves = data.buffers();
const uint samples = data.buffer_size();
Buffers<T> data_copy(data);
if (global_normalization)
data_copy /= data_copy.max_abs();
for (uint n=0; n < N_waves; ++n)
{
bool write = 0;
if (global_normalization)
write = wav::write_mono(name+std::to_string(n)+".wav", data_copy(n)(), samples, sample_rate_Hz, 1.0);
else
write = wav::write_mono(name+std::to_string(n)+".wav", data_copy(n)(), samples, sample_rate_Hz); // Let it normalize
if (! write)
return false;
}
return true;
}
} // End of namespace wav
#endif // WAV_H__