-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcltick.cpp
More file actions
146 lines (126 loc) · 4.04 KB
/
Copy pathcltick.cpp
File metadata and controls
146 lines (126 loc) · 4.04 KB
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
//cltick.cpp
#include <stdlib.h>
#include <cstdio>
#include <alsa/asoundlib.h>
snd_pcm_t *handle;
const short MAX=32767;
const int sampleRate = 8000;
const int freq=200;
const int bufferSize=sampleRate/freq;
short bufferTick[bufferSize]; //space for a period
short bufferSilent[bufferSize]; //space for a period
int period; //number of samples of tick + silence
int bufferIndex;
const char *deviceName="default";
void printWriteError(int err, int size) {
if (err < 0) {
printf("Write error: %s\n", snd_strerror(err));
exit(EXIT_FAILURE);
}
if (err != size) {
printf("Write error: written %i expected %d\n", err, size);
exit(EXIT_FAILURE);
}
}
void printAvailError(snd_pcm_sframes_t avail){
if(avail<0) {
printf("Write error: %s\n", snd_strerror(avail));
}
}
void async_callback(snd_async_handler_t *ahandler) {
snd_pcm_sframes_t avail;
int err;
avail = snd_pcm_avail_update(handle);
printAvailError(avail);
while (avail >= bufferSize) {
int size;
if(bufferIndex<bufferSize * 4) { //four periods
size=bufferSize;
err = snd_pcm_writei(handle, bufferTick, size);
bufferIndex +=bufferSize;
} else if(bufferIndex<period-bufferSize) {
size=bufferSize;
err = snd_pcm_writei(handle, bufferSilent, size);
bufferIndex +=bufferSize;
} else {
size=period-bufferIndex;
err = snd_pcm_writei(handle, bufferSilent, size);
bufferIndex=0;
}
printWriteError(err,size);
avail = snd_pcm_avail_update(handle);
printAvailError(avail);
}
}
int async_loop(snd_pcm_t *handle) {
snd_pcm_sframes_t avail;
snd_async_handler_t *ahandler;
int err;
err = snd_async_add_pcm_handler(&ahandler, handle, async_callback, 0);
if (err < 0) {
printf("Unable to register async handler\n");
exit(EXIT_FAILURE);
}
avail = snd_pcm_avail_update(handle);
printAvailError(avail);
for(int i=0; i< avail/bufferSize; i++) {
err = snd_pcm_writei(handle, bufferSilent, bufferSize);
printWriteError(err,bufferSize);
}
bufferIndex=0;
while (1) {
sleep(10);
}
}
snd_pcm_t *alsaOpen(const char *deviceName, snd_pcm_stream_t mode, unsigned int rate, snd_pcm_uframes_t periodSize, uint32_t periods, int channels) {
snd_pcm_t *handle;
snd_pcm_hw_params_t *hw_params;
snd_pcm_sw_params_t *sw_params;
if (snd_pcm_open (&handle, deviceName, mode, 0) < 0) {
fprintf (stderr, "cannot open audio device %s\n", deviceName);
exit (1);
}
snd_pcm_hw_params_alloca(&hw_params);
snd_pcm_hw_params_any(handle, hw_params);
snd_pcm_hw_params_set_access(handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
snd_pcm_hw_params_set_format(handle, hw_params, SND_PCM_FORMAT_S16_LE);
snd_pcm_hw_params_set_rate_near(handle, hw_params, &rate, 0);
snd_pcm_hw_params_set_channels(handle, hw_params, channels);
snd_pcm_hw_params_set_periods(handle, hw_params, periods, 0);
snd_pcm_hw_params_set_period_size(handle, hw_params, periodSize, 0);
snd_pcm_hw_params(handle, hw_params);
snd_pcm_sw_params_alloca(&sw_params);
snd_pcm_sw_params_current(handle, sw_params);
snd_pcm_sw_params_set_avail_min(handle, sw_params, periodSize);
snd_pcm_sw_params(handle, sw_params);
snd_pcm_prepare(handle);
snd_pcm_start(handle);
return handle;
}
int main(int argc, char *argv[]) {
int bpm;
if(argc!=2) {
printf("Usage: cltick bpm\n");
exit(0);
}
bpm=atoi(argv[1]);
if(bpm<=0) {
printf("Error in bpm\n");
exit(0);
}
period = sampleRate*60/bpm;
handle=alsaOpen(deviceName,SND_PCM_STREAM_PLAYBACK,sampleRate,256,16,1);
for(int i=0;i<bufferSize/2; i++){
bufferTick[i]=abs(random())%MAX;
bufferSilent[i]=0;
}
for(int i=bufferSize/2;i<bufferSize; i++){
bufferTick[i]=-1 * (abs(random())%MAX);
bufferSilent[i]=0;
}
bufferIndex=0;
int err = async_loop(handle);
if (err < 0) printf("Transfer failed: %s\n", snd_strerror(err));
snd_pcm_drain(handle);
snd_pcm_close(handle);
}