diff options
Diffstat (limited to 'uisimulator/sdl/sound.c')
-rw-r--r-- | uisimulator/sdl/sound.c | 216 |
1 files changed, 149 insertions, 67 deletions
diff --git a/uisimulator/sdl/sound.c b/uisimulator/sdl/sound.c index 66df6961b2..4b8427ca90 100644 --- a/uisimulator/sdl/sound.c +++ b/uisimulator/sdl/sound.c | |||
@@ -21,88 +21,170 @@ | |||
21 | 21 | ||
22 | #ifdef ROCKBOX_HAS_SIMSOUND /* play sound in sim enabled */ | 22 | #ifdef ROCKBOX_HAS_SIMSOUND /* play sound in sim enabled */ |
23 | 23 | ||
24 | #include <memory.h> | ||
25 | #include <stdlib.h> | 24 | #include <stdlib.h> |
26 | #include "uisdl.h" | 25 | #include <stdbool.h> |
26 | #include <memory.h> | ||
27 | #include "sound.h" | 27 | #include "sound.h" |
28 | #include "SDL.h" | ||
29 | |||
30 | static bool pcm_playing; | ||
31 | static bool pcm_paused; | ||
28 | 32 | ||
29 | static int audio_len; | 33 | static Uint8* pcm_data; |
30 | static char *audio_pos; | 34 | static int pcm_data_size; |
31 | SDL_sem* sem; | ||
32 | 35 | ||
33 | void mixaudio(void *udata, Uint8 *stream, int len) | 36 | static void sdl_dma_start(const void *addr, size_t size) |
34 | { | 37 | { |
35 | (void)udata; | 38 | pcm_playing = true; |
36 | 39 | ||
37 | /* Only play if we have data left */ | 40 | pcm_data = (Uint8 *) addr; |
38 | if ( audio_len == 0 ) | 41 | pcm_data_size = size; |
39 | return; | 42 | |
40 | 43 | SDL_PauseAudio(0); | |
41 | len = (len > audio_len) ? audio_len : len; | ||
42 | memcpy(stream, audio_pos, len); | ||
43 | audio_pos += len; | ||
44 | audio_len -= len; | ||
45 | |||
46 | if(audio_len == 0) { | ||
47 | if(SDL_SemPost(sem)) | ||
48 | fprintf(stderr,"Couldn't post: %s",SDL_GetError()); | ||
49 | |||
50 | } | ||
51 | } | 44 | } |
52 | 45 | ||
53 | int sim_sound_init(void) | 46 | static void sdl_dma_stop() |
54 | { | 47 | { |
55 | SDL_AudioSpec fmt; | 48 | pcm_playing = false; |
56 | 49 | ||
57 | /* Set 16-bit stereo audio at 44Khz */ | 50 | SDL_PauseAudio(1); |
58 | fmt.freq = 44100; | 51 | |
59 | fmt.format = AUDIO_S16SYS; | 52 | pcm_paused = false; |
60 | fmt.channels = 2; | ||
61 | fmt.samples = 512; /* A good value for games */ | ||
62 | fmt.callback = mixaudio; | ||
63 | fmt.userdata = NULL; | ||
64 | |||
65 | sem = SDL_CreateSemaphore(0); | ||
66 | |||
67 | /* Open the audio device and start playing sound! */ | ||
68 | if(SDL_OpenAudio(&fmt, NULL) < 0) { | ||
69 | fprintf(stderr, "Unable to open audio: %s\n", SDL_GetError()); | ||
70 | return -1; | ||
71 | } | ||
72 | |||
73 | SDL_PauseAudio(0); | ||
74 | return 0; | ||
75 | } | 53 | } |
76 | 54 | ||
77 | int sound_playback_thread(void *p) | 55 | static void (*callback_for_more)(unsigned char**, size_t*) = NULL; |
56 | void pcm_play_data(void (*get_more)(unsigned char** start, size_t* size), | ||
57 | unsigned char* start, size_t size) | ||
78 | { | 58 | { |
79 | int sndret = sim_sound_init(); | 59 | callback_for_more = get_more; |
80 | unsigned char *buf; | 60 | |
81 | long size; | 61 | if (!(start && size)) { |
62 | if (get_more) | ||
63 | get_more(&start, &size); | ||
64 | else | ||
65 | return; | ||
66 | } | ||
67 | |||
68 | if (start && size) { | ||
69 | sdl_dma_start(start, size); | ||
70 | } | ||
71 | } | ||
82 | 72 | ||
83 | (void)p; | 73 | size_t pcm_get_bytes_waiting(void) |
74 | { | ||
75 | return pcm_data_size; | ||
76 | } | ||
84 | 77 | ||
85 | while(sndret) | 78 | void pcm_mute(bool mute) |
86 | SDL_Delay(100000); /* wait forever, can't play sound! */ | 79 | { |
80 | (void) mute; | ||
81 | } | ||
82 | |||
83 | void pcm_play_stop(void) | ||
84 | { | ||
85 | if (pcm_playing) { | ||
86 | sdl_dma_stop(); | ||
87 | } | ||
88 | } | ||
89 | |||
90 | void pcm_play_pause(bool play) | ||
91 | { | ||
92 | int next_size; | ||
93 | Uint8 *next_start; | ||
94 | |||
95 | if (!pcm_playing) { | ||
96 | return; | ||
97 | } | ||
98 | |||
99 | if(pcm_paused && play) { | ||
100 | if (pcm_get_bytes_waiting()) { | ||
101 | printf("unpause\n"); | ||
102 | |||
103 | SDL_PauseAudio(0); | ||
104 | } else { | ||
105 | printf("unpause, no data waiting\n"); | ||
106 | |||
107 | void (*get_more)(unsigned char**, size_t*) = callback_for_more; | ||
108 | |||
109 | if (get_more) { | ||
110 | get_more(&next_start, &next_size); | ||
111 | } | ||
112 | |||
113 | if (next_start && next_size) { | ||
114 | sdl_dma_start(next_start, next_size); | ||
115 | } else { | ||
116 | sdl_dma_stop(); | ||
117 | printf("unpause attempted, no data\n"); | ||
118 | } | ||
119 | } | ||
120 | } else if(!pcm_paused && !play) { | ||
121 | printf("pause\n"); | ||
122 | |||
123 | SDL_PauseAudio(1); | ||
124 | } | ||
125 | |||
126 | pcm_paused = !play; | ||
127 | } | ||
128 | |||
129 | bool pcm_is_paused(void) | ||
130 | { | ||
131 | return pcm_paused; | ||
132 | } | ||
133 | |||
134 | bool pcm_is_playing(void) | ||
135 | { | ||
136 | return pcm_playing; | ||
137 | } | ||
138 | |||
139 | void sdl_audio_callback(void *udata, Uint8 *stream, int len) | ||
140 | { | ||
141 | int datalen; | ||
142 | |||
143 | (void) udata; | ||
144 | |||
145 | if (pcm_data_size == 0) { | ||
146 | return; | ||
147 | } | ||
148 | |||
149 | datalen = (len > pcm_data_size) ? pcm_data_size : len; | ||
150 | |||
151 | memcpy(stream, pcm_data, datalen); | ||
152 | |||
153 | pcm_data_size -= datalen; | ||
154 | pcm_data += datalen; | ||
155 | |||
156 | if (pcm_data_size == 0) { | ||
157 | void (*get_more)(unsigned char**, size_t*) = callback_for_more; | ||
158 | if (get_more) { | ||
159 | get_more(&pcm_data, &pcm_data_size); | ||
160 | } else { | ||
161 | pcm_data_size = 0; | ||
162 | pcm_data = NULL; | ||
163 | } | ||
164 | } | ||
165 | } | ||
166 | |||
167 | int pcm_init(void) | ||
168 | { | ||
169 | SDL_AudioSpec fmt; | ||
170 | |||
171 | /* Set 16-bit stereo audio at 44Khz */ | ||
172 | fmt.freq = 44100; | ||
173 | fmt.format = AUDIO_S16SYS; | ||
174 | fmt.channels = 2; | ||
175 | fmt.samples = 512; | ||
176 | fmt.callback = sdl_audio_callback; | ||
177 | fmt.userdata = NULL; | ||
178 | |||
179 | /* Open the audio device and start playing sound! */ | ||
180 | if(SDL_OpenAudio(&fmt, NULL) < 0) { | ||
181 | fprintf(stderr, "Unable to open audio: %s\n", SDL_GetError()); | ||
182 | return -1; | ||
183 | } | ||
87 | 184 | ||
88 | do { | 185 | sdl_dma_stop(); |
89 | while(!sound_get_pcm) | ||
90 | /* TODO: fix a fine thread-synch mechanism here */ | ||
91 | SDL_Delay(100); | ||
92 | do { | ||
93 | sound_get_pcm(&buf, &size); | ||
94 | if(!size) { | ||
95 | sound_get_pcm = NULL; | ||
96 | break; | ||
97 | } | ||
98 | audio_pos = buf; // TODO: is this safe? | ||
99 | audio_len = size; | ||
100 | |||
101 | if(SDL_SemWait(sem)) | ||
102 | fprintf(stderr,"Couldn't wait: %s",SDL_GetError()); | ||
103 | } while(size); | ||
104 | } while(1); | ||
105 | 186 | ||
187 | return 0; | ||
106 | } | 188 | } |
107 | 189 | ||
108 | #endif /* ROCKBOX_HAS_SIMSOUND */ | 190 | #endif /* ROCKBOX_HAS_SIMSOUND */ |