-
Notifications
You must be signed in to change notification settings - Fork 0
/
bridge.c
131 lines (105 loc) · 3.44 KB
/
bridge.c
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
#ifdef WIN32
#define EXPORT extern __declspec (dllexport)
#else
#define EXPORT extern
#endif
#include <sys/select.h>
#include <soundio/soundio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "scheme.h"
// <write_callback>
static void write_callback(struct SoundIoOutStream *outstream, int frame_count_min, int frame_count_max) {
struct SoundIoRingBuffer *ring_buffer = outstream->userdata;
struct SoundIoChannelArea *areas;
int frame_count;
int frames_left;
int err;
char *read_ptr = soundio_ring_buffer_read_ptr(ring_buffer);
int fill_bytes = soundio_ring_buffer_fill_count(ring_buffer);
int fill_count = fill_bytes / outstream->bytes_per_frame;
if (frame_count_min > fill_count) {
// <fill-stream-with-zeros>
frames_left = frame_count_min;
for (;;) {
frame_count = frames_left;
if (!frame_count)
return;
// <begin-write>
if ((err = soundio_outstream_begin_write(outstream, &areas, &frame_count))) {
fprintf(stderr, "begin_write: %s\n", soundio_strerror(err));
exit(1);
}
// </begin-write>
if (!frame_count)
return;
for (int frame = 0; frame < frame_count; frame += 1) {
for (int ch = 0; ch < outstream->layout.channel_count; ch += 1) {
memset(areas[ch].ptr, 0, outstream->bytes_per_sample);
areas[ch].ptr += areas[ch].step;
}
}
// <end-write>
if ((err = soundio_outstream_end_write(outstream))) {
fprintf(stderr, "end_write: %s\n", soundio_strerror(err));
// REVIEW pthread_exit?
exit(1);
}
// </end-write>
frames_left -= frame_count;
}
// </fill-stream-with-zeros>
}
// <copy-samples-from-buffer>
int read_count = frame_count_max < fill_count ? frame_count_max : fill_count;
frames_left = read_count;
while (frames_left > 0) {
int frame_count = frames_left;
// <begin-write>
if ((err = soundio_outstream_begin_write(outstream, &areas, &frame_count))) {
fprintf(stderr, "begin_write: %s\n", soundio_strerror(err));
exit(1);
}
// </begin-write>
if (frame_count <= 0)
break;
for (int frame = 0; frame < frame_count; frame += 1) {
for (int ch = 0; ch < outstream->layout.channel_count; ch += 1) {
memcpy(areas[ch].ptr, read_ptr, outstream->bytes_per_sample);
areas[ch].ptr += areas[ch].step;
read_ptr += outstream->bytes_per_sample;
}
}
// <end-write>
if ((err = soundio_outstream_end_write(outstream))) {
fprintf(stderr, "end_write: %s\n", soundio_strerror(err));
// REVIEW pthread_exit?
exit(1);
}
// </end-write>
frames_left -= frame_count;
}
// </copy-samples-from-buffer>
soundio_ring_buffer_advance_read_ptr(ring_buffer, read_count * outstream->bytes_per_frame);
}
// </write_callback>
// <bridge_outstream_attach_ring_buffer>
EXPORT void bridge_outstream_attach_ring_buffer
(struct SoundIoOutStream *outstream, struct SoundIoRingBuffer *buffer) {
outstream->format = SoundIoFormatFloat32NE;
outstream->userdata = buffer;
outstream->write_callback = write_callback;
}
// </bridge_outstream_attach_ring_buffer>
// <usleep>
EXPORT void usleep (long seconds, long microseconds) {
struct timeval timeout;
timeout.tv_sec = seconds;
timeout.tv_usec = microseconds;
Sdeactivate_thread();
select(0, NULL, NULL, NULL, &timeout);
Sactivate_thread();
}
// </usleep>