Skip to content

Commit

Permalink
auto-remove DC offset when importing wavs
Browse files Browse the repository at this point in the history
  • Loading branch information
yuxshao committed Jun 22, 2024
1 parent 71e4aa2 commit 27345e1
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 0 deletions.
66 changes: 66 additions & 0 deletions src/pxtone/pxtnPulse_PCM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,8 @@ pxtnERR pxtnPulse_PCM::read(pxtnDescriptor *doc, uint32_t *basic_key) {
(repeat_data_end - repeat_data_start) +
repeat_data_start];
}

_removeDcOffset();
term:

if (res != pxtnOK && _p_smp) {
Expand All @@ -208,6 +210,70 @@ pxtnERR pxtnPulse_PCM::read(pxtnDescriptor *doc, uint32_t *basic_key) {
return res;
}

void pxtnPulse_PCM::_removeDcOffset() {
int64_t total_offset[2] = {0, 0};
int16_t min[2] = {0, 0};
int16_t max[2] = {0, 0};

// Determine average, min, and max dc offset of sample
for (uint32_t i = 0; i < _smp_body; ++i) {
for (uint32_t ch = 0; ch < _ch; ++ch) {
int16_t pcm = 0;
uint32_t pos = (i * _ch + ch) * (_bps / 8);
switch (_bps) {
case 8:
pcm = _p_smp[pos];
break;
case 16:
pcm = *((int16_t *)(&_p_smp[pos]));
break;
}
total_offset[ch] += pcm;
if (pcm < min[ch]) min[ch] = pcm;
if (pcm > max[ch]) max[ch] = pcm;
}
}

int16_t min_bound, max_bound;
switch (_bps) {
case 8:
min_bound = 0;
max_bound = 255;
break;
case 16:
min_bound = -32768;
max_bound = 32767;
break;
}

// Determine adjustment. It ought to be the average value, but we clamp it if
// it would cause the min or max value to be out of bounds
// (Maybe we can do some kind of lerping instead since if we clamp it we
// technically wouldn't be removing all of the DC offset)
int16_t adjustment[2];
for (uint32_t ch = 0; ch < _ch; ++ch) {
int64_t adj = -total_offset[ch] / _smp_body;
if (min[ch] + adj < min_bound) adj = min_bound - min[ch];
if (max[ch] + adj > max_bound) adj = max_bound - max[ch];
adjustment[ch] = adj;
}

// Apply offset
for (uint32_t i = 0; i < _smp_body; ++i) {
for (uint32_t ch = 0; ch < _ch; ++ch) {
uint32_t pos = (i * _ch + ch) * (_bps / 8);
switch (_bps) {
case 8:
_p_smp[pos] += adjustment[ch];
break;
case 16:
*((int16_t *)(&_p_smp[pos])) += adjustment[ch];
break;
}
}
}
}

bool pxtnPulse_PCM::write(pxtnDescriptor *doc, const char *pstrLIST) const {
if (!_p_smp) return false;

Expand Down
2 changes: 2 additions & 0 deletions src/pxtone/pxtnPulse_PCM.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ class pxtnPulse_PCM {
bool _Convert_BitPerSample(int32_t new_bps);
bool _Convert_SamplePerSecond(int32_t new_sps);

void _removeDcOffset();

public:
pxtnPulse_PCM();
~pxtnPulse_PCM();
Expand Down

0 comments on commit 27345e1

Please sign in to comment.