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>
This commit was merged in pull request #2.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
a.out
|
a.out
|
||||||
|
tags
|
||||||
|
|||||||
17
README.md
17
README.md
@@ -1,17 +1,16 @@
|
|||||||
|
## countdown
|
||||||
|
|
||||||
Simple command line countdown timer that plays a sound when the time is up.
|
Simple command line countdown timer that plays a sound when the time is up.
|
||||||
|
|
||||||
It is using `pulseaudio`s simple API.
|
When the time has expired a square wave is sent to `pulseaudio`s simple API \
|
||||||
|
to notify the user.
|
||||||
|
|
||||||
#### installation
|
#### installation
|
||||||
|
|
||||||
install `libpulse-dev` (debian based) or `libpulse` package depending on your distro
|
Install `libpulse-dev` (debian based) or `libpulse` package depending on your distribution.
|
||||||
|
|
||||||
```
|
```
|
||||||
sudo pacman -S libpulse pulseaudio sound-theme-freedesktop
|
sudo pacman -S libpulse pulseaudio
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
ffmpeg -i /usr/share/sounds/freedesktop/stereo/alarm-clock-elapsed.oga ${HOME}/music/alarm-clock-elapsed.wav
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -23,6 +22,7 @@ sudo make install
|
|||||||
|
|
||||||
#### usage
|
#### usage
|
||||||
|
|
||||||
|
Start a 20 minute countdown:
|
||||||
```
|
```
|
||||||
countdown 20
|
countdown 20
|
||||||
```
|
```
|
||||||
@@ -35,5 +35,4 @@ sudo make uninstall
|
|||||||
|
|
||||||
#### TODO
|
#### TODO
|
||||||
|
|
||||||
- make alarm clock file wave file configurable
|
- Arch Linux package
|
||||||
- fix still reachable bytes (still reachable: 42,485 bytes in 97 blocks)?
|
|
||||||
|
|||||||
7
main.c
7
main.c
@@ -1,9 +1,9 @@
|
|||||||
#include "play_raw_audio.h"
|
#include "play_raw_audio.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
// debug pulse audio problems
|
// debug pulse audio problems
|
||||||
#define PA_DEBUG 0
|
#define PA_DEBUG 0
|
||||||
@@ -59,7 +59,8 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
printf ("THE TIME IS UP!\n");
|
printf ("THE TIME IS UP!\n");
|
||||||
play_raw_audio(audio_file_path);
|
|
||||||
|
play_manual_alarm();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
2
makefile
2
makefile
@@ -1,6 +1,6 @@
|
|||||||
.PHONY:all
|
.PHONY:all
|
||||||
all:
|
all:
|
||||||
gcc -Wall *.c -lpulse-simple
|
gcc -Wall *.c -lpulse-simple -lpulse
|
||||||
|
|
||||||
.PHONY:run
|
.PHONY:run
|
||||||
run:
|
run:
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "play_raw_audio.h"
|
#include "play_raw_audio.h"
|
||||||
|
#include "time_utils.h"
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <pulse/error.h>
|
#include <pulse/error.h>
|
||||||
@@ -7,6 +8,27 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.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 play_raw_audio(char file_name[]) {
|
||||||
int pa_error = 0;
|
int pa_error = 0;
|
||||||
char content[1024] = "";
|
char content[1024] = "";
|
||||||
@@ -42,3 +64,54 @@ int play_raw_audio(char file_name[]) {
|
|||||||
|
|
||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
int play_manual_alarm();
|
||||||
int play_raw_audio(char file_name[]);
|
int play_raw_audio(char file_name[]);
|
||||||
|
|||||||
10
time_utils.c
Normal file
10
time_utils.c
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
void sleep_ms(int milliseconds) {
|
||||||
|
struct timespec ts = {
|
||||||
|
.tv_sec = 0,
|
||||||
|
.tv_nsec = milliseconds * 1e6,
|
||||||
|
};
|
||||||
|
|
||||||
|
nanosleep(&ts, NULL);
|
||||||
|
}
|
||||||
3
time_utils.h
Normal file
3
time_utils.h
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
void sleep_ms(int milliseconds);
|
||||||
Reference in New Issue
Block a user