Mercurial > mplayer.hg
annotate libao2/ao_sdl.c @ 28465:26c1df953188
Add config.h #include for ARCH_X86 definition.
author | diego |
---|---|
date | Mon, 09 Feb 2009 18:04:19 +0000 |
parents | 48c1ae64255b |
children | 9a5b8c2ed6de |
rev | line source |
---|---|
27509
d97a607821f1
Replace casual GPL notices by proper license headers.
diego
parents:
26757
diff
changeset
|
1 /* |
d97a607821f1
Replace casual GPL notices by proper license headers.
diego
parents:
26757
diff
changeset
|
2 * SDLlib audio output driver for MPlayer |
972 | 3 * |
23734 | 4 * Copyleft 2001 by Felix BĆ¼nemann (atmosfear@users.sf.net) |
972 | 5 * |
6 * Thanks to Arpi for nice ringbuffer-code! | |
7 * | |
27509
d97a607821f1
Replace casual GPL notices by proper license headers.
diego
parents:
26757
diff
changeset
|
8 * This file is part of MPlayer. |
d97a607821f1
Replace casual GPL notices by proper license headers.
diego
parents:
26757
diff
changeset
|
9 * |
d97a607821f1
Replace casual GPL notices by proper license headers.
diego
parents:
26757
diff
changeset
|
10 * MPlayer is free software; you can redistribute it and/or modify |
d97a607821f1
Replace casual GPL notices by proper license headers.
diego
parents:
26757
diff
changeset
|
11 * it under the terms of the GNU General Public License as published by |
d97a607821f1
Replace casual GPL notices by proper license headers.
diego
parents:
26757
diff
changeset
|
12 * the Free Software Foundation; either version 2 of the License, or |
d97a607821f1
Replace casual GPL notices by proper license headers.
diego
parents:
26757
diff
changeset
|
13 * (at your option) any later version. |
d97a607821f1
Replace casual GPL notices by proper license headers.
diego
parents:
26757
diff
changeset
|
14 * |
d97a607821f1
Replace casual GPL notices by proper license headers.
diego
parents:
26757
diff
changeset
|
15 * MPlayer is distributed in the hope that it will be useful, |
d97a607821f1
Replace casual GPL notices by proper license headers.
diego
parents:
26757
diff
changeset
|
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
d97a607821f1
Replace casual GPL notices by proper license headers.
diego
parents:
26757
diff
changeset
|
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
d97a607821f1
Replace casual GPL notices by proper license headers.
diego
parents:
26757
diff
changeset
|
18 * GNU General Public License for more details. |
d97a607821f1
Replace casual GPL notices by proper license headers.
diego
parents:
26757
diff
changeset
|
19 * |
d97a607821f1
Replace casual GPL notices by proper license headers.
diego
parents:
26757
diff
changeset
|
20 * You should have received a copy of the GNU General Public License along |
d97a607821f1
Replace casual GPL notices by proper license headers.
diego
parents:
26757
diff
changeset
|
21 * along with MPlayer; if not, write to the Free Software |
d97a607821f1
Replace casual GPL notices by proper license headers.
diego
parents:
26757
diff
changeset
|
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
972 | 23 */ |
24 | |
966 | 25 #include <stdio.h> |
1038
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
993
diff
changeset
|
26 #include <stdlib.h> |
12093
f54d02f6ddbf
let uninit wait until sound is completely played, don't restore volume at exit, fixed ringbuffer bug, patch by Nehal <nehalmistry at gmx.net>\n
faust3
parents:
12027
diff
changeset
|
27 #include <string.h> |
966 | 28 |
14123 | 29 #include "config.h" |
30 #include "mp_msg.h" | |
31 #include "help_mp.h" | |
8027 | 32 |
966 | 33 #include "audio_out.h" |
34 #include "audio_out_internal.h" | |
14245 | 35 #include "libaf/af_format.h" |
6184 | 36 #include <SDL.h> |
12093
f54d02f6ddbf
let uninit wait until sound is completely played, don't restore volume at exit, fixed ringbuffer bug, patch by Nehal <nehalmistry at gmx.net>\n
faust3
parents:
12027
diff
changeset
|
37 #include "osdep/timer.h" |
966 | 38 |
14123 | 39 #include "libvo/fastmemcpy.h" |
972 | 40 |
966 | 41 static ao_info_t info = |
42 { | |
43 "SDLlib audio output", | |
44 "sdl", | |
45 "Felix Buenemann <atmosfear@users.sourceforge.net>", | |
46 "" | |
47 }; | |
48 | |
49 LIBAO_EXTERN(sdl) | |
50 | |
12673
c1371fce7267
make the internal sdl mixer optional, idea by Reimar Doffinger
alex
parents:
12440
diff
changeset
|
51 // turn this on if you want to use the slower SDL_MixAudio |
12908
7b9b4f07d2c4
automatic loading of af_volume, original patch by Dan Christiansen (danchr (at) daimi (dot) au (dot) dk)
reimar
parents:
12714
diff
changeset
|
52 #undef USE_SDL_INTERNAL_MIXER |
12673
c1371fce7267
make the internal sdl mixer optional, idea by Reimar Doffinger
alex
parents:
12440
diff
changeset
|
53 |
972 | 54 // Samplesize used by the SDLlib AudioSpec struct |
27727
48c1ae64255b
Replace preprocessor check for WIN32 with checks for __MINGW32__ and __CYGWIN__.
diego
parents:
27509
diff
changeset
|
55 #if defined(__MINGW32__) || defined(__CYGWIN__) || defined(__AMIGAOS4__) |
12019
6ede5366bc47
fix compilation with sdl on mingw patch by Nehal <nehalmistry at gmx.net>
faust3
parents:
11750
diff
changeset
|
56 #define SAMPLESIZE 2048 |
12113 | 57 #else |
58 #define SAMPLESIZE 1024 | |
59 #endif | |
972 | 60 |
13832
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
61 #define CHUNK_SIZE 4096 |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
62 #define NUM_CHUNKS 8 |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
63 // This type of ring buffer may never fill up completely, at least |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
64 // one byte must always be unused. |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
65 // For performance reasons (alignment etc.) one whole chunk always stays |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
66 // empty, not only one byte. |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
67 #define BUFFSIZE ((NUM_CHUNKS + 1) * CHUNK_SIZE) |
972 | 68 |
13832
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
69 static unsigned char *buffer; |
972 | 70 |
13832
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
71 // may only be modified by SDL's playback thread or while it is stopped |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
72 static volatile int read_pos; |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
73 // may only be modified by mplayer's thread |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
74 static volatile int write_pos; |
12673
c1371fce7267
make the internal sdl mixer optional, idea by Reimar Doffinger
alex
parents:
12440
diff
changeset
|
75 #ifdef USE_SDL_INTERNAL_MIXER |
12093
f54d02f6ddbf
let uninit wait until sound is completely played, don't restore volume at exit, fixed ringbuffer bug, patch by Nehal <nehalmistry at gmx.net>\n
faust3
parents:
12027
diff
changeset
|
76 static unsigned char volume=SDL_MIX_MAXVOLUME; |
12673
c1371fce7267
make the internal sdl mixer optional, idea by Reimar Doffinger
alex
parents:
12440
diff
changeset
|
77 #endif |
972 | 78 |
13832
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
79 // may only be called by mplayer's thread |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
80 // return value may change between immediately following two calls, |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
81 // and the real number of free bytes might be larger! |
17566
f580a7755ac5
Patch by Stefan Huehner / stefan % huehner ! org \
rathann
parents:
17245
diff
changeset
|
82 static int buf_free(void) { |
13832
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
83 int free = read_pos - write_pos - CHUNK_SIZE; |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
84 if (free < 0) free += BUFFSIZE; |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
85 return free; |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
86 } |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
87 |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
88 // may only be called by SDL's playback thread |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
89 // return value may change between immediately following two calls, |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
90 // and the real number of buffered bytes might be larger! |
17566
f580a7755ac5
Patch by Stefan Huehner / stefan % huehner ! org \
rathann
parents:
17245
diff
changeset
|
91 static int buf_used(void) { |
13832
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
92 int used = write_pos - read_pos; |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
93 if (used < 0) used += BUFFSIZE; |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
94 return used; |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
95 } |
1038
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
993
diff
changeset
|
96 |
972 | 97 static int write_buffer(unsigned char* data,int len){ |
13832
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
98 int first_len = BUFFSIZE - write_pos; |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
99 int free = buf_free(); |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
100 if (len > free) len = free; |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
101 if (first_len > len) first_len = len; |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
102 // till end of buffer |
23457
a124f3abc1ec
Replace implicit use of fast_memcpy via macro by explicit use to allow
reimar
parents:
22104
diff
changeset
|
103 fast_memcpy (&buffer[write_pos], data, first_len); |
13832
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
104 if (len > first_len) { // we have to wrap around |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
105 // remaining part from beginning of buffer |
23457
a124f3abc1ec
Replace implicit use of fast_memcpy via macro by explicit use to allow
reimar
parents:
22104
diff
changeset
|
106 fast_memcpy (buffer, &data[first_len], len - first_len); |
972 | 107 } |
13832
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
108 write_pos = (write_pos + len) % BUFFSIZE; |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
109 return len; |
972 | 110 } |
111 | |
112 static int read_buffer(unsigned char* data,int len){ | |
13832
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
113 int first_len = BUFFSIZE - read_pos; |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
114 int buffered = buf_used(); |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
115 if (len > buffered) len = buffered; |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
116 if (first_len > len) first_len = len; |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
117 // till end of buffer |
12673
c1371fce7267
make the internal sdl mixer optional, idea by Reimar Doffinger
alex
parents:
12440
diff
changeset
|
118 #ifdef USE_SDL_INTERNAL_MIXER |
13832
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
119 SDL_MixAudio (data, &buffer[read_pos], first_len, volume); |
12673
c1371fce7267
make the internal sdl mixer optional, idea by Reimar Doffinger
alex
parents:
12440
diff
changeset
|
120 #else |
23457
a124f3abc1ec
Replace implicit use of fast_memcpy via macro by explicit use to allow
reimar
parents:
22104
diff
changeset
|
121 fast_memcpy (data, &buffer[read_pos], first_len); |
12673
c1371fce7267
make the internal sdl mixer optional, idea by Reimar Doffinger
alex
parents:
12440
diff
changeset
|
122 #endif |
13832
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
123 if (len > first_len) { // we have to wrap around |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
124 // remaining part from beginning of buffer |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
125 #ifdef USE_SDL_INTERNAL_MIXER |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
126 SDL_MixAudio (&data[first_len], buffer, len - first_len, volume); |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
127 #else |
23457
a124f3abc1ec
Replace implicit use of fast_memcpy via macro by explicit use to allow
reimar
parents:
22104
diff
changeset
|
128 fast_memcpy (&data[first_len], buffer, len - first_len); |
13832
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
129 #endif |
972 | 130 } |
13832
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
131 read_pos = (read_pos + len) % BUFFSIZE; |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
132 return len; |
972 | 133 } |
134 | |
135 // end ring buffer stuff | |
966 | 136 |
1038
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
993
diff
changeset
|
137 |
966 | 138 // to set/get/query special features/parameters |
9633
12b1790038b0
64bit libao2 fix by Jens Axboe <mplayer-dev@kernel.dk>
alex
parents:
8027
diff
changeset
|
139 static int control(int cmd,void *arg){ |
12673
c1371fce7267
make the internal sdl mixer optional, idea by Reimar Doffinger
alex
parents:
12440
diff
changeset
|
140 #ifdef USE_SDL_INTERNAL_MIXER |
6184 | 141 switch (cmd) { |
142 case AOCONTROL_GET_VOLUME: | |
143 { | |
144 ao_control_vol_t* vol = (ao_control_vol_t*)arg; | |
12093
f54d02f6ddbf
let uninit wait until sound is completely played, don't restore volume at exit, fixed ringbuffer bug, patch by Nehal <nehalmistry at gmx.net>\n
faust3
parents:
12027
diff
changeset
|
145 vol->left = vol->right = volume * 100 / SDL_MIX_MAXVOLUME; |
6184 | 146 return CONTROL_OK; |
147 } | |
148 case AOCONTROL_SET_VOLUME: | |
149 { | |
12093
f54d02f6ddbf
let uninit wait until sound is completely played, don't restore volume at exit, fixed ringbuffer bug, patch by Nehal <nehalmistry at gmx.net>\n
faust3
parents:
12027
diff
changeset
|
150 int diff; |
6184 | 151 ao_control_vol_t* vol = (ao_control_vol_t*)arg; |
152 diff = (vol->left+vol->right) / 2; | |
12093
f54d02f6ddbf
let uninit wait until sound is completely played, don't restore volume at exit, fixed ringbuffer bug, patch by Nehal <nehalmistry at gmx.net>\n
faust3
parents:
12027
diff
changeset
|
153 volume = diff * SDL_MIX_MAXVOLUME / 100; |
6184 | 154 return CONTROL_OK; |
155 } | |
156 } | |
12673
c1371fce7267
make the internal sdl mixer optional, idea by Reimar Doffinger
alex
parents:
12440
diff
changeset
|
157 #endif |
c1371fce7267
make the internal sdl mixer optional, idea by Reimar Doffinger
alex
parents:
12440
diff
changeset
|
158 return CONTROL_UNKNOWN; |
966 | 159 } |
160 | |
972 | 161 // SDL Callback function |
162 void outputaudio(void *unused, Uint8 *stream, int len) { | |
163 //SDL_MixAudio(stream, read_buffer(buffers, len), len, SDL_MIX_MAXVOLUME); | |
1066 | 164 //if(!full_buffers) printf("SDL: Buffer underrun!\n"); |
165 | |
972 | 166 read_buffer(stream, len); |
1066 | 167 //printf("SDL: Full Buffers: %i\n", full_buffers); |
966 | 168 } |
169 | |
170 // open & setup audio device | |
171 // return: 1=success 0=fail | |
172 static int init(int rate,int channels,int format,int flags){ | |
173 | |
972 | 174 /* SDL Audio Specifications */ |
7908
dc96a3eb9fab
Check what we obtain in SDL_OpenAudio() - allows to build the
colin
parents:
7897
diff
changeset
|
175 SDL_AudioSpec aspec, obtained; |
972 | 176 |
177 /* Allocate ring-buffer memory */ | |
13832
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
178 buffer = (unsigned char *) malloc(BUFFSIZE); |
972 | 179 |
14264 | 180 mp_msg(MSGT_AO,MSGL_INFO,MSGTR_AO_SDL_INFO, rate, (channels > 1) ? "Stereo" : "Mono", af_fmt2str_short(format)); |
983 | 181 |
1189 | 182 if(ao_subdevice) { |
183 setenv("SDL_AUDIODRIVER", ao_subdevice, 1); | |
13383
c1955840883d
mp_msg transition of unmaintained audio output drivers.
ivo
parents:
12908
diff
changeset
|
184 mp_msg(MSGT_AO,MSGL_INFO,MSGTR_AO_SDL_DriverInfo, ao_subdevice); |
1189 | 185 } |
3095 | 186 |
7660 | 187 ao_data.channels=channels; |
188 ao_data.samplerate=rate; | |
189 ao_data.format=format; | |
190 | |
3137 | 191 ao_data.bps=channels*rate; |
14245 | 192 if(format != AF_FORMAT_U8 && format != AF_FORMAT_S8) |
3095 | 193 ao_data.bps*=2; |
966 | 194 |
1066 | 195 /* The desired audio format (see SDL_AudioSpec) */ |
196 switch(format) { | |
14245 | 197 case AF_FORMAT_U8: |
1066 | 198 aspec.format = AUDIO_U8; |
199 break; | |
14245 | 200 case AF_FORMAT_S16_LE: |
1066 | 201 aspec.format = AUDIO_S16LSB; |
202 break; | |
14245 | 203 case AF_FORMAT_S16_BE: |
1066 | 204 aspec.format = AUDIO_S16MSB; |
205 break; | |
14245 | 206 case AF_FORMAT_S8: |
1066 | 207 aspec.format = AUDIO_S8; |
208 break; | |
14245 | 209 case AF_FORMAT_U16_LE: |
1066 | 210 aspec.format = AUDIO_U16LSB; |
211 break; | |
14245 | 212 case AF_FORMAT_U16_BE: |
1066 | 213 aspec.format = AUDIO_U16MSB; |
214 break; | |
215 default: | |
12440
56bdb9b7a4bc
use fallback for unsupported formats instead of quitting
reimar
parents:
12151
diff
changeset
|
216 aspec.format = AUDIO_S16LSB; |
14245 | 217 ao_data.format = AF_FORMAT_S16_LE; |
13383
c1955840883d
mp_msg transition of unmaintained audio output drivers.
ivo
parents:
12908
diff
changeset
|
218 mp_msg(MSGT_AO,MSGL_WARN,MSGTR_AO_SDL_UnsupportedAudioFmt, format); |
1066 | 219 } |
220 | |
966 | 221 /* The desired audio frequency in samples-per-second. */ |
222 aspec.freq = rate; | |
223 | |
224 /* Number of channels (mono/stereo) */ | |
225 aspec.channels = channels; | |
226 | |
227 /* The desired size of the audio buffer in samples. This number should be a power of two, and may be adjusted by the audio driver to a value more suitable for the hardware. Good values seem to range between 512 and 8192 inclusive, depending on the application and CPU speed. Smaller values yield faster response time, but can lead to underflow if the application is doing heavy processing and cannot fill the audio buffer in time. A stereo sample consists of both right and left channels in LR ordering. Note that the number of samples is directly related to time by the following formula: ms = (samples*1000)/freq */ | |
972 | 228 aspec.samples = SAMPLESIZE; |
966 | 229 |
230 /* This should be set to a function that will be called when the audio device is ready for more data. It is passed a pointer to the audio buffer, and the length in bytes of the audio buffer. This function usually runs in a separate thread, and so you should protect data structures that it accesses by calling SDL_LockAudio and SDL_UnlockAudio in your code. The callback prototype is: | |
231 void callback(void *userdata, Uint8 *stream, int len); userdata is the pointer stored in userdata field of the SDL_AudioSpec. stream is a pointer to the audio buffer you want to fill with information and len is the length of the audio buffer in bytes. */ | |
972 | 232 aspec.callback = outputaudio; |
966 | 233 |
234 /* This pointer is passed as the first parameter to the callback function. */ | |
235 aspec.userdata = NULL; | |
236 | |
972 | 237 /* initialize the SDL Audio system */ |
238 if (SDL_Init (SDL_INIT_AUDIO/*|SDL_INIT_NOPARACHUTE*/)) { | |
13383
c1955840883d
mp_msg transition of unmaintained audio output drivers.
ivo
parents:
12908
diff
changeset
|
239 mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_SDL_CantInit, SDL_GetError()); |
972 | 240 return 0; |
241 } | |
242 | |
966 | 243 /* Open the audio device and start playing sound! */ |
7908
dc96a3eb9fab
Check what we obtain in SDL_OpenAudio() - allows to build the
colin
parents:
7897
diff
changeset
|
244 if(SDL_OpenAudio(&aspec, &obtained) < 0) { |
13383
c1955840883d
mp_msg transition of unmaintained audio output drivers.
ivo
parents:
12908
diff
changeset
|
245 mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_SDL_CantOpenAudio, SDL_GetError()); |
26757
0fdf04b07ecb
cosmetics: Remove pointless parentheses from return statements.
diego
parents:
25335
diff
changeset
|
246 return 0; |
966 | 247 } |
7908
dc96a3eb9fab
Check what we obtain in SDL_OpenAudio() - allows to build the
colin
parents:
7897
diff
changeset
|
248 |
dc96a3eb9fab
Check what we obtain in SDL_OpenAudio() - allows to build the
colin
parents:
7897
diff
changeset
|
249 /* did we got what we wanted ? */ |
dc96a3eb9fab
Check what we obtain in SDL_OpenAudio() - allows to build the
colin
parents:
7897
diff
changeset
|
250 ao_data.channels=obtained.channels; |
dc96a3eb9fab
Check what we obtain in SDL_OpenAudio() - allows to build the
colin
parents:
7897
diff
changeset
|
251 ao_data.samplerate=obtained.freq; |
dc96a3eb9fab
Check what we obtain in SDL_OpenAudio() - allows to build the
colin
parents:
7897
diff
changeset
|
252 |
dc96a3eb9fab
Check what we obtain in SDL_OpenAudio() - allows to build the
colin
parents:
7897
diff
changeset
|
253 switch(obtained.format) { |
dc96a3eb9fab
Check what we obtain in SDL_OpenAudio() - allows to build the
colin
parents:
7897
diff
changeset
|
254 case AUDIO_U8 : |
14245 | 255 ao_data.format = AF_FORMAT_U8; |
7908
dc96a3eb9fab
Check what we obtain in SDL_OpenAudio() - allows to build the
colin
parents:
7897
diff
changeset
|
256 break; |
dc96a3eb9fab
Check what we obtain in SDL_OpenAudio() - allows to build the
colin
parents:
7897
diff
changeset
|
257 case AUDIO_S16LSB : |
14245 | 258 ao_data.format = AF_FORMAT_S16_LE; |
7908
dc96a3eb9fab
Check what we obtain in SDL_OpenAudio() - allows to build the
colin
parents:
7897
diff
changeset
|
259 break; |
dc96a3eb9fab
Check what we obtain in SDL_OpenAudio() - allows to build the
colin
parents:
7897
diff
changeset
|
260 case AUDIO_S16MSB : |
14245 | 261 ao_data.format = AF_FORMAT_S16_BE; |
7908
dc96a3eb9fab
Check what we obtain in SDL_OpenAudio() - allows to build the
colin
parents:
7897
diff
changeset
|
262 break; |
dc96a3eb9fab
Check what we obtain in SDL_OpenAudio() - allows to build the
colin
parents:
7897
diff
changeset
|
263 case AUDIO_S8 : |
14245 | 264 ao_data.format = AF_FORMAT_S8; |
7908
dc96a3eb9fab
Check what we obtain in SDL_OpenAudio() - allows to build the
colin
parents:
7897
diff
changeset
|
265 break; |
dc96a3eb9fab
Check what we obtain in SDL_OpenAudio() - allows to build the
colin
parents:
7897
diff
changeset
|
266 case AUDIO_U16LSB : |
14245 | 267 ao_data.format = AF_FORMAT_U16_LE; |
7908
dc96a3eb9fab
Check what we obtain in SDL_OpenAudio() - allows to build the
colin
parents:
7897
diff
changeset
|
268 break; |
dc96a3eb9fab
Check what we obtain in SDL_OpenAudio() - allows to build the
colin
parents:
7897
diff
changeset
|
269 case AUDIO_U16MSB : |
14245 | 270 ao_data.format = AF_FORMAT_U16_BE; |
7908
dc96a3eb9fab
Check what we obtain in SDL_OpenAudio() - allows to build the
colin
parents:
7897
diff
changeset
|
271 break; |
dc96a3eb9fab
Check what we obtain in SDL_OpenAudio() - allows to build the
colin
parents:
7897
diff
changeset
|
272 default: |
13383
c1955840883d
mp_msg transition of unmaintained audio output drivers.
ivo
parents:
12908
diff
changeset
|
273 mp_msg(MSGT_AO,MSGL_WARN,MSGTR_AO_SDL_UnsupportedAudioFmt, obtained.format); |
7908
dc96a3eb9fab
Check what we obtain in SDL_OpenAudio() - allows to build the
colin
parents:
7897
diff
changeset
|
274 return 0; |
dc96a3eb9fab
Check what we obtain in SDL_OpenAudio() - allows to build the
colin
parents:
7897
diff
changeset
|
275 } |
dc96a3eb9fab
Check what we obtain in SDL_OpenAudio() - allows to build the
colin
parents:
7897
diff
changeset
|
276 |
8027 | 277 mp_msg(MSGT_AO,MSGL_V,"SDL: buf size = %d\n",obtained.size); |
7908
dc96a3eb9fab
Check what we obtain in SDL_OpenAudio() - allows to build the
colin
parents:
7897
diff
changeset
|
278 ao_data.buffersize=obtained.size; |
13887
48ce49693b3c
respect immed uninit flag, initialize ao_data.outburst.
reimar
parents:
13832
diff
changeset
|
279 ao_data.outburst = CHUNK_SIZE; |
974 | 280 |
13832
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
281 reset(); |
966 | 282 /* unsilence audio, if callback is ready */ |
283 SDL_PauseAudio(0); | |
284 | |
285 return 1; | |
286 } | |
287 | |
288 // close audio device | |
12145 | 289 static void uninit(int immed){ |
8027 | 290 mp_msg(MSGT_AO,MSGL_V,"SDL: Audio Subsystem shutting down!\n"); |
13887
48ce49693b3c
respect immed uninit flag, initialize ao_data.outburst.
reimar
parents:
13832
diff
changeset
|
291 if (!immed) |
14849
d313f591d1a4
aos should respect the immed uninit flag (quit immediatly vs waiting till file
reimar
parents:
14264
diff
changeset
|
292 usec_sleep(get_delay() * 1000 * 1000); |
966 | 293 SDL_CloseAudio(); |
972 | 294 SDL_QuitSubSystem(SDL_INIT_AUDIO); |
966 | 295 } |
296 | |
297 // stop playing and empty buffers (for seeking/pause) | |
17566
f580a7755ac5
Patch by Stefan Huehner / stefan % huehner ! org \
rathann
parents:
17245
diff
changeset
|
298 static void reset(void){ |
1066 | 299 |
1091 | 300 //printf("SDL: reset called!\n"); |
1066 | 301 |
13832
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
302 SDL_PauseAudio(1); |
972 | 303 /* Reset ring-buffer state */ |
13832
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
304 read_pos = 0; |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
305 write_pos = 0; |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
306 SDL_PauseAudio(0); |
966 | 307 } |
308 | |
1038
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
993
diff
changeset
|
309 // stop playing, keep buffers (for pause) |
17566
f580a7755ac5
Patch by Stefan Huehner / stefan % huehner ! org \
rathann
parents:
17245
diff
changeset
|
310 static void audio_pause(void) |
1038
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
993
diff
changeset
|
311 { |
1070 | 312 |
1091 | 313 //printf("SDL: audio_pause called!\n"); |
7897
7674e94baff7
Change SDL_(Un)lockAudio to PauseAudio() (works better)
colin
parents:
7660
diff
changeset
|
314 SDL_PauseAudio(1); |
1070 | 315 |
1038
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
993
diff
changeset
|
316 } |
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
993
diff
changeset
|
317 |
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
993
diff
changeset
|
318 // resume playing, after audio_pause() |
17566
f580a7755ac5
Patch by Stefan Huehner / stefan % huehner ! org \
rathann
parents:
17245
diff
changeset
|
319 static void audio_resume(void) |
1038
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
993
diff
changeset
|
320 { |
1091 | 321 //printf("SDL: audio_resume called!\n"); |
7897
7674e94baff7
Change SDL_(Un)lockAudio to PauseAudio() (works better)
colin
parents:
7660
diff
changeset
|
322 SDL_PauseAudio(0); |
1038
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
993
diff
changeset
|
323 } |
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
993
diff
changeset
|
324 |
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
993
diff
changeset
|
325 |
966 | 326 // return: how many bytes can be played without blocking |
17566
f580a7755ac5
Patch by Stefan Huehner / stefan % huehner ! org \
rathann
parents:
17245
diff
changeset
|
327 static int get_space(void){ |
13832
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
328 return buf_free(); |
966 | 329 } |
330 | |
331 // plays 'len' bytes of 'data' | |
332 // it should round it down to outburst*n | |
333 // return: number of bytes played | |
334 static int play(void* data,int len,int flags){ | |
972 | 335 |
22104 | 336 if (!(flags & AOPLAY_FINAL_CHUNK)) |
12151
75fdb659f5bf
round len to outburst and increment full_buffers at the correct time, patch by Nehal <nehalmistry at gmx.net>
faust3
parents:
12145
diff
changeset
|
337 len = (len/ao_data.outburst)*ao_data.outburst; |
985 | 338 #if 0 |
972 | 339 int ret; |
966 | 340 |
972 | 341 /* Audio locking prohibits call of outputaudio */ |
966 | 342 SDL_LockAudio(); |
972 | 343 // copy audio stream into ring-buffer |
344 ret = write_buffer(data, len); | |
966 | 345 SDL_UnlockAudio(); |
346 | |
972 | 347 return ret; |
348 #else | |
349 return write_buffer(data, len); | |
350 #endif | |
966 | 351 } |
352 | |
3095 | 353 // return: delay in seconds between first and last sample in buffer |
17566
f580a7755ac5
Patch by Stefan Huehner / stefan % huehner ! org \
rathann
parents:
17245
diff
changeset
|
354 static float get_delay(void){ |
13832
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
355 int buffered = BUFFSIZE - CHUNK_SIZE - buf_free(); // could be less |
2f8cfe66dbfd
Different buffering scheme, avoiding possible races (SDL is using threads!).
reimar
parents:
13383
diff
changeset
|
356 return (float)(buffered + ao_data.buffersize)/(float)ao_data.bps; |
966 | 357 } |
358 | |
359 | |
360 | |
361 | |
362 | |
363 |