Files
countdown/play_raw_audio.c
bjoernf 671f503a41 play-manual-square-wave-instead-of-file (#2)
Remove dependency on external raw audio file.\
Play manual square wave instead.

Reviewed-on: #2
Co-authored-by: bjoernf <bjoern.foersterling@web.de>
Co-committed-by: bjoernf <bjoern.foersterling@web.de>
2025-11-15 16:48:16 +01:00

118 lines
2.7 KiB
C

#include "play_raw_audio.h"
#include "time_utils.h"
#include <errno.h>
#include <fcntl.h>
#include <pulse/error.h>
#include <pulse/simple.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
// prototypes for static functions
static int play_square_wave(float frequency, float duration);
int play_manual_alarm() {
int err = 0;
for (int i = 0; i < 3; i++) {
for (int i = 0; i < 2; i++) {
err = play_square_wave(1000.0, 0.2);
if (err != 0) {
return err;
}
sleep_ms(200);
}
sleep_ms(500);
}
return 0;
}
// UNUSED
// Playing a raw audio file has the downside of depending on a file.
int play_raw_audio(char file_name[]) {
int pa_error = 0;
char content[1024] = "";
int myfd = open(file_name, O_RDONLY);
if (myfd == -1) {
fprintf(stderr, "Failed to open audio file %s: %s.\n", file_name, strerror(errno));
return 1;
}
pa_simple* simple = NULL;
pa_sample_spec ss;
ss.format = PA_SAMPLE_S16LE;
ss.rate = 48000;
ss.channels = 2;
simple = pa_simple_new(NULL, "Audio Playback", PA_STREAM_PLAYBACK, NULL, "playback", &ss, NULL, NULL, &pa_error);
int i = 0;
while (read(myfd, content, sizeof(content))) {
// skip the first 1024 bytes to not play the file header
if (i != 0) {
pa_simple_write(simple, content, sizeof(content), &pa_error);
}
i++;
}
pa_simple_drain(simple, NULL);
pa_simple_free(simple);
close(myfd);
return 0;
}
// Output a tone with the audio frequency "frequency"
// for "duration" number of seconds.
// The sound signals are not sine waves but square waves.
static int play_square_wave(float frequency, float duration) {
const int sample_rate = 44100;
const int channel_count = 2;
size_t buffer_size = sample_rate * channel_count * duration;
short buffer[buffer_size] = {};
pa_simple *s;
pa_sample_spec ss = {
.format = PA_SAMPLE_S16LE,
.rate = sample_rate,
.channels = channel_count,
};
// number of identical consecutive elements
// 5 would look like this:
// [0,0,0,0,0,32768,32768,32768,32768,32768,0,...]
int array_interval = sample_rate / frequency;
bool square_peak = false;
for (int i = 0; i < buffer_size; i++) {
if (i % array_interval == 0) {
// toggle the value (0 or the max value for a short)
square_peak = !square_peak;
}
if (square_peak) {
buffer[i] = SHRT_MAX;
} else {
buffer[i] = 0;
}
}
if (!(s = pa_simple_new(NULL, NULL, PA_STREAM_PLAYBACK, NULL, "playback", &ss, NULL, NULL, &errno))) {
fprintf(stderr, "pa_simple_new() failed: %s\n", pa_strerror(errno));
return 1;
}
if (pa_simple_write(s, buffer, sizeof(buffer), NULL) < 0) {
fprintf(stderr, "pa_simple_write() failed: %s\n", pa_strerror(errno));
return 1;
}
pa_simple_drain(s, NULL);
pa_simple_free(s);
return 0;
}