Skip to content

Commit cc88988

Browse files
committed
Implement int wav encode
1 parent 0221601 commit cc88988

File tree

1 file changed

+48
-20
lines changed

1 file changed

+48
-20
lines changed

src/framework/audio/engine/internal/export/wavencoder.cpp

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,14 @@
2222

2323
#include "wavencoder.h"
2424

25+
#include "../dsp/audiomathutils.h"
26+
2527
#include "log.h"
2628

2729
using namespace muse::audio;
2830
using namespace muse::audio::encode;
2931

3032
struct WavHeader {
31-
enum class WavFileType {
32-
int16, // 16 bit signed integer
33-
float32
34-
};
35-
3633
uint32_t chunkSize = 0;
3734
uint16_t audioChannelsNumber = 0;
3835
uint16_t bitsPerSample = 0;
@@ -42,7 +39,7 @@ struct WavHeader {
4239

4340
void write(std::ofstream& stream)
4441
{
45-
const uint32_t bytesPerSample = 4;
42+
const uint32_t bytesPerSample = bitsPerSample / 8;
4643
const uint32_t sampleDataLength = audioChannelsNumber * samplesPerChannel * bytesPerSample;
4744
const uint32_t headerLength = 20 + chunkSize + 8;
4845
const uint32_t file_length = headerLength + sampleDataLength;
@@ -58,7 +55,7 @@ struct WavHeader {
5855

5956
writeTagData<uint32_t>(stream, chunkSize);
6057
writeTagData<uint16_t>(stream, code);
61-
writeTagData<uint16_t>(stream, 2);
58+
writeTagData<uint16_t>(stream, audioChannelsNumber);
6259
writeTagData<uint32_t>(stream, sampleRate);
6360
writeTagData<uint32_t>(stream, bytesPerSec);
6461
writeTagData<uint16_t>(stream, bytesPerFrame);
@@ -89,8 +86,25 @@ size_t WavEncoder::encode(samples_t samplesPerChannel, const float* input)
8986

9087
WavHeader header;
9188
header.chunkSize = 18; // 18 is 2 bytes more to include cbsize field / extension size
92-
header.bitsPerSample = 32;
93-
header.code = 3; // IEEE_FLOAT = 3, PCM = 1
89+
90+
switch (m_format.sampleFormat) {
91+
case AudioSampleFormat::Int16:
92+
header.bitsPerSample = 16;
93+
header.code = 1; // PCM
94+
break;
95+
case AudioSampleFormat::Int24:
96+
header.bitsPerSample = 24;
97+
header.code = 1; // PCM
98+
break;
99+
case AudioSampleFormat::Float32:
100+
header.bitsPerSample = 32;
101+
header.code = 3; // IEEE_FLOAT
102+
break;
103+
case AudioSampleFormat::Undefined:
104+
default:
105+
return 0;
106+
}
107+
94108
header.audioChannelsNumber = m_format.outputSpec.audioChannelCount;
95109
header.sampleRate = m_format.outputSpec.sampleRate;
96110
header.samplesPerChannel = samplesPerChannel;
@@ -99,20 +113,34 @@ size_t WavEncoder::encode(samples_t samplesPerChannel, const float* input)
99113

100114
int total = header.samplesPerChannel;
101115
int progressStep = (total * 5) / 100; // every 5%
102-
QVector<samples_t> progressValues;
103-
for (samples_t sampleIdx = 0; sampleIdx < header.samplesPerChannel;) {
104-
progressValues << sampleIdx;
105-
sampleIdx += progressStep;
106-
}
107116

108-
for (samples_t sampleIdx = 0; sampleIdx < header.samplesPerChannel; ++sampleIdx) {
109-
for (audioch_t audioChNum = 0; audioChNum < m_format.outputSpec.audioChannelCount; ++audioChNum) {
110-
int idx = sampleIdx * m_format.outputSpec.audioChannelCount + audioChNum;
111-
m_fileStream.write(reinterpret_cast<const char*>(input + idx), 4);
117+
const int channels = m_format.outputSpec.audioChannelCount;
118+
119+
if (m_format.sampleFormat == AudioSampleFormat::Float32) {
120+
for (samples_t sampleIdx = 0; sampleIdx < header.samplesPerChannel; ++sampleIdx) {
121+
for (audioch_t audioChNum = 0; audioChNum < channels; ++audioChNum) {
122+
int idx = sampleIdx * channels + audioChNum;
123+
m_fileStream.write(reinterpret_cast<const char*>(input + idx), 4);
124+
}
125+
if (sampleIdx % progressStep == 0) {
126+
m_progress.progress(sampleIdx, total);
127+
}
112128
}
129+
} else {
130+
const int bits = header.bitsPerSample;
131+
const int bytesToWrite = bits / 8;
132+
133+
for (samples_t sampleIdx = 0; sampleIdx < header.samplesPerChannel; ++sampleIdx) {
134+
for (audioch_t audioChNum = 0; audioChNum < channels; ++audioChNum) {
135+
int idx = sampleIdx * channels + audioChNum;
136+
137+
int32_t sampleInt = dsp::convertFloatSamples<int32_t>(input[idx], bits);
113138

114-
if (progressValues.contains(sampleIdx)) {
115-
m_progress.progress(sampleIdx, total);
139+
m_fileStream.write(reinterpret_cast<const char*>(&sampleInt), bytesToWrite);
140+
}
141+
if (sampleIdx % progressStep == 0) {
142+
m_progress.progress(sampleIdx, total);
143+
}
116144
}
117145
}
118146

0 commit comments

Comments
 (0)