diff options
Diffstat (limited to 'src/wavetable.c')
-rw-r--r-- | src/wavetable.c | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/src/wavetable.c b/src/wavetable.c new file mode 100644 index 0000000..ab3308a --- /dev/null +++ b/src/wavetable.c @@ -0,0 +1,182 @@ +#include "wavetable.h" +#include <sndfile.h> + +static wave_t wvt_sine_data; +static wave_t wvt_saw_data; +static wave_t wvt_digisaw_data; +static wave_t wvt_tri_data; +static wave_t wvt_sqr_data; +static wave_t wvt_sound_data; + + +void +wvt_sine_init(size_t size) +{ + wvt_sine_data.size = size; + wvt_sine_data.data = (float *) malloc(sizeof(float) * size); + for (int i = 0; i < size; i++) { + wvt_sine_data.data[i] = sinf(2 * M_PI * i / size); + } +} + +void +wvt_saw_init(size_t size) +{ + wvt_saw_data.size = size; + wvt_saw_data.data = (float *) malloc(sizeof(float) * size); + for (int i = 0; i < size; i++) { + float dOutput = 0.0; + for (float n = 1.0; n < 25; n++) + dOutput += sinf(n * 2.0 * M_PI * i / size) / n; + wvt_saw_data.data[i] = 0.6 * dOutput; + } +} + +void +wvt_digisaw_init(size_t size) +{ + wvt_digisaw_data.size = size; + wvt_digisaw_data.data = (float *) malloc(sizeof(float) * size); + for (int i = 0; i < size; i++) { + wvt_digisaw_data.data[i] = (float)i / size; + } +} + +void +wvt_sqr_init(size_t size) +{ + wvt_sqr_data.size = size; + wvt_sqr_data.data = (float *) malloc(sizeof(float) * size); + for (int i = 0; i < size; i++) { + if (i < size / 2) { + wvt_sqr_data.data[i] = -1.0f; + } else { + wvt_sqr_data.data[i] = 1.0f; + } + } +} + +void +wvt_sound_init(char * path) +{ + SNDFILE* file; + SF_INFO fileInfo; + int numSamplesRead; + + // Open the WAV file + file = sf_open(path, SFM_READ, &fileInfo); + if (!file) { + printf("Failed to open the WAV file: %s\n", sf_strerror(NULL)); + return; + } + printf("frames: %ld sr: %d chan: %d format: %d sections: %d seekable: %d\n", fileInfo.frames, fileInfo.samplerate, fileInfo.channels, fileInfo.format, fileInfo.sections, fileInfo.seekable); + // Ensure the WAV file has only one channel + if (fileInfo.channels != 1) { + printf("Only mono WAV files are supported.\n"); + sf_close(file); + return; + } + + wvt_sound_data.size = fileInfo.frames ; + wvt_sound_data.data = (float *) malloc(sizeof(float) * fileInfo.frames); + + // Read the WAV file into the buffer + numSamplesRead = sf_readf_float(file, wvt_sound_data.data, fileInfo.frames); + + float max = -1000; + float min = 1000; + for (int i = 0; i < numSamplesRead; i++) { + float s = wvt_sound_data.data[i]; + // printf("Sample %d: %f\n", i, s); + if (s < min) min = s; + if (s > max) max = s; + } + printf("Min: %f Max: %f\n", min, max); + + // Close the WAV file + sf_close(file); +} + +void +wvt_init() +{ + wvt_sine_init(44100); + wvt_saw_init(128); + wvt_digisaw_init(48000); + wvt_sqr_init(48000); + wvt_tri_data.size = 2; + wvt_tri_data.data = (float *) malloc(sizeof(float) * 2); + wvt_tri_data.data[0] = -1.0f; + wvt_tri_data.data[1] = 1.0f; + wvt_sound_init("/home/gramanas/code/synth-project/waves/test1.wav"); +} + + +float +wvt_gen(wave_t * wave, float * index, float freq, int sample_rate) +{ + if (*index >= wave->size) *index = 0; + + int current_index = (int)*index; + int next_index = current_index + 1 >= wave->size ? 0 : current_index + 1; + + // linear interpolation between current_index and next_index + float m = (wave->data[next_index] - wave->data[current_index]) / (1 - 0); + float b = wave->data[current_index] /* + m * 0 */; + + // the value to pick + float x = *index - current_index; + + float sample = m * x + b; + float step = freq * ((float)wave->size / sample_rate); + + *index += step; + if (*index >= wave->size) { + *index -= wave->size; + } + + return sample; +} + +float +wvt_next(float (* wvt_fun)(float *, float, int), float freq, int sample_rate, float * wvt_index) +{ + float sample = wvt_fun(wvt_index, freq, sample_rate); + return sample; +} + +float +wvt_saw(float * index, float freq, int sample_rate) +{ + return wvt_gen(&wvt_saw_data, index, freq, sample_rate); +} + +float +wvt_digisaw(float * index, float freq, int sample_rate) +{ + return wvt_gen(&wvt_digisaw_data, index, freq, sample_rate); +} + +float +wvt_sine(float * index, float freq, int sample_rate) +{ + return wvt_gen(&wvt_sine_data, index, freq, sample_rate); +} + +float +wvt_tri(float * index, float freq, int sample_rate) +{ + return wvt_gen(&wvt_tri_data, index, freq, sample_rate); +} + +float +wvt_sqr(float * index, float freq, int sample_rate) +{ + return wvt_gen(&wvt_sqr_data, index, freq, sample_rate); +} + +float +wvt_sound(float * index, float freq, int sample_rate) +{ + return wvt_gen(&wvt_sound_data, index, freq, sample_rate); +} |