Skip to content

Commit

Permalink
Correct WT and Window handling og 16 full range wt files (#7703)
Browse files Browse the repository at this point in the history
wt files with full-range 16 bit ints (so 16-is-16 or flag
0x8 + 0x4 = 0xC) was broken in a couple of ways, but most
importnatly, didn't survive a save/restore roundtrip.

This fixes it in three ways

1. When converting 16-as-16 to float scale accordingly with
   a different function and leave the ints untouched
2. Modify the window oscillator so if it gets a 16-as-16 it
   reduces the height of the ints to be consistent with a
   15 with an extra shift, making I15 WT vs Window and
   I16 WT vs Window consistent
3. Make sure it streams properly. No change required but
   tested.

Addresses #7694

Update wt-tool to allow int16 and int15 options both
  • Loading branch information
baconpaul committed Jul 10, 2024
1 parent 7a641fe commit 41ceba4
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 16 deletions.
23 changes: 16 additions & 7 deletions scripts/wt-tool/wt-tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ def read_wt_header(fn):
flags = {}
flags["is_sample"] = (fl[0] & 0x01 != 0)
flags["loop_sample"] = (fl[0] & 0x02 != 0)
flags["format"] = "int16" if (fl[0] & 0x04 != 0) else "float32"

flags["format"] = "int16-full-range" if (fl[0] == 0xC) else "int16" if (fl[0] & 0x04 != 0) else "float32"
flags["samplebytes"] = 2 if (fl[0] & 0x04 != 0) else 4

header["flags"] = flags
Expand Down Expand Up @@ -74,7 +75,7 @@ def explode(fn, wav_dir):
wav_file.writeframes(bdata)


def create(fn, wavdir, norm):
def create(fn, wavdir, norm, intform):
onlyfiles = [f for f in listdir(wavdir) if (isfile(join(wavdir, f)) and f.endswith(".wav"))]
onlyfiles.sort()

Expand Down Expand Up @@ -122,8 +123,8 @@ def create(fn, wavdir, norm):
newrec[2 * i + 1] = nms
newdb.append(newrec)
databuffer = newdb
elif (norm == "peak"):
print("Normalizing to peak")
elif (norm == "peak" or norm == "peak16"):
print("Normalizing to " + norm)
peakp = 0
peakm = 0
for d in databuffer:
Expand All @@ -141,6 +142,11 @@ def create(fn, wavdir, norm):
peakp = -peakm
print("Peak value is ", peakp)
newdb = []

den = 16384.0
if (norm == "peak16"):
den = den * 2

for d in databuffer:
newrec = bytearray(len(d))

Expand All @@ -149,7 +155,7 @@ def create(fn, wavdir, norm):
ms = d[2 * i + 1]
if(ms >= 128):
ms -= 256
r = int((ls + ms * 256) * 16384.0 / peakp)
r = int((ls + ms * 256) * den / peakp)

nls = int(r % 256)
nms = int(r / 256)
Expand All @@ -169,7 +175,7 @@ def create(fn, wavdir, norm):
outf.write(b'vawt')
outf.write(nf.to_bytes(4, byteorder='little'))
outf.write((len(onlyfiles)).to_bytes(2, byteorder='little'))
outf.write(bytes([4, 0]))
outf.write(bytes([4 if (intform == "i15") else 12, 0]))
for d in databuffer:
outf.write(d)

Expand Down Expand Up @@ -199,7 +205,10 @@ def main():
Modes are 'none' leave input untouched;
'half' input wav are divided by 2 (so 2^16 range becomes 2^15 range);
'peak' input wav are scanned and re-peaked to 2^15.
'peak16' input wav are scanned and re-peaked to 2^15.
""")
parser.add_option("-i", "--int-range", dest="intrange", default="i15", metavar="INTRANGE",
help = "Int range for creating i16 files. Either i15 or i16")
(options, args) = parser.parse_args()

act = options.action
Expand All @@ -208,7 +217,7 @@ def main():
parser.print_help()
print("\nYou must specify a file and wav_dir for create")
else:
create(options.file, options.wav_dir, options.normalize)
create(options.file, options.wav_dir, options.normalize, options.intrange)
elif act == "explode":
if(options.file is None or options.wav_dir is None):
parser.print_help()
Expand Down
11 changes: 7 additions & 4 deletions src/common/dsp/Wavetable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -247,11 +247,14 @@ bool Wavetable::BuildWT(void *wdata, wt_header &wh, bool AppendSilence)
&((short *)wdata)[this->size * j], this->size);
if (this->flags & wtf_int16_is_16)
{
i16toi15_block(&this->TableI16WeakPointers[0][j][FIRoffsetI16],
&this->TableI16WeakPointers[0][j][FIRoffsetI16], this->size);
i162float_block(&this->TableI16WeakPointers[0][j][FIRoffsetI16],
this->TableF32WeakPointers[0][j], this->size);
}
else
{
i152float_block(&this->TableI16WeakPointers[0][j][FIRoffsetI16],
this->TableF32WeakPointers[0][j], this->size);
}
i152float_block(&this->TableI16WeakPointers[0][j][FIRoffsetI16],
this->TableF32WeakPointers[0][j], this->size);
}
}
else
Expand Down
32 changes: 28 additions & 4 deletions src/common/dsp/oscillators/WindowOscillator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ inline unsigned int BigMULr16(unsigned int a, unsigned int b)
return c >> 16u;
}

void WindowOscillator::ProcessWindowOscs(bool stereo, bool FM)
template <bool FM, bool Full16> void WindowOscillator::ProcessWindowOscs(bool stereo)
{
const unsigned int M0Mask = 0x07f8;
unsigned int SizeMask = (oscdata->wt.size << 16) - 1;
Expand Down Expand Up @@ -332,8 +332,9 @@ void WindowOscillator::ProcessWindowOscs(bool stereo, bool FM)
#endif

iWin[0] = (iWin[0] + iWin[1] + iWin[2] + iWin[3]) >> 13;
iWave[0] = (iWave[0] + iWave[1] + iWave[2] + iWave[3]) >> 13;
iWaveP1[0] = (iWaveP1[0] + iWaveP1[1] + iWaveP1[2] + iWaveP1[3]) >> 13;
iWave[0] = (iWave[0] + iWave[1] + iWave[2] + iWave[3]) >> (13 + (Full16 ? 1 : 0));
iWaveP1[0] =
(iWaveP1[0] + iWaveP1[1] + iWaveP1[2] + iWaveP1[3]) >> (13 + (Full16 ? 1 : 0));

iWave[0] = (int)((1.f - FTable) * iWave[0] + FTable * iWaveP1[0]);

Expand Down Expand Up @@ -414,7 +415,30 @@ void WindowOscillator::process_block(float pitch, float drift, bool stereo, bool
}
}

ProcessWindowOscs(stereo, FM);
bool is16 = oscdata->wt.flags & wtf_int16_is_16;

if (FM)
{
if (is16)
{
ProcessWindowOscs<true, true>(stereo);
}
else
{
ProcessWindowOscs<true, false>(stereo);
}
}
else
{
if (is16)
{
ProcessWindowOscs<false, true>(stereo);
}
else
{
ProcessWindowOscs<false, false>(stereo);
}
}

// int32 -> float conversion
__m128 scale = _mm_load1_ps(&OutAttenuation);
Expand Down
2 changes: 1 addition & 1 deletion src/common/dsp/oscillators/WindowOscillator.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ class WindowOscillator : public Oscillator
void applyFilter();
template <bool is_init> void update_lagvals();

void ProcessWindowOscs(bool stereo, bool FM);
template <bool FM, bool Full16> void ProcessWindowOscs(bool stereo);
lag<double> FMdepth[MAX_UNISON];
lag<float> l_morph;

Expand Down
9 changes: 9 additions & 0 deletions src/common/dsp/vembertech/basic_dsp.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@ inline void i152float_block(short *s, float *f, int n)
}
}

inline void i162float_block(short *s, float *f, int n)
{
const float scale = 1.f / (16384.f * 2);
for (int i = 0; i < n; i++)
{
f[i] = (float)s[i] * scale;
}
}

inline void i16toi15_block(short *s, short *o, int n)
{
for (int i = 0; i < n; i++)
Expand Down

0 comments on commit 41ceba4

Please sign in to comment.