#include "synth_common.h" #include "osc.h" #include #include #include float osc_interpolate(float offset, float start, float end) { // linear interpolation between start and end float m = (end - start) / (1 - 0); float b = start /* + m * 0 */; // the value to pick float x = offset - (int)offset; return m * x + b; } /** * Takes a floating-point position (offset) in the oscillator/buffer. * Wraps it so it stays between osc->start and osc->len - 1 (cyclically). * Converts it to an integer index. * Returns the next index, wrapping back to osc->start if it reaches the end. */ int osc_next_index(osc_t * osc, float offset) { if (offset >= osc->len) offset = fmodf(osc->start + offset, osc->len - osc->start); if (offset < osc->start) offset = osc->start + fmodf(osc->start + offset, osc->len - osc->start); int current_index = (int)offset; return current_index + 1 >= osc->len ? osc->start : current_index + 1; } // TODO same from AI: check it /* int */ /* osc_next_index(osc_t *osc, float offset) { */ /* float range = osc->len - osc->start; */ /* // Wrap offset into the [start, len) range */ /* offset = osc->start + fmodf(offset - osc->start + range, range); */ /* // Get integer index and advance */ /* int next = (int)offset + 1; */ /* return (next >= osc->len) ? osc->start : next; */ /* } */ float osc_next_offset(osc_t * osc, float f, float offset) { if (offset >= osc->len) offset = fmodf(osc->start + offset, osc->len - osc->start); if (offset < osc->start) offset = osc->start + fmodf(osc->start + offset, osc->len - osc->start); if (osc->type == SAMPLE) { // this makes A2 be the base ??? // A2 = 220.0 Hz is base ??? // get this from osc* f = f / (16.35160 * pow(2, (2 + 5 / 12.0))); } float step = f * ((osc->len - osc->start) / (float)SAMPLE_RATE); offset += step; if (offset >= osc->len) { offset -= osc->len; } return offset; } /* static inline float wrap_offset(float x, float start, float len) { */ /* float range = len - start; */ /* x -= start; */ /* x -= range * floorf(x / range); // efficient wrap to [0, range) */ /* return start + x; */ /* } */ /* float osc_next_offset(osc_t * osc, float f, float offset) */ /* { */ /* // Wrap once at the start */ /* if (offset < osc->start || offset >= osc->len) { */ /* offset = wrap_offset(offset, osc->start, osc->len); */ /* } */ /* if (osc->type == SAMPLE) { */ /* // Precomputed constant for (16.35160 * 2^(2 + 5/12)) */ /* // = base frequency for A2 mapping */ /* #define BASE_A2_FACTOR 220.00000f */ /* f /= BASE_A2_FACTOR; */ /* } */ /* // Precompute conversion factor */ /* float step = f * ((osc->len - osc->start) / (float)SAMPLE_RATE); */ /* offset += step; */ /* // Single wrap without fmodf (branchless for most cases) */ /* if (offset >= osc->len) { */ /* offset -= osc->len; */ /* } */ /* return offset; */ /* } */ int osc_load_wav(osc_t * osc, const char * path) { SNDFILE* file; SF_INFO fileInfo; int numSamplesRead = 0; // 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 -1; } /* printf("Opened %s: \n", path); */ /* 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 -1; } osc->len = fileInfo.frames; osc->data = (float *) malloc(sizeof(float) * fileInfo.frames); // Read the WAV file into the buffer numSamplesRead = sf_readf_float(file, osc->data, fileInfo.frames); (void)numSamplesRead; /* float max = -1000; */ /* float min = 1000; */ /* for (int i = 0; i < numSamplesRead; i++) { */ /* float s = osc_sound_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); return 0; }