#include <stdio.h>
#include <math.h>
#include "allegro5/allegro.h"
#include "allegro5/allegro_audio.h"
#include "common.c"
#define SAMPLES_PER_BUFFER 1024
#define N 2
int frequency[N];
double samplepos[N];
ALLEGRO_AUDIO_STREAM *stream[N];
ALLEGRO_DISPLAY *display;
float waveform[640], waveform_buffer[640];
static void mainloop(void)
{
ALLEGRO_EVENT_QUEUE *queue;
ALLEGRO_TIMER *timer;
float *buf;
double pitch = 440;
int i, si;
int n = 0;
bool redraw = false;
for (i = 0; i < N; i++) {
frequency[i] = 22050 * pow(2, i / (double)N);
stream[i] = al_create_audio_stream(4, SAMPLES_PER_BUFFER, frequency[i],
ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_1);
if (!stream[i]) {
abort_example("Could not create stream.\n");
}
if (!al_attach_audio_stream_to_mixer(stream[i], al_get_default_mixer())) {
abort_example("Could not attach stream to mixer.\n");
}
}
queue = al_create_event_queue();
al_register_event_source(queue, al_get_keyboard_event_source());
for (i = 0; i < N; i++) {
al_register_event_source(queue,
al_get_audio_stream_event_source(stream[i]));
}
#ifdef ALLEGRO_POPUP_EXAMPLES
if (textlog) {
al_register_event_source(queue, al_get_native_text_log_event_source(textlog));
}
#endif
log_printf("Generating %d sine waves of different sampling quality\n", N);
log_printf("If Allegro's resampling is correct there should be little variation\n", N);
timer = al_create_timer(1.0 / 60);
al_register_event_source(queue, al_get_timer_event_source(timer));
al_register_event_source(queue, al_get_display_event_source(display));
al_start_timer(timer);
while (n < 60 * frequency[0] / SAMPLES_PER_BUFFER * N) {
ALLEGRO_EVENT event;
al_wait_for_event(queue, &event);
if (event.type == ALLEGRO_EVENT_AUDIO_STREAM_FRAGMENT) {
for (si = 0; si < N; si++) {
buf = al_get_audio_stream_fragment(stream[si]);
if (!buf) {
continue;
}
for (i = 0; i < SAMPLES_PER_BUFFER; i++) {
double t = samplepos[si]++ / (double)frequency[si];
buf[i] = sin(t * pitch * ALLEGRO_PI * 2) / N;
}
if (!al_set_audio_stream_fragment(stream[si], buf)) {
log_printf("Error setting stream fragment.\n");
}
n++;
log_printf("%d", si);
if ((n % 60) == 0)
log_printf("\n");
}
}
if (event.type == ALLEGRO_EVENT_TIMER) {
redraw = true;
}
if (event.type == ALLEGRO_EVENT_KEY_DOWN &&
event.keyboard.keycode == ALLEGRO_KEY_ESCAPE) {
break;
}
if (event.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
break;
}
#ifdef ALLEGRO_POPUP_EXAMPLES
if (event.type == ALLEGRO_EVENT_NATIVE_DIALOG_CLOSE) {
break;
}
#endif
if (redraw &&al_is_event_queue_empty(queue)) {
ALLEGRO_COLOR c = al_map_rgb(0, 0, 0);
int i;
al_clear_to_color(al_map_rgb_f(1, 1, 1));
for (i = 0; i < 640; i++) {
al_draw_pixel(i, 50 + waveform[i] * 50, c);
}
al_flip_display();
redraw = false;
}
}
for (si = 0; si < N; si++) {
al_drain_audio_stream(stream[si]);
}
log_printf("\n");
al_destroy_event_queue(queue);
}
static void update_waveform(void *buf, unsigned int samples, void *data)
{
static int pos;
float *fbuf = (float *)buf;
int i;
int n = samples;
(void)data;
* first 640 samples of each buffer is enough for our purpose here.
*/
if (n > 640) n = 640;
for (i = 0; i < n; i++) {
waveform_buffer[pos++] = fbuf[i * 2];
if (pos == 640) {
memcpy(waveform, waveform_buffer, 640 * sizeof(float));
pos = 0;
break;
}
}
}
int main(int argc, char **argv)
{
int i;
(void)argc;
(void)argv;
if (!al_init()) {
abort_example("Could not init Allegro.\n");
}
al_install_keyboard();
open_log();
display = al_create_display(640, 100);
if (!display) {
abort_example("Could not create display.\n");
}
if (!al_install_audio()) {
abort_example("Could not init sound.\n");
}
al_reserve_samples(N);
al_set_mixer_postprocess_callback(al_get_default_mixer(), update_waveform, NULL);
mainloop();
close_log(false);
for (i = 0; i < N; i++) {
al_destroy_audio_stream(stream[i]);
}
al_uninstall_audio();
return 0;
}