summaryrefslogtreecommitdiff
path: root/uisimulator/sdl/sound.c
diff options
context:
space:
mode:
Diffstat (limited to 'uisimulator/sdl/sound.c')
-rw-r--r--uisimulator/sdl/sound.c216
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
30static bool pcm_playing;
31static bool pcm_paused;
28 32
29static int audio_len; 33static Uint8* pcm_data;
30static char *audio_pos; 34static int pcm_data_size;
31SDL_sem* sem;
32 35
33void mixaudio(void *udata, Uint8 *stream, int len) 36static 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
53int sim_sound_init(void) 46static 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
77int sound_playback_thread(void *p) 55static void (*callback_for_more)(unsigned char**, size_t*) = NULL;
56void 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; 73size_t pcm_get_bytes_waiting(void)
74{
75 return pcm_data_size;
76}
84 77
85 while(sndret) 78void pcm_mute(bool mute)
86 SDL_Delay(100000); /* wait forever, can't play sound! */ 79{
80 (void) mute;
81}
82
83void pcm_play_stop(void)
84{
85 if (pcm_playing) {
86 sdl_dma_stop();
87 }
88}
89
90void 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
129bool pcm_is_paused(void)
130{
131 return pcm_paused;
132}
133
134bool pcm_is_playing(void)
135{
136 return pcm_playing;
137}
138
139void 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
167int 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 */