NumeRe v1.1.4
NumeRe: Framework für Numerische Rechnungen
wavfile.cpp
Go to the documentation of this file.
1/*****************************************************************************
2 NumeRe: Framework fuer Numerische Rechnungen
3 Copyright (C) 2021 Erik Haenel et al.
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17******************************************************************************/
18
19#include "wavfile.hpp"
20#include <cstring>
21
22#define PCM 0x0001
23
24namespace Audio
25{
35 static double convertFromUnsigned(double val)
36 {
37 return val > 1.0 ? val-2.0 : val;
38 }
39
40
49 static double getMaxVal(uint16_t bitdepth)
50 {
51 return (1 << (bitdepth-1)) - 1;
52 }
53
61 WavFile::WavFile(const std::string& sFileName)
62 {
63 m_WavFileStream.open(sFileName.c_str(), std::ios_base::in | std::ios_base::binary);
64 sName = sFileName;
65
66 if (!readHeader())
67 m_WavFileStream.close();
68 }
69
70
76 {
77 closeFile();
78 }
79
80
91 {
92 if (!m_WavFileStream.good())
93 {
95 return false;
96 }
97 else
98 {
99 char headerInfo[5] = {0,0,0,0,0};
100 m_WavFileStream.read(headerInfo, 4);
101
102 if (strcmp(headerInfo, "RIFF"))
103 {
105 return false;
106 }
107
108 m_WavFileStream.read(headerInfo, 4);
109 m_WavFileStream.read(headerInfo, 4);
110
111 if (strcmp(headerInfo, "WAVE"))
112 {
114 return false;
115 }
116
117 m_WavFileStream.seekg(20);
118 m_WavFileStream.read((char*)&m_Header, sizeof(WavFileHeader));
119
120 if (m_Header.formatTag != PCM)
121 {
123 return false;
124 }
125
126 m_WavFileStream.seekg(40);
127 m_WavFileStream.read((char*)&m_DataBlockLength, 4);
128 }
129
130 return true;
131 }
132
133
142 {
143 if (m_WavFileStream.is_open())
144 {
145 m_WavFileStream.seekp(0, std::ios_base::end);
146 uint32_t pos = m_WavFileStream.tellp()-8LL;
147 m_WavFileStream.seekp(4);
148 m_WavFileStream.write((char*)&pos, 4);
149 m_WavFileStream.seekp(40);
150 pos -= 36;
151 m_WavFileStream.write((char*)&pos, 4);
152 m_WavFileStream.close();
153 }
154 }
155
156
168 {
169 closeFile();
170
171 // prepare header
176
177 m_WavFileStream.open(sName.c_str(), std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
178 m_WavFileStream.write("RIFF WAVEfmt ", 16);
179 uint32_t nSize = 16;
180 m_WavFileStream.write((char*)&nSize, 4);
181 m_WavFileStream.write((char*)&m_Header, sizeof(WavFileHeader));
182 m_WavFileStream.write("data ", 8);
183 }
184
185
193 void WavFile::write(const Sample& sample)
194 {
195 if (m_WavFileStream.is_open() && m_WavFileStream.good())
196 {
197 int16_t channelvalue = sample.leftOrMono * getMaxVal(16);
198 m_WavFileStream.write((char*)&channelvalue, 2);
199
200 if (m_Header.channels > 1 && !std::isnan(sample.right))
201 {
202 channelvalue = sample.right * getMaxVal(16);
203 m_WavFileStream.write((char*)&channelvalue, 2);
204 }
205 }
206 }
207
208
216 {
217 uint32_t samples[2] = {0,0};
218
219 if (m_Header.channels == 1)
220 {
221 m_WavFileStream.read((char*)samples, m_Header.blockAlign);
223 }
224 else
225 {
226 m_WavFileStream.read((char*)&samples[0], m_Header.blockAlign/m_Header.channels);
227 m_WavFileStream.read((char*)&samples[1], m_Header.blockAlign/m_Header.channels);
229 }
230
231 return Sample(NAN);
232 }
233
234
243 std::vector<Sample> WavFile::readSome(size_t len) const
244 {
245 std::vector<Sample> vSamples;
246
247 for (size_t i = 0; i < len; i++)
248 {
249 if (m_WavFileStream.eof() || !m_WavFileStream.good())
250 break;
251
252 vSamples.push_back(read());
253 }
254
255 return vSamples;
256 }
257
258
267 void WavFile::writeSome(const std::vector<Sample> vSamples)
268 {
269 for (const Sample& s : vSamples)
270 {
271 write(s);
272 }
273 }
274}
275
std::string sName
Definition: wavfile.hpp:55
virtual std::vector< Sample > readSome(size_t len) const override
Read a block of samples from the audio stream.
Definition: wavfile.cpp:243
bool readHeader()
Private member function to read the wave file header to memory. It will ensure that the current file ...
Definition: wavfile.cpp:90
WavFileHeader m_Header
Definition: wavfile.hpp:57
virtual void write(const Sample &sample) override
Write a sample to the audio stream.
Definition: wavfile.cpp:193
virtual ~WavFile()
Destructor. Will close the file stream and update the header.
Definition: wavfile.cpp:75
virtual void writeSome(const std::vector< Sample > vSamples) override
Write a block of samples to the audio stream.
Definition: wavfile.cpp:267
void closeFile()
Updates the wave file header, which is currently open, and closes the file afterwards.
Definition: wavfile.cpp:141
virtual Sample read() const override
Read a sample from the audio stream.
Definition: wavfile.cpp:215
virtual void newFile() override
Prepares the wave file header for a new file, opens the stream and writes the header to the file....
Definition: wavfile.cpp:167
std::fstream m_WavFileStream
Definition: wavfile.hpp:56
WavFile(const std::string &sFileName)
Constructor. Tries to open the wave file, if it exists.
Definition: wavfile.cpp:61
uint32_t m_DataBlockLength
Definition: wavfile.hpp:58
static double getMaxVal(uint16_t bitdepth)
Calculates the maximal value available with the current bitdepth.
Definition: wavfile.cpp:49
static double convertFromUnsigned(double val)
Applies the necessary conversion to obtain a signed floating point value from an unsigned integer.
Definition: wavfile.cpp:35
CONSTCD11 std::enable_if<!std::chrono::treat_as_floating_point< T >::value, T >::type trunc(T t) NOEXCEPT
Definition: date.h:1113
bool isnan(const value_type &v)
Definition: muParserDef.h:379
Defines a sample in the audio stream, i.e. a single value per channel.
Definition: audiofile.hpp:33
double right
Definition: audiofile.hpp:35
double leftOrMono
Definition: audiofile.hpp:34
This structure represents the central part of the wave file header in a format, which can be directly...
Definition: wavfile.hpp:34
uint16_t bitsPerSample
Definition: wavfile.hpp:40
uint32_t sampleRate
Definition: wavfile.hpp:37
uint16_t blockAlign
Definition: wavfile.hpp:39
uint32_t bytesPerSecond
Definition: wavfile.hpp:38
uint16_t formatTag
Definition: wavfile.hpp:35
#define PCM
Definition: wavfile.cpp:22