HART  0.2.0
High level Audio Regression and Testing
Loading...
Searching...
No Matches
hart_wavwriter.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <cmath> // delete me
4#include <string>
5#include <vector>
6
7#include "dependencies/choc/platform/choc_DisableAllWarnings.h"
8#include "dependencies/dr_libs/dr_wav.h"
9#include "dependencies/choc/platform/choc_ReenableAllWarnings.h"
10
13#include "hart_units.hpp"
15
16namespace hart
17{
18
19template <typename SampleType>
21{
22public:
23 static void writeBuffer (const AudioBuffer<SampleType>& buffer, const std::string& fileName, double sampleRateHz, WavFormat wavFormat = WavFormat::pcm24)
24 {
25 const size_t numFrames = buffer.getNumFrames();
26 const size_t numChannels = buffer.getNumChannels();
27
28 drwav drWavHandle;
29 drwav_data_format drWavFormat;
30 drWavFormat.container = drwav_container_riff;
31 drWavFormat.channels = static_cast<drwav_uint16> (numChannels);
32 drWavFormat.sampleRate = static_cast<drwav_uint32> (sampleRateHz);
33
34 switch (wavFormat)
35 {
37 drWavFormat.format = DR_WAVE_FORMAT_PCM;
38 drWavFormat.bitsPerSample = 16;
39 break;
41 drWavFormat.format = DR_WAVE_FORMAT_PCM;
42 drWavFormat.bitsPerSample = 24;
43 break;
45 drWavFormat.format = DR_WAVE_FORMAT_PCM;
46 drWavFormat.bitsPerSample = 32;
47 break;
49 drWavFormat.format = DR_WAVE_FORMAT_IEEE_FLOAT;
50 drWavFormat.bitsPerSample = 32;
51 break;
52 }
53
54 if (! drwav_init_file_write (&drWavHandle, fileName.c_str(), &drWavFormat, nullptr))
55 HART_THROW_OR_RETURN_VOID (hart::IOError, "Failed to init WAV writer");
56
57 switch (wavFormat)
58 {
60 {
61 std::vector<float> pcmData (numFrames * numChannels);
62
63 for (size_t frame = 0; frame < numFrames; ++frame)
64 {
65 for (size_t channel = 0; channel < numChannels; ++channel)
66 pcmData[frame * numChannels + channel] = buffer[channel][frame];
67 }
68
69 drwav_write_pcm_frames (&drWavHandle, numFrames, pcmData.data());
70 break;
71 }
72
74 {
75 std::vector<int16_t> pcmData (numFrames * numChannels);
76 constexpr double scale = 32767.0;
77
78 for (size_t frame = 0; frame < numFrames; ++frame)
79 {
80 for (size_t channel = 0; channel < numChannels; ++channel)
81 {
82 const double sample = static_cast<double> (buffer[channel][frame]);
83 const int16_t pcmValue = static_cast<int16_t> (std::round (hart::clamp (scale * sample, -scale, scale)));
84 pcmData[frame * numChannels + channel] = pcmValue;
85 }
86 }
87
88 drwav_write_pcm_frames (&drWavHandle, numFrames, pcmData.data());
89 break;
90 }
91
93 {
94 std::vector<int32_t> pcmData (numFrames * numChannels);
95 constexpr double scale = 2147483647.0;
96
97 for (size_t frame = 0; frame < numFrames; ++frame)
98 {
99 for (size_t channel = 0; channel < numChannels; ++channel)
100 {
101 const double sample = static_cast<double> (buffer[channel][frame]);
102 const int32_t pcmValue = static_cast<int32_t> (std::round (hart::clamp (scale * sample, -scale, scale)));
103 pcmData[frame * numChannels + channel] = pcmValue;
104 }
105 }
106
107 drwav_write_pcm_frames (&drWavHandle, numFrames, pcmData.data());
108 break;
109 }
110
111 case WavFormat::pcm24:
112 {
113 std::vector<uint8_t> pcmData (numFrames * numChannels * 3);
114 constexpr double scale = 8388607.0;
115
116 for (size_t frame = 0; frame < numFrames; ++frame)
117 {
118 for (size_t channel = 0; channel < numChannels; ++channel)
119 {
120 const double sample = static_cast<double> (buffer[channel][frame]);
121 const int32_t pcmValue = static_cast<int32_t> (std::round (hart::clamp (scale * sample, -scale, scale)));
122 size_t idx = (frame * numChannels + channel) * 3;
123 pcmData[idx] = static_cast<uint8_t> (pcmValue & 0xff);
124 pcmData[idx + 1] = static_cast<uint8_t> ((pcmValue >> 8) & 0xff);
125 pcmData[idx + 2] = static_cast<uint8_t> ((pcmValue >> 16) & 0xff);
126 }
127 }
128
129 drwav_write_pcm_frames (&drWavHandle, numFrames, pcmData.data());
130 break;
131 }
132 }
133
134 drwav_uninit (&drWavHandle);
135 }
136};
137
138} // namespace hart
static void writeBuffer(const AudioBuffer< SampleType > &buffer, const std::string &fileName, double sampleRateHz, WavFormat wavFormat=WavFormat::pcm24)
NumericType clamp(const NumericType &value, const NumericType &low, const NumericType &high)
std::clamp() replacement for C++11
#define HART_THROW_OR_RETURN_VOID(ExceptionType, message)