diff --git a/lib/main.c b/lib/main.c index a9a59dc..d875c8c 100644 --- a/lib/main.c +++ b/lib/main.c @@ -1,15 +1,16 @@ #include #include - #include #define M_PI_M2 (M_PI + M_PI) #define DEFAULT_RATE 44100 +#define DEFAULT_PERIOD 1.0 / DEFAULT_RATE + #define DEFAULT_CHANNELS 2 #define DEFAULT_VOLUME 0.7 -#define DEFAULT_FREQ 200 +#define DEFAULT_FREQ 500 #define DEFAULT_ACCUMULATOR -1 @@ -18,17 +19,72 @@ struct data { struct pw_main_loop *loop; struct pw_stream *stream; - double accumulator; - uint32_t cycle; + + /* + */ + double t, tcyc; // global time and cycle time + uint32_t frame, cycle; }; +#define NEW_DATA (struct data) \ + { \ + .t = 0, \ + .tcyc = 0, \ + .frame = 0, \ + .cycle = 0, \ + } + +typedef int16_t (*snd)(struct data*); + +inline void data_progress(struct data *state) { + state->t += DEFAULT_PERIOD / DEFAULT_FREQ; + state->tcyc += DEFAULT_PERIOD / DEFAULT_FREQ; + if (++state->frame == DEFAULT_FREQ) { + state->tcyc -= DEFAULT_PERIOD; + state->frame = 0; + state->cycle++; + } +} + +int16_t snd_sine(struct data *state) { + int16_t val; + + /* sin() gives a value between -1.0 and 1.0, we first apply + * the volume and then scale with 32767.0 to get a 16 bits value + * between [-32767 32767]. + * Another common method to convert a double to + * 16 bits is to multiple by 32768.0 and then clamp to + * [-32768 32767] to get the full 16 bits range. */ + val = sin(state->tcyc * M_PI_M2 * DEFAULT_FREQ) * 32767.0 * DEFAULT_VOLUME; + + return val; +} + +int graph_snd(snd f, struct data *state, double t_max, FILE *fstream) { + int16_t val; + if (fstream == NULL) + return 1; + + fputs("x, sin(x)\n", fstream); + while (state->t < t_max) { + val = f(state); + fprintf(fstream, "%f, %d\n", state->t, val); + data_progress(state); + } + + fclose(fstream); + return 0; +} + + /* [on_process] */ static void on_process(void *userdata) { struct data *data = userdata; struct pw_buffer *b; struct spa_buffer *buf; - int i, c, n_frames, stride; + int n_frames, stride; int16_t *dst, val; + int i, c; if ((b = pw_stream_dequeue_buffer(data->stream)) == NULL) { pw_log_warn("out of buffers: %m"); @@ -45,19 +101,7 @@ static void on_process(void *userdata) { n_frames = SPA_MIN(b->requested, n_frames); for (i = 0; i < n_frames; i++) { - // data->accumulator += M_PI_M2 * DEFAULT_FREQ / DEFAULT_RATE; // * 440 - if (data->accumulator++ == DEFAULT_RATE) { - data->accumulator = DEFAULT_ACCUMULATOR; - data->cycle++; - } - - /* sin() gives a value between -1.0 and 1.0, we first apply - * the volume and then scale with 32767.0 to get a 16 bits value - * between [-32767 32767]. - * Another common method to convert a double to - * 16 bits is to multiple by 32768.0 and then clamp to - * [-32768 32767] to get the full 16 bits range. */ - val = sin(data->accumulator * M_PI_M2 * DEFAULT_FREQ / DEFAULT_RATE) * DEFAULT_VOLUME * 32767.0; + val = snd_sine(data); for (c = 0; c < DEFAULT_CHANNELS; c++) *dst++ = val; } @@ -75,16 +119,20 @@ static const struct pw_stream_events stream_events = { .process = on_process, }; -int main(int argc, char *argv[]) { - struct data data = { - .accumulator = DEFAULT_ACCUMULATOR, - .cycle = 0, - }; +int main(int argc, char **argv) { + struct data data = NEW_DATA; const struct spa_pod *params[1]; uint8_t buffer[1024]; struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); - pw_init(&argc, &argv); + // DEBUG: check sine wave is actually a sine wave + FILE *fstream = fopen("sine.txt", "w"); + graph_snd(&snd_sine, &NEW_DATA, DEFAULT_PERIOD, fstream); + exit(69); + + int pw_argc = 0; + char **pw_argv = NULL; + pw_init(&pw_argc, &pw_argv); // pw_init(&argc, &argv); data.loop = pw_main_loop_new(NULL);