summaryrefslogtreecommitdiffstats
path: root/src/osc.c
blob: 70e7c32cb2779d4524be10ae6f2dbb69f22efedb (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include "synth_common.h"
#include "osc.h"

#include <sndfile.h>
#include <stdlib.h>
#include <stddef.h>


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;
}