diff options
-rw-r--r-- | apps/plugin.c | 6 | ||||
-rw-r--r-- | apps/plugin.h | 10 | ||||
-rw-r--r-- | apps/plugins/test_sampr.c | 6 | ||||
-rw-r--r-- | apps/recorder/recording.c | 19 | ||||
-rw-r--r-- | uisimulator/sdl/sound.c | 304 |
5 files changed, 256 insertions, 89 deletions
diff --git a/apps/plugin.c b/apps/plugin.c index 0ce214cbde..ea228c454c 100644 --- a/apps/plugin.c +++ b/apps/plugin.c | |||
@@ -309,7 +309,7 @@ static const struct plugin_api rockbox_api = { | |||
309 | utf8seek, | 309 | utf8seek, |
310 | 310 | ||
311 | /* sound */ | 311 | /* sound */ |
312 | #if CONFIG_CODEC == SWCODEC && defined(HAVE_RECORDING) | 312 | #if CONFIG_CODEC == SWCODEC |
313 | sound_default, | 313 | sound_default, |
314 | #endif | 314 | #endif |
315 | sound_set, | 315 | sound_set, |
@@ -329,9 +329,7 @@ static const struct plugin_api rockbox_api = { | |||
329 | #if CONFIG_CODEC == SWCODEC | 329 | #if CONFIG_CODEC == SWCODEC |
330 | &audio_master_sampr_list[0], | 330 | &audio_master_sampr_list[0], |
331 | &hw_freq_sampr[0], | 331 | &hw_freq_sampr[0], |
332 | #ifndef SIMULATOR | ||
333 | pcm_apply_settings, | 332 | pcm_apply_settings, |
334 | #endif | ||
335 | pcm_play_data, | 333 | pcm_play_data, |
336 | pcm_play_stop, | 334 | pcm_play_stop, |
337 | pcm_set_frequency, | 335 | pcm_set_frequency, |
@@ -342,7 +340,6 @@ static const struct plugin_api rockbox_api = { | |||
342 | pcm_calculate_peaks, | 340 | pcm_calculate_peaks, |
343 | #ifdef HAVE_RECORDING | 341 | #ifdef HAVE_RECORDING |
344 | &rec_freq_sampr[0], | 342 | &rec_freq_sampr[0], |
345 | #ifndef SIMULATOR | ||
346 | pcm_init_recording, | 343 | pcm_init_recording, |
347 | pcm_close_recording, | 344 | pcm_close_recording, |
348 | pcm_record_data, | 345 | pcm_record_data, |
@@ -352,7 +349,6 @@ static const struct plugin_api rockbox_api = { | |||
352 | audio_set_recording_gain, | 349 | audio_set_recording_gain, |
353 | audio_set_output_source, | 350 | audio_set_output_source, |
354 | rec_set_source, | 351 | rec_set_source, |
355 | #endif | ||
356 | #endif /* HAVE_RECORDING */ | 352 | #endif /* HAVE_RECORDING */ |
357 | 353 | ||
358 | #endif | 354 | #endif |
diff --git a/apps/plugin.h b/apps/plugin.h index 2886b0938f..987c07067d 100644 --- a/apps/plugin.h +++ b/apps/plugin.h | |||
@@ -110,12 +110,12 @@ | |||
110 | #define PLUGIN_MAGIC 0x526F634B /* RocK */ | 110 | #define PLUGIN_MAGIC 0x526F634B /* RocK */ |
111 | 111 | ||
112 | /* increase this every time the api struct changes */ | 112 | /* increase this every time the api struct changes */ |
113 | #define PLUGIN_API_VERSION 53 | 113 | #define PLUGIN_API_VERSION 54 |
114 | 114 | ||
115 | /* update this to latest version if a change to the api struct breaks | 115 | /* update this to latest version if a change to the api struct breaks |
116 | backwards compatibility (and please take the opportunity to sort in any | 116 | backwards compatibility (and please take the opportunity to sort in any |
117 | new function which are "waiting" at the end of the function table) */ | 117 | new function which are "waiting" at the end of the function table) */ |
118 | #define PLUGIN_MIN_API_VERSION 52 | 118 | #define PLUGIN_MIN_API_VERSION 54 |
119 | 119 | ||
120 | /* plugin return codes */ | 120 | /* plugin return codes */ |
121 | enum plugin_status { | 121 | enum plugin_status { |
@@ -404,7 +404,7 @@ struct plugin_api { | |||
404 | int (*utf8seek)(const unsigned char* utf8, int offset); | 404 | int (*utf8seek)(const unsigned char* utf8, int offset); |
405 | 405 | ||
406 | /* sound */ | 406 | /* sound */ |
407 | #if CONFIG_CODEC == SWCODEC && defined(HAVE_RECORDING) | 407 | #if CONFIG_CODEC == SWCODEC |
408 | int (*sound_default)(int setting); | 408 | int (*sound_default)(int setting); |
409 | #endif | 409 | #endif |
410 | void (*sound_set)(int setting, int value); | 410 | void (*sound_set)(int setting, int value); |
@@ -424,9 +424,7 @@ struct plugin_api { | |||
424 | #if CONFIG_CODEC == SWCODEC | 424 | #if CONFIG_CODEC == SWCODEC |
425 | const unsigned long *audio_master_sampr_list; | 425 | const unsigned long *audio_master_sampr_list; |
426 | const unsigned long *hw_freq_sampr; | 426 | const unsigned long *hw_freq_sampr; |
427 | #ifndef SIMULATOR | ||
428 | void (*pcm_apply_settings)(void); | 427 | void (*pcm_apply_settings)(void); |
429 | #endif | ||
430 | void (*pcm_play_data)(pcm_more_callback_type get_more, | 428 | void (*pcm_play_data)(pcm_more_callback_type get_more, |
431 | unsigned char* start, size_t size); | 429 | unsigned char* start, size_t size); |
432 | void (*pcm_play_stop)(void); | 430 | void (*pcm_play_stop)(void); |
@@ -438,7 +436,6 @@ struct plugin_api { | |||
438 | void (*pcm_calculate_peaks)(int *left, int *right); | 436 | void (*pcm_calculate_peaks)(int *left, int *right); |
439 | #ifdef HAVE_RECORDING | 437 | #ifdef HAVE_RECORDING |
440 | const unsigned long *rec_freq_sampr; | 438 | const unsigned long *rec_freq_sampr; |
441 | #ifndef SIMULATOR | ||
442 | void (*pcm_init_recording)(void); | 439 | void (*pcm_init_recording)(void); |
443 | void (*pcm_close_recording)(void); | 440 | void (*pcm_close_recording)(void); |
444 | void (*pcm_record_data)(pcm_more_callback_type2 more_ready, | 441 | void (*pcm_record_data)(pcm_more_callback_type2 more_ready, |
@@ -449,7 +446,6 @@ struct plugin_api { | |||
449 | void (*audio_set_recording_gain)(int left, int right, int type); | 446 | void (*audio_set_recording_gain)(int left, int right, int type); |
450 | void (*audio_set_output_source)(int monitor); | 447 | void (*audio_set_output_source)(int monitor); |
451 | void (*rec_set_source)(int source, unsigned flags); | 448 | void (*rec_set_source)(int source, unsigned flags); |
452 | #endif | ||
453 | #endif /* HAVE_RECORDING */ | 449 | #endif /* HAVE_RECORDING */ |
454 | 450 | ||
455 | #endif | 451 | #endif |
diff --git a/apps/plugins/test_sampr.c b/apps/plugins/test_sampr.c index 7e78137e97..891e68ffda 100644 --- a/apps/plugins/test_sampr.c +++ b/apps/plugins/test_sampr.c | |||
@@ -198,10 +198,14 @@ void play_waveform(void) | |||
198 | rb->audio_stop(); | 198 | rb->audio_stop(); |
199 | rb->sound_set(SOUND_VOLUME, rb->sound_default(SOUND_VOLUME)); | 199 | rb->sound_set(SOUND_VOLUME, rb->sound_default(SOUND_VOLUME)); |
200 | 200 | ||
201 | #ifdef HAVE_RECORDING | ||
201 | /* Select playback */ | 202 | /* Select playback */ |
202 | rb->rec_set_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK); | 203 | rb->rec_set_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK); |
204 | #endif | ||
203 | 205 | ||
206 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | ||
204 | rb->cpu_boost(true); | 207 | rb->cpu_boost(true); |
208 | #endif | ||
205 | 209 | ||
206 | rb->pcm_set_frequency(rb->hw_freq_sampr[freq]); | 210 | rb->pcm_set_frequency(rb->hw_freq_sampr[freq]); |
207 | 211 | ||
@@ -223,7 +227,9 @@ void play_waveform(void) | |||
223 | while (rb->pcm_is_playing()) | 227 | while (rb->pcm_is_playing()) |
224 | rb->yield(); | 228 | rb->yield(); |
225 | 229 | ||
230 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | ||
226 | rb->cpu_boost(false); | 231 | rb->cpu_boost(false); |
232 | #endif | ||
227 | 233 | ||
228 | /* restore default - user of apis is responsible for restoring | 234 | /* restore default - user of apis is responsible for restoring |
229 | default state - normally playback at 44100Hz */ | 235 | default state - normally playback at 44100Hz */ |
diff --git a/apps/recorder/recording.c b/apps/recorder/recording.c index 025480cf91..d0e79bcdd7 100644 --- a/apps/recorder/recording.c +++ b/apps/recorder/recording.c | |||
@@ -2100,6 +2100,12 @@ void audio_set_recording_gain(int left, int right, int type) | |||
2100 | type = type; | 2100 | type = type; |
2101 | } | 2101 | } |
2102 | 2102 | ||
2103 | void audio_set_output_source(int source) | ||
2104 | { | ||
2105 | source = source; | ||
2106 | } | ||
2107 | |||
2108 | |||
2103 | void audio_record(const char *filename) | 2109 | void audio_record(const char *filename) |
2104 | { | 2110 | { |
2105 | filename = filename; | 2111 | filename = filename; |
@@ -2117,19 +2123,6 @@ void audio_resume_recording(void) | |||
2117 | { | 2123 | { |
2118 | } | 2124 | } |
2119 | 2125 | ||
2120 | void pcm_calculate_rec_peaks(int *left, int *right) | ||
2121 | { | ||
2122 | if (left) | ||
2123 | *left = 0; | ||
2124 | if (right) | ||
2125 | *right = 0; | ||
2126 | } | ||
2127 | |||
2128 | unsigned long pcm_rec_status(void) | ||
2129 | { | ||
2130 | return 0; | ||
2131 | } | ||
2132 | |||
2133 | #endif /* #ifdef SIMULATOR */ | 2126 | #endif /* #ifdef SIMULATOR */ |
2134 | #endif /* #ifdef CONFIG_CODEC == SWCODEC */ | 2127 | #endif /* #ifdef CONFIG_CODEC == SWCODEC */ |
2135 | 2128 | ||
diff --git a/uisimulator/sdl/sound.c b/uisimulator/sdl/sound.c index eec9b3e78b..3447112231 100644 --- a/uisimulator/sdl/sound.c +++ b/uisimulator/sdl/sound.c | |||
@@ -25,34 +25,71 @@ | |||
25 | #include "debug.h" | 25 | #include "debug.h" |
26 | #include "kernel.h" | 26 | #include "kernel.h" |
27 | #include "sound.h" | 27 | #include "sound.h" |
28 | #include "pcm_sampr.h" | ||
28 | #include "SDL.h" | 29 | #include "SDL.h" |
29 | 30 | ||
30 | static bool pcm_playing; | 31 | static bool pcm_playing; |
31 | static bool pcm_paused; | 32 | static bool pcm_paused; |
33 | static int cvt_status = -1; | ||
34 | static unsigned long pcm_frequency = SAMPR_44; | ||
35 | static unsigned long pcm_curr_frequency = SAMPR_44; | ||
32 | 36 | ||
33 | static Uint8* pcm_data; | 37 | static Uint8* pcm_data; |
34 | static size_t pcm_data_size; | 38 | static size_t pcm_data_size; |
39 | static size_t pcm_sample_bytes; | ||
40 | static size_t pcm_channel_bytes; | ||
41 | |||
42 | struct pcm_udata | ||
43 | { | ||
44 | Uint8 *stream; | ||
45 | Uint32 num_in; | ||
46 | Uint32 num_out; | ||
47 | FILE *debug; | ||
48 | } udata; | ||
35 | 49 | ||
36 | static SDL_AudioSpec obtained; | 50 | static SDL_AudioSpec obtained; |
37 | static SDL_AudioCVT cvt; | 51 | static SDL_AudioCVT cvt; |
38 | 52 | ||
39 | extern bool debug_audio; | 53 | extern bool debug_audio; |
40 | 54 | ||
41 | static void sdl_dma_start(const void *addr, size_t size) | 55 | #ifndef MIN |
56 | #define MIN(a, b) (((a) < (b)) ? (a) : (b)) | ||
57 | #endif | ||
58 | |||
59 | static void pcm_apply_settings_nolock(void) | ||
42 | { | 60 | { |
43 | pcm_playing = true; | 61 | cvt_status = SDL_BuildAudioCVT(&cvt, AUDIO_S16SYS, 2, pcm_frequency, |
62 | obtained.format, obtained.channels, obtained.freq); | ||
63 | |||
64 | pcm_curr_frequency = pcm_frequency; | ||
65 | |||
66 | if (cvt_status < 0) { | ||
67 | cvt.len_ratio = (double)obtained.freq / (double)pcm_curr_frequency; | ||
68 | } | ||
69 | } | ||
44 | 70 | ||
71 | void pcm_apply_settings(void) | ||
72 | { | ||
45 | SDL_LockAudio(); | 73 | SDL_LockAudio(); |
46 | 74 | pcm_apply_settings_nolock(); | |
75 | SDL_UnlockAudio(); | ||
76 | } | ||
77 | |||
78 | static void sdl_dma_start_nolock(const void *addr, size_t size) | ||
79 | { | ||
80 | pcm_playing = false; | ||
81 | |||
82 | pcm_apply_settings_nolock(); | ||
83 | |||
47 | pcm_data = (Uint8 *) addr; | 84 | pcm_data = (Uint8 *) addr; |
48 | pcm_data_size = size; | 85 | pcm_data_size = size; |
49 | 86 | ||
50 | SDL_UnlockAudio(); | 87 | pcm_playing = true; |
51 | 88 | ||
52 | SDL_PauseAudio(0); | 89 | SDL_PauseAudio(0); |
53 | } | 90 | } |
54 | 91 | ||
55 | static void sdl_dma_stop(void) | 92 | static void sdl_dma_stop_nolock(void) |
56 | { | 93 | { |
57 | pcm_playing = false; | 94 | pcm_playing = false; |
58 | 95 | ||
@@ -65,18 +102,20 @@ static void (*callback_for_more)(unsigned char**, size_t*) = NULL; | |||
65 | void pcm_play_data(void (*get_more)(unsigned char** start, size_t* size), | 102 | void pcm_play_data(void (*get_more)(unsigned char** start, size_t* size), |
66 | unsigned char* start, size_t size) | 103 | unsigned char* start, size_t size) |
67 | { | 104 | { |
105 | SDL_LockAudio(); | ||
106 | |||
68 | callback_for_more = get_more; | 107 | callback_for_more = get_more; |
69 | 108 | ||
70 | if (!(start && size)) { | 109 | if (!(start && size)) { |
71 | if (get_more) | 110 | if (get_more) |
72 | get_more(&start, &size); | 111 | get_more(&start, &size); |
73 | else | ||
74 | return; | ||
75 | } | 112 | } |
76 | 113 | ||
77 | if (start && size) { | 114 | if (start && size) { |
78 | sdl_dma_start(start, size); | 115 | sdl_dma_start_nolock(start, size); |
79 | } | 116 | } |
117 | |||
118 | SDL_UnlockAudio(); | ||
80 | } | 119 | } |
81 | 120 | ||
82 | size_t pcm_get_bytes_waiting(void) | 121 | size_t pcm_get_bytes_waiting(void) |
@@ -91,24 +130,29 @@ void pcm_mute(bool mute) | |||
91 | 130 | ||
92 | void pcm_play_stop(void) | 131 | void pcm_play_stop(void) |
93 | { | 132 | { |
133 | SDL_LockAudio(); | ||
94 | if (pcm_playing) { | 134 | if (pcm_playing) { |
95 | sdl_dma_stop(); | 135 | sdl_dma_stop_nolock(); |
96 | } | 136 | } |
137 | SDL_UnlockAudio(); | ||
97 | } | 138 | } |
98 | 139 | ||
99 | void pcm_play_pause(bool play) | 140 | void pcm_play_pause(bool play) |
100 | { | 141 | { |
101 | size_t next_size; | 142 | size_t next_size; |
102 | Uint8 *next_start; | 143 | Uint8 *next_start; |
144 | |||
145 | SDL_LockAudio(); | ||
103 | 146 | ||
104 | if (!pcm_playing) { | 147 | if (!pcm_playing) { |
148 | SDL_UnlockAudio(); | ||
105 | return; | 149 | return; |
106 | } | 150 | } |
107 | 151 | ||
108 | if(pcm_paused && play) { | 152 | if(pcm_paused && play) { |
109 | if (pcm_get_bytes_waiting()) { | 153 | if (pcm_get_bytes_waiting()) { |
110 | printf("unpause\n"); | 154 | printf("unpause\n"); |
111 | 155 | pcm_apply_settings_nolock(); | |
112 | SDL_PauseAudio(0); | 156 | SDL_PauseAudio(0); |
113 | } else { | 157 | } else { |
114 | printf("unpause, no data waiting\n"); | 158 | printf("unpause, no data waiting\n"); |
@@ -120,9 +164,9 @@ void pcm_play_pause(bool play) | |||
120 | } | 164 | } |
121 | 165 | ||
122 | if (next_start && next_size) { | 166 | if (next_start && next_size) { |
123 | sdl_dma_start(next_start, next_size); | 167 | sdl_dma_start_nolock(next_start, next_size); |
124 | } else { | 168 | } else { |
125 | sdl_dma_stop(); | 169 | sdl_dma_stop_nolock(); |
126 | printf("unpause attempted, no data\n"); | 170 | printf("unpause attempted, no data\n"); |
127 | } | 171 | } |
128 | } | 172 | } |
@@ -133,6 +177,8 @@ void pcm_play_pause(bool play) | |||
133 | } | 177 | } |
134 | 178 | ||
135 | pcm_paused = !play; | 179 | pcm_paused = !play; |
180 | |||
181 | SDL_UnlockAudio(); | ||
136 | } | 182 | } |
137 | 183 | ||
138 | bool pcm_is_paused(void) | 184 | bool pcm_is_paused(void) |
@@ -147,9 +193,26 @@ bool pcm_is_playing(void) | |||
147 | 193 | ||
148 | void pcm_set_frequency(unsigned int frequency) | 194 | void pcm_set_frequency(unsigned int frequency) |
149 | { | 195 | { |
150 | // FIXME: Check return values | 196 | switch (frequency) |
151 | SDL_BuildAudioCVT(&cvt, AUDIO_S16SYS, 2, frequency, | 197 | { |
152 | obtained.format, obtained.channels, obtained.freq); | 198 | HW_HAVE_8_( case SAMPR_8:) |
199 | HW_HAVE_11_(case SAMPR_11:) | ||
200 | HW_HAVE_12_(case SAMPR_12:) | ||
201 | HW_HAVE_16_(case SAMPR_16:) | ||
202 | HW_HAVE_22_(case SAMPR_22:) | ||
203 | HW_HAVE_24_(case SAMPR_24:) | ||
204 | HW_HAVE_32_(case SAMPR_32:) | ||
205 | /* 44100 implied */ | ||
206 | HW_HAVE_48_(case SAMPR_48:) | ||
207 | HW_HAVE_64_(case SAMPR_64:) | ||
208 | HW_HAVE_88_(case SAMPR_88:) | ||
209 | HW_HAVE_96_(case SAMPR_96:) | ||
210 | break; | ||
211 | default: | ||
212 | frequency = SAMPR_44; | ||
213 | } | ||
214 | |||
215 | pcm_frequency = frequency; | ||
153 | } | 216 | } |
154 | 217 | ||
155 | /* | 218 | /* |
@@ -216,83 +279,174 @@ void pcm_calculate_peaks(int *left, int *right) | |||
216 | } | 279 | } |
217 | } | 280 | } |
218 | 281 | ||
219 | static long write_to_soundcard(Uint8 *stream, int len, FILE *debug) { | 282 | void write_to_soundcard(struct pcm_udata *udata) { |
220 | Uint32 written = (((Uint32) len) > pcm_data_size) ? pcm_data_size : (Uint32) len; | ||
221 | |||
222 | if (cvt.needed) { | 283 | if (cvt.needed) { |
223 | cvt.buf = (Uint8 *) malloc(written * cvt.len_mult); | 284 | Uint32 rd = udata->num_in; |
224 | cvt.len = written; | 285 | Uint32 wr = (double)rd * cvt.len_ratio; |
225 | 286 | ||
226 | memcpy(cvt.buf, pcm_data, written); | 287 | if (wr > udata->num_out) { |
288 | wr = udata->num_out; | ||
289 | rd = (double)wr / cvt.len_ratio; | ||
227 | 290 | ||
228 | SDL_ConvertAudio(&cvt); | 291 | if (rd > udata->num_in) |
229 | 292 | { | |
230 | memcpy(stream, cvt.buf, cvt.len_cvt); | 293 | rd = udata->num_in; |
294 | wr = (double)rd * cvt.len_ratio; | ||
295 | } | ||
296 | } | ||
297 | |||
298 | if (wr == 0 || rd == 0) | ||
299 | { | ||
300 | udata->num_out = udata->num_in = 0; | ||
301 | return; | ||
302 | } | ||
303 | |||
304 | if (cvt_status > 0) { | ||
305 | cvt.len = rd * pcm_sample_bytes; | ||
306 | cvt.buf = (Uint8 *) malloc(cvt.len * cvt.len_mult); | ||
307 | |||
308 | memcpy(cvt.buf, pcm_data, cvt.len); | ||
309 | |||
310 | SDL_ConvertAudio(&cvt); | ||
231 | 311 | ||
232 | if (debug != NULL) { | 312 | memcpy(udata->stream, cvt.buf, cvt.len_cvt); |
233 | fwrite(cvt.buf, sizeof(Uint8), cvt.len_cvt, debug); | 313 | |
314 | udata->num_in = cvt.len / pcm_sample_bytes; | ||
315 | udata->num_out = cvt.len_cvt / pcm_sample_bytes; | ||
316 | |||
317 | if (udata->debug != NULL) { | ||
318 | fwrite(cvt.buf, sizeof(Uint8), cvt.len_cvt, udata->debug); | ||
319 | } | ||
320 | |||
321 | free(cvt.buf); | ||
234 | } | 322 | } |
323 | else { | ||
324 | /* Convert is bad, so do silence */ | ||
325 | Uint32 num = wr*obtained.channels; | ||
326 | udata->num_in = rd; | ||
327 | udata->num_out = wr; | ||
328 | |||
329 | switch (pcm_channel_bytes) | ||
330 | { | ||
331 | case 1: | ||
332 | { | ||
333 | Uint8 *stream = udata->stream; | ||
334 | while (num-- > 0) | ||
335 | *stream++ = obtained.silence; | ||
336 | break; | ||
337 | } | ||
338 | case 2: | ||
339 | { | ||
340 | Uint16 *stream = (Uint16 *)udata->stream; | ||
341 | while (num-- > 0) | ||
342 | *stream++ = obtained.silence; | ||
343 | break; | ||
344 | } | ||
345 | } | ||
235 | 346 | ||
236 | free(cvt.buf); | 347 | if (udata->debug != NULL) { |
348 | fwrite(udata->stream, sizeof(Uint8), wr, udata->debug); | ||
349 | } | ||
350 | } | ||
237 | } else { | 351 | } else { |
238 | memcpy(stream, pcm_data, written); | 352 | udata->num_in = udata->num_out = MIN(udata->num_in, udata->num_out); |
353 | memcpy(udata->stream, pcm_data, udata->num_out * pcm_sample_bytes); | ||
239 | 354 | ||
240 | if (debug != NULL) { | 355 | if (udata->debug != NULL) { |
241 | fwrite(pcm_data, sizeof(Uint8), written, debug); | 356 | fwrite(pcm_data, sizeof(Uint8), udata->num_out * pcm_sample_bytes, |
357 | udata->debug); | ||
242 | } | 358 | } |
243 | } | 359 | } |
244 | |||
245 | return written; | ||
246 | } | 360 | } |
247 | 361 | ||
248 | void sdl_audio_callback(void *udata, Uint8 *stream, int len) | 362 | void sdl_audio_callback(struct pcm_udata *udata, Uint8 *stream, int len) |
249 | { | 363 | { |
250 | Uint32 have_now; | 364 | udata->stream = stream; |
251 | FILE *debug = (FILE *) udata; | ||
252 | |||
253 | /* At all times we need to write a full 'len' bytes to stream. */ | ||
254 | 365 | ||
255 | /* Write what we have in the PCM buffer */ | 366 | /* Write what we have in the PCM buffer */ |
256 | if (pcm_data_size > 0) { | 367 | if (pcm_data_size > 0) |
257 | have_now = write_to_soundcard(stream, len, debug); | 368 | goto start; |
258 | |||
259 | stream += have_now; | ||
260 | len -= have_now; | ||
261 | pcm_data += have_now; | ||
262 | pcm_data_size -= have_now; | ||
263 | } | ||
264 | 369 | ||
265 | /* Audio card wants more? Get some more then. */ | 370 | /* Audio card wants more? Get some more then. */ |
266 | while (len > 0) { | 371 | while (len > 0) { |
267 | if (callback_for_more) { | 372 | if ((ssize_t)pcm_data_size <= 0) { |
268 | callback_for_more(&pcm_data, &pcm_data_size); | ||
269 | } else { | ||
270 | pcm_data = NULL; | ||
271 | pcm_data_size = 0; | 373 | pcm_data_size = 0; |
374 | |||
375 | if (callback_for_more) | ||
376 | callback_for_more(&pcm_data, &pcm_data_size); | ||
272 | } | 377 | } |
273 | 378 | ||
274 | if (pcm_data_size > 0) { | 379 | if (pcm_data_size > 0) { |
275 | have_now = write_to_soundcard(stream, len, debug); | 380 | start: |
276 | 381 | udata->num_in = pcm_data_size / pcm_sample_bytes; | |
277 | stream += have_now; | 382 | udata->num_out = len / pcm_sample_bytes; |
278 | len -= have_now; | 383 | |
279 | pcm_data += have_now; | 384 | write_to_soundcard(udata); |
280 | pcm_data_size -= have_now; | 385 | |
386 | udata->num_in *= pcm_sample_bytes; | ||
387 | udata->num_out *= pcm_sample_bytes; | ||
388 | |||
389 | pcm_data += udata->num_in; | ||
390 | pcm_data_size -= udata->num_in; | ||
391 | udata->stream += udata->num_out; | ||
392 | len -= udata->num_out; | ||
281 | } else { | 393 | } else { |
282 | DEBUGF("sdl_audio_callback: No Data.\n"); | 394 | DEBUGF("sdl_audio_callback: No Data.\n"); |
283 | sdl_dma_stop(); | 395 | sdl_dma_stop_nolock(); |
284 | break; | 396 | break; |
285 | } | 397 | } |
286 | } | 398 | } |
287 | } | 399 | } |
288 | 400 | ||
401 | #ifdef HAVE_RECORDING | ||
402 | void pcm_init_recording(void) | ||
403 | { | ||
404 | } | ||
405 | |||
406 | void pcm_close_recording(void) | ||
407 | { | ||
408 | } | ||
409 | |||
410 | void pcm_record_data(void (*more_ready)(void* start, size_t size), | ||
411 | void *start, size_t size) | ||
412 | { | ||
413 | (void)more_ready; | ||
414 | (void)start; | ||
415 | (void)size; | ||
416 | } | ||
417 | |||
418 | void pcm_stop_recording(void) | ||
419 | { | ||
420 | } | ||
421 | |||
422 | void pcm_record_more(void *start, size_t size) | ||
423 | { | ||
424 | (void)start; | ||
425 | (void)size; | ||
426 | } | ||
427 | |||
428 | void pcm_calculate_rec_peaks(int *left, int *right) | ||
429 | { | ||
430 | if (left) | ||
431 | *left = 0; | ||
432 | if (right) | ||
433 | *right = 0; | ||
434 | } | ||
435 | |||
436 | unsigned long pcm_rec_status(void) | ||
437 | { | ||
438 | return 0; | ||
439 | } | ||
440 | |||
441 | #endif /* HAVE_RECORDING */ | ||
442 | |||
289 | int pcm_init(void) | 443 | int pcm_init(void) |
290 | { | 444 | { |
291 | SDL_AudioSpec wanted_spec; | 445 | SDL_AudioSpec wanted_spec; |
292 | FILE *debug = NULL; | 446 | udata.debug = NULL; |
293 | 447 | ||
294 | if (debug_audio) { | 448 | if (debug_audio) { |
295 | debug = fopen("audiodebug.raw", "wb"); | 449 | udata.debug = fopen("audiodebug.raw", "wb"); |
296 | } | 450 | } |
297 | 451 | ||
298 | /* Set 16-bit stereo audio at 44Khz */ | 452 | /* Set 16-bit stereo audio at 44Khz */ |
@@ -300,8 +454,10 @@ int pcm_init(void) | |||
300 | wanted_spec.format = AUDIO_S16SYS; | 454 | wanted_spec.format = AUDIO_S16SYS; |
301 | wanted_spec.channels = 2; | 455 | wanted_spec.channels = 2; |
302 | wanted_spec.samples = 2048; | 456 | wanted_spec.samples = 2048; |
303 | wanted_spec.callback = sdl_audio_callback; | 457 | wanted_spec.callback = |
304 | wanted_spec.userdata = debug; | 458 | (void (SDLCALL *)(void *userdata, |
459 | Uint8 *stream, int len))sdl_audio_callback; | ||
460 | wanted_spec.userdata = &udata; | ||
305 | 461 | ||
306 | /* Open the audio device and start playing sound! */ | 462 | /* Open the audio device and start playing sound! */ |
307 | if(SDL_OpenAudio(&wanted_spec, &obtained) < 0) { | 463 | if(SDL_OpenAudio(&wanted_spec, &obtained) < 0) { |
@@ -309,7 +465,29 @@ int pcm_init(void) | |||
309 | return -1; | 465 | return -1; |
310 | } | 466 | } |
311 | 467 | ||
312 | sdl_dma_stop(); | 468 | switch (obtained.format) |
469 | { | ||
470 | case AUDIO_U8: | ||
471 | case AUDIO_S8: | ||
472 | pcm_channel_bytes = 1; | ||
473 | break; | ||
474 | case AUDIO_U16LSB: | ||
475 | case AUDIO_S16LSB: | ||
476 | case AUDIO_U16MSB: | ||
477 | case AUDIO_S16MSB: | ||
478 | pcm_channel_bytes = 2; | ||
479 | break; | ||
480 | default: | ||
481 | fprintf(stderr, "Unknown sample format obtained: %u\n", | ||
482 | (unsigned)obtained.format); | ||
483 | return -1; | ||
484 | } | ||
485 | |||
486 | pcm_sample_bytes = obtained.channels * pcm_channel_bytes; | ||
487 | |||
488 | pcm_apply_settings_nolock(); | ||
489 | |||
490 | sdl_dma_stop_nolock(); | ||
313 | 491 | ||
314 | return 0; | 492 | return 0; |
315 | } | 493 | } |
@@ -317,5 +495,3 @@ int pcm_init(void) | |||
317 | void pcm_postinit(void) | 495 | void pcm_postinit(void) |
318 | { | 496 | { |
319 | } | 497 | } |
320 | |||
321 | |||