Last active
February 9, 2020 22:10
-
-
Save jpcima/9e43f08ed3a39e0363115c1ed449740e to your computer and use it in GitHub Desktop.
Wavetable generator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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