[music-dsp] designing wavetables
Laurent de Soras [Ohm Force]
laurent at ohmforce.com
Thu May 8 06:12:00 EDT 2003
Urs Heckmann wrote:
>
> I guess the best way to do this is using iFFT with 1024 real values
> only (imaginary values introduce phase shift and screw up zero
> crossings?!?), where for each bandlimitted subtable a certain range of
> values is zeroed out.
You can also use my FFTReal class <http://ldesoras.free.fr/src/FFTReal-1.03.zip>,
which performs FFT on real numbers and is roughly equivalent
to the FHT regarding CPU load.
I have also a function to build the mipmaps. The following code uses
an auxiliary class not given here to store the wavetables, I think
its members are self-explaining :
void build_mipmaps (WavetableDataType &wavetable)
{
// Copy first table into temporary zone
const int bigger_table = wavetable.get_nbr_tables () - 1;
WavetableDataType::DataType * bwt_ptr = wavetable.use_table (bigger_table);
std::vector <FFTReal::flt_t> temp (WavetableDataType::MAX_SIZE);
for (long i = 0; i < WavetableDataType::MAX_SIZE; ++i)
{
temp [i] = static_cast <FFTReal::flt_t> (bwt_ptr [i]);
}
FFTReal fft (WavetableDataType::MAX_SIZE);
std::vector <FFTReal::flt_t> bins (WavetableDataType::MAX_SIZE);
// Get spectrum data of the longest wavetable
fft.do_fft (&bins [0], &temp [0]);
fft.rescale (&bins [0]);
long nbr_used_bins = _max_table_size / 2;
const long imag_index = nbr_used_bins;
// Build all other wavetables
for (int table = bigger_table - 1; table >= 0; --table)
{
// Reduce spectrum bandwidth by 1/2
const long old_nbr_used_bins = nbr_used_bins;
nbr_used_bins /= 2;
for (long bin = nbr_used_bins + 1; bin < old_nbr_used_bins; ++bin)
{
bins [bin] = 0;
bins [imag_index + bin] = 0;
}
bins [old_nbr_used_bins] = 0; // Kill real part of old nyquist freq
bins [imag_index + nbr_used_bins] = 0; // Kill imag part of new nyquist freq
// Transform
fft.do_ifft (&bins [0], &temp [0]);
// Decimate if required
const long table_len = wavetable.get_table_len (table);
const long step = _max_table_size / table_len;
for (long pos = 0; pos < table_len; ++pos)
{
const WavetableDataType::DataType val =
static_cast <WavetableDataType::DataType> (temp [pos * step]);
wavetable.set_sample (table, pos, val);
}
}
wavetable.update_all_tables_unroll ();
}
I have tweaked it a bit to isolate it from its context and
to make it work stand-alone, so I hope I haven't introduced
too much errors ;). Tell me if you need more info.
-- Laurent
==================================+========================
Laurent de Soras | Ohm Force
DSP developer & Software designer | Digital Audio Software
mailto:laurent at ohmforce.com | http://www.ohmforce.com
==================================+========================
More information about the music-dsp
mailing list