Skip to content

Instantly share code, notes, and snippets.

@jpcima
Last active February 9, 2020 22:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jpcima/9e43f08ed3a39e0363115c1ed449740e to your computer and use it in GitHub Desktop.
Save jpcima/9e43f08ed3a39e0363115c1ed449740e to your computer and use it in GitHub Desktop.
Wavetable generator
#include "kiss_fftr.h"
#include <memory>
#include <complex>
static std::complex<kiss_fft_scalar> make_bin(double amplitude, double phase = 0.0)
{
return std::polar<kiss_fft_scalar>(0.5 * amplitude, phase + M_PI / 2);
}
static void make_sine(kiss_fft_scalar *wave, int size, double amplitude)
{
typedef std::complex<kiss_fft_scalar> cpx;
std::unique_ptr<cpx[]> spec{new cpx[size / 2 + 1]{}};
spec[1] = make_bin(amplitude);
kiss_fftr_cfg cfg = kiss_fftr_alloc(size, true, nullptr, nullptr);
kiss_fftri(cfg, reinterpret_cast<kiss_fft_cpx *>(spec.get()), wave);
kiss_fftr_free(cfg);
}
static void make_triangle(kiss_fft_scalar *wave, int size, double amplitude)
{
typedef std::complex<kiss_fft_scalar> cpx;
std::unique_ptr<cpx[]> spec{new cpx[size / 2 + 1]{}};
for (int i = 1, s = 0; i < size / 2 + 1; i += 2, s = !s) {
spec[i] = make_bin(
amplitude * (8 / (M_PI * M_PI)) * (1.0 / (i * i)),
s ? 0.0 : M_PI);
}
kiss_fftr_cfg cfg = kiss_fftr_alloc(size, true, nullptr, nullptr);
kiss_fftri(cfg, reinterpret_cast<kiss_fft_cpx *>(spec.get()), wave);
kiss_fftr_free(cfg);
}
static void make_saw(kiss_fft_scalar *wave, int size, double amplitude)
{
typedef std::complex<kiss_fft_scalar> cpx;
std::unique_ptr<cpx[]> spec{new cpx[size / 2 + 1]{}};
for (int i = 1; i < size / 2 + 1; ++i) {
spec[i] = make_bin(
amplitude * (2.0 / M_PI) / i,
(i & 1) ? 0.0 : M_PI);
}
kiss_fftr_cfg cfg = kiss_fftr_alloc(size, true, nullptr, nullptr);
kiss_fftri(cfg, reinterpret_cast<kiss_fft_cpx *>(spec.get()), wave);
kiss_fftr_free(cfg);
}
static void make_square(kiss_fft_scalar *wave, int size, double amplitude)
{
typedef std::complex<kiss_fft_scalar> cpx;
std::unique_ptr<cpx[]> spec{new cpx[size / 2 + 1]{}};
for (int i = 1; i < size / 2 + 1; i += 2)
spec[i] = make_bin(amplitude * (4.0 / M_PI) / i, M_PI);
kiss_fftr_cfg cfg = kiss_fftr_alloc(size, true, nullptr, nullptr);
kiss_fftri(cfg, reinterpret_cast<kiss_fft_cpx *>(spec.get()), wave);
kiss_fftr_free(cfg);
}
#include <cstdio>
int main(int argc, char *argv[])
{
int waveno = 0;
float amplitude = 1.0;
int size = 256;
if (argc > 1)
waveno = std::stoi(argv[1]);
if (argc > 2)
amplitude = std::stof(argv[2]);
if (argc > 3)
size = std::stoi(argv[3]);
float *wave = new float[size];
switch (waveno) {
default: case 0:
make_sine(wave, size, amplitude);
break;
case 1:
make_triangle(wave, size, amplitude);
break;
case 2:
make_saw(wave, size, amplitude);
break;
case 3:
make_square(wave, size, amplitude);
break;
}
for (int i = 0; i < size; ++i)
printf("%d %e\n", i, wave[i]);
delete[] wave;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment