-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsndout_sdl.c
151 lines (124 loc) · 2.56 KB
/
sndout_sdl.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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/*
* (C) notaz, 2013
*
* This work is licensed under the terms of any of these licenses
* (at your option):
* - GNU GPL, version 2 or later.
* - GNU LGPL, version 2.1 or later.
* - MAME license.
* See the COPYING file in the top-level directory.
*/
#include <SDL.h>
#include "sndout_sdl.h"
// ~1/3s at 44kHz
// set this to power of 2
#define BUF_LEN 32768
#define BUF_MASK (BUF_LEN - 1)
static short buf[BUF_LEN];
static int buf_w, buf_r;
static int started;
static void callback(void *userdata, Uint8 *stream, int len)
{
int have = (buf_w - buf_r) & BUF_MASK;
int buf_left = BUF_LEN - buf_r;
len /= 2;
if (have > len)
have = len;
if (have > 0) {
if (have > buf_left) {
memcpy(stream, buf + buf_r, buf_left * 2);
stream += buf_left * 2;
buf_r = 0;
have -= buf_left;
len -= buf_left;
}
memcpy(stream, buf + buf_r, have * 2);
stream += have * 2;
buf_r = (buf_r + have) & BUF_MASK;
len -= have;
}
if (len > 0) {
// put in some silence..
memset(stream, 0, len * 2);
}
}
int sndout_sdl_init(void)
{
int ret;
ret = SDL_InitSubSystem(SDL_INIT_AUDIO);
if (ret != 0)
return -1;
return 0;
}
int sndout_sdl_start(int rate, int stereo)
{
SDL_AudioSpec desired = { 0 };
int samples, shift;
int ret;
if (started)
sndout_sdl_stop();
desired.freq = rate;
desired.format = AUDIO_S16SYS;
desired.channels = stereo ? 2 : 1;
desired.callback = callback;
desired.userdata = NULL;
samples = rate >> 6;
for (shift = 8; (1 << shift) < samples; shift++)
;
desired.samples = 1 << shift;
ret = SDL_OpenAudio(&desired, NULL);
if (ret != 0) {
fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());
return -1;
}
buf_w = buf_r = 0;
SDL_PauseAudio(0);
started = 1;
return 0;
}
void sndout_sdl_stop(void)
{
SDL_PauseAudio(1);
SDL_CloseAudio();
started = 0;
}
void sndout_sdl_wait(void)
{
int left;
while (1)
{
left = (buf_r - buf_w - 2) & BUF_MASK;
if (left >= BUF_LEN / 2)
break;
SDL_Delay(4);
}
}
int sndout_sdl_write_nb(const void *samples, int len)
{
int maxlen = (buf_r - buf_w - 2) & BUF_MASK;
int buf_left = BUF_LEN - buf_w;
int retval;
len /= 2;
if (len > maxlen)
// not enough space
len = maxlen;
if (len == 0)
// totally full
return 0;
retval = len;
if (len > buf_left) {
memcpy(buf + buf_w, samples, buf_left * 2);
samples = (const short *)samples + buf_left;
len -= buf_left;
buf_w = 0;
}
memcpy(buf + buf_w, samples, len * 2);
buf_w = (buf_w + len) & BUF_MASK;
return retval;
}
void sndout_sdl_exit(void)
{
if (started)
sndout_sdl_stop();
SDL_QuitSubSystem(SDL_INIT_AUDIO);
}