| @@ -1,56 +1,284 @@ | | | @@ -1,56 +1,284 @@ |
1 | $NetBSD: patch-src_audio_netbsd_SDL__netbsdaudio.c,v 1.1 2017/09/26 13:10:56 adam Exp $ | | 1 | $NetBSD: patch-src_audio_netbsd_SDL__netbsdaudio.c,v 1.2 2019/05/24 18:13:36 nia Exp $ |
2 | | | 2 | |
3 | Remove delay as there is already an inherent delay in writing audio. | | 3 | Remove delays and use blocking i/o |
4 | https://bugzilla.libsdl.org/show_bug.cgi?id=3177 | | 4 | https://bugzilla.libsdl.org/show_bug.cgi?id=3177 |
5 | | | 5 | |
6 | audio_prinfo needs 'struct' on NetBSD. | | 6 | audio_prinfo needs 'struct' on NetBSD. |
7 | Use correct prinfo. | | 7 | Use correct prinfo type (play/record) |
8 | Inform upper layer of blocksize | | 8 | Rework initialization |
9 | | | 9 | |
10 | --- src/audio/netbsd/SDL_netbsdaudio.c.orig 2017-09-26 12:34:35.000000000 +0000 | | 10 | --- src/audio/netbsd/SDL_netbsdaudio.c.orig 2018-10-31 15:07:22.000000000 +0000 |
11 | +++ src/audio/netbsd/SDL_netbsdaudio.c | | 11 | +++ src/audio/netbsd/SDL_netbsdaudio.c |
12 | @@ -63,14 +63,14 @@ NETBSDAUDIO_Status(_THIS) | | 12 | @@ -43,12 +43,7 @@ |
| | | 13 | #include "../SDL_audiodev_c.h" |
| | | 14 | #include "SDL_netbsdaudio.h" |
| | | 15 | |
| | | 16 | -/* Use timer for synchronization */ |
| | | 17 | -/* #define USE_TIMER_SYNC */ |
| | | 18 | - |
| | | 19 | /* #define DEBUG_AUDIO */ |
| | | 20 | -/* #define DEBUG_AUDIO_STREAM */ |
| | | 21 | - |
| | | 22 | |
| | | 23 | static void |
| | | 24 | NETBSDAUDIO_DetectDevices(void) |
| | | 25 | @@ -63,14 +58,14 @@ NETBSDAUDIO_Status(_THIS) |
13 | #ifdef DEBUG_AUDIO | | 26 | #ifdef DEBUG_AUDIO |
14 | /* *INDENT-OFF* */ | | 27 | /* *INDENT-OFF* */ |
15 | audio_info_t info; | | 28 | audio_info_t info; |
16 | - const audio_prinfo *prinfo; | | 29 | - const audio_prinfo *prinfo; |
17 | + const struct audio_prinfo *prinfo; | | 30 | + const struct audio_prinfo *prinfo; |
18 | | | 31 | |
19 | if (ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info) < 0) { | | 32 | if (ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info) < 0) { |
20 | fprintf(stderr, "AUDIO_GETINFO failed.\n"); | | 33 | fprintf(stderr, "AUDIO_GETINFO failed.\n"); |
21 | return; | | 34 | return; |
22 | } | | 35 | } |
23 | | | 36 | |
24 | - prinfo = this->iscapture ? &info.play : &info.record; | | 37 | - prinfo = this->iscapture ? &info.play : &info.record; |
25 | + prinfo = this->iscapture ? &info.record : &info.play; | | 38 | + prinfo = this->iscapture ? &info.record : &info.play; |
26 | | | 39 | |
27 | fprintf(stderr, "\n" | | 40 | fprintf(stderr, "\n" |
28 | "[%s info]\n" | | 41 | "[%s info]\n" |
29 | @@ -184,10 +184,6 @@ NETBSDAUDIO_PlayDevice(_THIS) | | 42 | @@ -115,90 +110,37 @@ NETBSDAUDIO_Status(_THIS) |
30 | fprintf(stderr, "Wrote %d bytes of audio data\n", written); | | 43 | (info.mode == AUMODE_PLAY) ? "PLAY" |
31 | #endif | | 44 | : (info.mode = AUMODE_RECORD) ? "RECORD" |
| | | 45 | : (info.mode == AUMODE_PLAY_ALL ? "PLAY_ALL" : "?")); |
| | | 46 | + |
| | | 47 | + fprintf(stderr, "\n" |
| | | 48 | + "[audio spec]\n" |
| | | 49 | + "format : 0x%x\n" |
| | | 50 | + "size : %u\n" |
| | | 51 | + "", |
| | | 52 | + this->spec.format, |
| | | 53 | + this->spec.size); |
| | | 54 | /* *INDENT-ON* */ |
| | | 55 | #endif /* DEBUG_AUDIO */ |
| | | 56 | } |
| | | 57 | |
32 | | | 58 | |
| | | 59 | -/* This function waits until it is possible to write a full sound buffer */ |
| | | 60 | -static void |
| | | 61 | -NETBSDAUDIO_WaitDevice(_THIS) |
| | | 62 | -{ |
| | | 63 | -#ifndef USE_BLOCKING_WRITES /* Not necessary when using blocking writes */ |
| | | 64 | - /* See if we need to use timed audio synchronization */ |
| | | 65 | - if (this->hidden->frame_ticks) { |
| | | 66 | - /* Use timer for general audio synchronization */ |
| | | 67 | - Sint32 ticks; |
| | | 68 | - |
| | | 69 | - ticks = ((Sint32) (this->hidden->next_frame - SDL_GetTicks())) - FUDGE_TICKS; |
| | | 70 | - if (ticks > 0) { |
| | | 71 | - SDL_Delay(ticks); |
| | | 72 | - } |
| | | 73 | - } else { |
| | | 74 | - /* Use SDL_IOReady() for audio synchronization */ |
| | | 75 | -#ifdef DEBUG_AUDIO |
| | | 76 | - fprintf(stderr, "Waiting for audio to get ready\n"); |
| | | 77 | -#endif |
| | | 78 | - if (SDL_IOReady(this->hidden->audio_fd, SDL_TRUE, 10 * 1000) |
| | | 79 | - <= 0) { |
| | | 80 | - const char *message = |
| | | 81 | - "Audio timeout - buggy audio driver? (disabled)"; |
| | | 82 | - /* In general we should never print to the screen, |
| | | 83 | - but in this case we have no other way of letting |
| | | 84 | - the user know what happened. |
| | | 85 | - */ |
| | | 86 | - fprintf(stderr, "SDL: %s\n", message); |
| | | 87 | - SDL_OpenedAudioDeviceDisconnected(this); |
| | | 88 | - /* Don't try to close - may hang */ |
| | | 89 | - this->hidden->audio_fd = -1; |
| | | 90 | -#ifdef DEBUG_AUDIO |
| | | 91 | - fprintf(stderr, "Done disabling audio\n"); |
| | | 92 | -#endif |
| | | 93 | - } |
| | | 94 | -#ifdef DEBUG_AUDIO |
| | | 95 | - fprintf(stderr, "Ready!\n"); |
| | | 96 | -#endif |
| | | 97 | - } |
| | | 98 | -#endif /* !USE_BLOCKING_WRITES */ |
| | | 99 | -} |
| | | 100 | - |
| | | 101 | static void |
| | | 102 | NETBSDAUDIO_PlayDevice(_THIS) |
| | | 103 | { |
| | | 104 | - int written, p = 0; |
| | | 105 | + struct SDL_PrivateAudioData *h = this->hidden; |
| | | 106 | + int written; |
| | | 107 | |
| | | 108 | - /* Write the audio data, checking for EAGAIN on broken audio drivers */ |
| | | 109 | - do { |
| | | 110 | - written = write(this->hidden->audio_fd, |
| | | 111 | - &this->hidden->mixbuf[p], this->hidden->mixlen - p); |
| | | 112 | - |
| | | 113 | - if (written > 0) |
| | | 114 | - p += written; |
| | | 115 | - if (written == -1 && errno != 0 && errno != EAGAIN && errno != EINTR) { |
| | | 116 | - /* Non recoverable error has occurred. It should be reported!!! */ |
| | | 117 | - perror("audio"); |
| | | 118 | - break; |
| | | 119 | - } |
| | | 120 | + /* Write the audio data */ |
| | | 121 | + written = write(h->audio_fd, h->mixbuf, h->mixlen); |
| | | 122 | + if (written == -1) { |
| | | 123 | + /* Non recoverable error has occurred. It should be reported!!! */ |
| | | 124 | + SDL_OpenedAudioDeviceDisconnected(this); |
| | | 125 | + perror("audio"); |
| | | 126 | + return; |
| | | 127 | + } |
| | | 128 | |
| | | 129 | #ifdef DEBUG_AUDIO |
| | | 130 | - fprintf(stderr, "Wrote %d bytes of audio data\n", written); |
| | | 131 | + fprintf(stderr, "Wrote %d bytes of audio data\n", written); |
| | | 132 | #endif |
| | | 133 | - |
33 | - if (p < this->hidden->mixlen | | 134 | - if (p < this->hidden->mixlen |
34 | - || ((written < 0) && ((errno == 0) || (errno == EAGAIN)))) { | | 135 | - || ((written < 0) && ((errno == 0) || (errno == EAGAIN)))) { |
35 | - SDL_Delay(1); /* Let a little CPU time go by */ | | 136 | - SDL_Delay(1); /* Let a little CPU time go by */ |
36 | - } | | 137 | - } |
37 | } while (p < this->hidden->mixlen); | | 138 | - } while (p < this->hidden->mixlen); |
| | | 139 | - |
| | | 140 | - /* If timer synchronization is enabled, set the next write frame */ |
| | | 141 | - if (this->hidden->frame_ticks) { |
| | | 142 | - this->hidden->next_frame += this->hidden->frame_ticks; |
| | | 143 | - } |
| | | 144 | - |
| | | 145 | - /* If we couldn't write, assume fatal error for now */ |
| | | 146 | - if (written < 0) { |
| | | 147 | - SDL_OpenedAudioDeviceDisconnected(this); |
| | | 148 | - } |
| | | 149 | } |
| | | 150 | |
| | | 151 | static Uint8 * |
| | | 152 | @@ -212,28 +154,19 @@ static int |
| | | 153 | NETBSDAUDIO_CaptureFromDevice(_THIS, void *_buffer, int buflen) |
| | | 154 | { |
| | | 155 | Uint8 *buffer = (Uint8 *) _buffer; |
| | | 156 | - int br, p = 0; |
| | | 157 | + int br; |
38 | | | 158 | |
39 | /* If timer synchronization is enabled, set the next write frame */ | | 159 | - /* Capture the audio data, checking for EAGAIN on broken audio drivers */ |
40 | @@ -274,7 +270,7 @@ NETBSDAUDIO_OpenDevice(_THIS, void *hand | | 160 | - do { |
41 | const int flags = iscapture ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT; | | 161 | - br = read(this->hidden->audio_fd, buffer + p, buflen - p); |
| | | 162 | - if (br > 0) |
| | | 163 | - p += br; |
| | | 164 | - if (br == -1 && errno != 0 && errno != EAGAIN && errno != EINTR) { |
| | | 165 | - /* Non recoverable error has occurred. It should be reported!!! */ |
| | | 166 | - perror("audio"); |
| | | 167 | - return p ? p : -1; |
| | | 168 | - } |
| | | 169 | + br = read(this->hidden->audio_fd, buffer, buflen); |
| | | 170 | + if (br == -1) { |
| | | 171 | + /* Non recoverable error has occurred. It should be reported!!! */ |
| | | 172 | + perror("audio"); |
| | | 173 | + return -1; |
| | | 174 | + } |
| | | 175 | |
| | | 176 | #ifdef DEBUG_AUDIO |
| | | 177 | - fprintf(stderr, "Captured %d bytes of audio data\n", br); |
| | | 178 | + fprintf(stderr, "Captured %d bytes of audio data\n", br); |
| | | 179 | #endif |
| | | 180 | - |
| | | 181 | - if (p < buflen |
| | | 182 | - || ((br < 0) && ((errno == 0) || (errno == EAGAIN)))) { |
| | | 183 | - SDL_Delay(1); /* Let a little CPU time go by */ |
| | | 184 | - } |
| | | 185 | - } while (p < buflen); |
| | | 186 | + return 0; |
| | | 187 | } |
| | | 188 | |
| | | 189 | static void |
| | | 190 | @@ -271,10 +204,9 @@ NETBSDAUDIO_CloseDevice(_THIS) |
| | | 191 | static int |
| | | 192 | NETBSDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) |
| | | 193 | { |
| | | 194 | - const int flags = iscapture ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT; |
42 | SDL_AudioFormat format = 0; | | 195 | SDL_AudioFormat format = 0; |
43 | audio_info_t info; | | 196 | audio_info_t info; |
44 | - audio_prinfo *prinfo = iscapture ? &info.play : &info.record; | | 197 | - audio_prinfo *prinfo = iscapture ? &info.play : &info.record; |
45 | + struct audio_prinfo *prinfo = iscapture ? &info.record : &info.play; | | 198 | + struct audio_prinfo *prinfo = iscapture ? &info.record : &info.play; |
46 | | | 199 | |
47 | /* We don't care what the devname is...we'll try to open anything. */ | | 200 | /* We don't care what the devname is...we'll try to open anything. */ |
48 | /* ...but default to first name in the list... */ | | 201 | /* ...but default to first name in the list... */ |
49 | @@ -366,6 +362,7 @@ NETBSDAUDIO_OpenDevice(_THIS, void *hand | | 202 | @@ -294,25 +226,16 @@ NETBSDAUDIO_OpenDevice(_THIS, void *hand |
| | | 203 | SDL_zerop(this->hidden); |
| | | 204 | |
| | | 205 | /* Open the audio device */ |
| | | 206 | - this->hidden->audio_fd = open(devname, flags, 0); |
| | | 207 | + this->hidden->audio_fd = open(devname, iscapture ? O_RDONLY : O_WRONLY); |
| | | 208 | if (this->hidden->audio_fd < 0) { |
| | | 209 | return SDL_SetError("Couldn't open %s: %s", devname, strerror(errno)); |
| | | 210 | } |
| | | 211 | |
| | | 212 | AUDIO_INITINFO(&info); |
| | | 213 | |
| | | 214 | - /* Calculate the final parameters for this audio specification */ |
| | | 215 | - SDL_CalculateAudioSpec(&this->spec); |
| | | 216 | - |
| | | 217 | - /* Set to play mode */ |
| | | 218 | - info.mode = iscapture ? AUMODE_RECORD : AUMODE_PLAY; |
| | | 219 | - if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) < 0) { |
| | | 220 | - return SDL_SetError("Couldn't put device into play mode"); |
| | | 221 | - } |
| | | 222 | + prinfo->encoding = AUDIO_ENCODING_NONE; |
| | | 223 | |
| | | 224 | - AUDIO_INITINFO(&info); |
| | | 225 | - for (format = SDL_FirstAudioFormat(this->spec.format); |
| | | 226 | - format; format = SDL_NextAudioFormat()) { |
| | | 227 | + for (format = SDL_FirstAudioFormat(this->spec.format); format;) { |
| | | 228 | switch (format) { |
| | | 229 | case AUDIO_U8: |
| | | 230 | prinfo->encoding = AUDIO_ENCODING_ULINEAR; |
| | | 231 | @@ -338,34 +261,33 @@ NETBSDAUDIO_OpenDevice(_THIS, void *hand |
| | | 232 | prinfo->encoding = AUDIO_ENCODING_ULINEAR_BE; |
| | | 233 | prinfo->precision = 16; |
| | | 234 | break; |
| | | 235 | - default: |
| | | 236 | - continue; |
| | | 237 | } |
| | | 238 | - |
| | | 239 | - if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) == 0) { |
| | | 240 | + if (prinfo->encoding != AUDIO_ENCODING_NONE) { |
| | | 241 | break; |
| | | 242 | } |
| | | 243 | + format = SDL_NextAudioFormat(); |
| | | 244 | } |
| | | 245 | |
| | | 246 | - if (!format) { |
| | | 247 | + if (prinfo->encoding == AUDIO_ENCODING_NONE) { |
| | | 248 | return SDL_SetError("No supported encoding for 0x%x", this->spec.format); |
| | | 249 | } |
| | | 250 | |
| | | 251 | this->spec.format = format; |
| | | 252 | |
| | | 253 | - AUDIO_INITINFO(&info); |
| | | 254 | - prinfo->channels = this->spec.channels; |
| | | 255 | - if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) == -1) { |
| | | 256 | - this->spec.channels = 1; |
| | | 257 | - } |
| | | 258 | - AUDIO_INITINFO(&info); |
| | | 259 | - prinfo->sample_rate = this->spec.freq; |
| | | 260 | + /* Calculate spec parameters based on our chosen format */ |
| | | 261 | + SDL_CalculateAudioSpec(&this->spec); |
| | | 262 | + |
| | | 263 | + info.mode = iscapture ? AUMODE_RECORD : AUMODE_PLAY; |
| | | 264 | info.blocksize = this->spec.size; |
| | | 265 | info.hiwat = 5; |
| | | 266 | info.lowat = 3; |
| | | 267 | + prinfo->sample_rate = this->spec.freq; |
| | | 268 | + prinfo->channels = this->spec.channels; |
50 | (void) ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info); | | 269 | (void) ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info); |
| | | 270 | + |
51 | (void) ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info); | | 271 | (void) ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info); |
52 | this->spec.freq = prinfo->sample_rate; | | 272 | this->spec.freq = prinfo->sample_rate; |
53 | + this->spec.size = info.blocksize; | | 273 | + this->spec.channels = prinfo->channels; |
54 | | | 274 | |
55 | if (!iscapture) { | | 275 | if (!iscapture) { |
56 | /* Allocate mixing buffer */ | | 276 | /* Allocate mixing buffer */ |
| | | 277 | @@ -390,7 +312,6 @@ NETBSDAUDIO_Init(SDL_AudioDriverImpl * i |
| | | 278 | impl->DetectDevices = NETBSDAUDIO_DetectDevices; |
| | | 279 | impl->OpenDevice = NETBSDAUDIO_OpenDevice; |
| | | 280 | impl->PlayDevice = NETBSDAUDIO_PlayDevice; |
| | | 281 | - impl->WaitDevice = NETBSDAUDIO_WaitDevice; |
| | | 282 | impl->GetDeviceBuf = NETBSDAUDIO_GetDeviceBuf; |
| | | 283 | impl->CloseDevice = NETBSDAUDIO_CloseDevice; |
| | | 284 | impl->CaptureFromDevice = NETBSDAUDIO_CaptureFromDevice; |