-
Notifications
You must be signed in to change notification settings - Fork 0
/
sdl_sound.c
171 lines (142 loc) · 5.93 KB
/
sdl_sound.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/* sz81 Copyright (C) 2007-2011 Thunor <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef OSS_SOUND_SUPPORT
/* Includes */
#include "sdl_engine.h"
/* Defines */
/* Variables */
/* Function prototypes */
/***************************************************************************
* Sound Initialise *
***************************************************************************/
/* On exit: returns FALSE on success else
* returns TRUE on error */
int sdl_sound_init(int freq, int *stereo, int *sixteenbit) {
SDL_AudioSpec desired, obtained;
sdl_sound.buffer_start = sdl_sound.buffer_end = 0;
desired.freq = freq;
#if defined(PLATFORM_GP2X)
desired.format = AUDIO_U16;
#if defined(TOOLCHAIN_OPEN2X) || defined(TOOLCHAIN_OPENWIZ)
desired.samples = 256;
#else
desired.samples = 1024; /* This might be better at 512 */
#endif
#else
desired.format = AUDIO_U8; /* z81's default */
desired.samples = 1024; /* This might be better at 512 */
#endif
desired.channels = *stereo + 1;
desired.callback = sdl_sound_callback;
desired.userdata = NULL;
/* Open the audio device */
if (SDL_OpenAudio(&desired, &obtained) < 0 ) {
fprintf(stderr, "%s: Couldn't open audio: %s\n", __func__, SDL_GetError());
return TRUE;
}
sdl_sound.state = TRUE;
*stereo = obtained.channels - 1;
*sixteenbit = (obtained.format & 0xff) / 16;
/* Start playing */
SDL_PauseAudio(0);
#ifdef SDL_DEBUG_SOUND
printf("%s:\n", __func__);
printf(" desired.freq=%i\n", desired.freq);
printf(" desired.format=");
if (desired.format == 0x0008) printf("AUDIO_U8\n");
if (desired.format == 0x8008) printf("AUDIO_S8\n");
if (desired.format == 0x0010) printf("AUDIO_U16LSB/AUDIO_U16\n");
if (desired.format == 0x8010) printf("AUDIO_S16LSB/AUDIO_S16\n");
if (desired.format == 0x1010) printf("AUDIO_U16MSB\n");
if (desired.format == 0x9010) printf("AUDIO_S16MSB\n");
printf(" desired.channels=%i\n", desired.channels);
printf(" desired.samples=%i\n", desired.samples);
printf(" obtained.freq=%i\n", obtained.freq);
printf(" obtained.format=");
if (obtained.format == 0x0008) printf("AUDIO_U8\n");
if (obtained.format == 0x8008) printf("AUDIO_S8\n");
if (obtained.format == 0x0010) printf("AUDIO_U16LSB/AUDIO_U16\n");
if (obtained.format == 0x8010) printf("AUDIO_S16LSB/AUDIO_S16\n");
if (obtained.format == 0x1010) printf("AUDIO_U16MSB\n");
if (obtained.format == 0x9010) printf("AUDIO_S16MSB\n");
printf(" obtained.channels=%i\n", obtained.channels);
printf(" obtained.samples=%i\n", obtained.samples);
#endif
return FALSE;
}
/***************************************************************************
* Sound Callback *
***************************************************************************/
/* When the audio device is ready for more data it calls this function which
* could be running in another thread. The data will have been previously
* stored in our linear sound buffer via the sound frame function below */
void sdl_sound_callback(void *userdata, Uint8 *stream, int len) {
#if defined(SDL_DEBUG_SOUND) || defined(SDL_DEBUG_TIMING)
static Uint32 lasttime = 0;
static int Hz = 0;
Hz++;
if (SDL_GetTicks() - lasttime >= 1000) {
printf("%s=%iHz", __func__, Hz);
printf(" stream len=%i\n", len);
lasttime = SDL_GetTicks();
Hz = 0;
}
#endif
/* Generate white noise for testing
while (len-- > 0) {
*(stream++) = (rand() % 256) / 8;
} */
/* Keep writing to the stream until it's full or our linear
* buffer's end reaches its start i.e. no more sound data */
while (len--) {
if (sdl_sound.buffer_start == sdl_sound.buffer_end) break;
*(stream++) = sdl_sound.buffer[sdl_sound.buffer_start++];
if (sdl_sound.buffer_start >= SOUND_BUFFER_SIZE) sdl_sound.buffer_start = 0;
}
}
/***************************************************************************
* Sound Frame *
***************************************************************************/
/* This function receives sound data from the emulator which we store in our
* linear sound buffer. It is read later by the sound card via the above
* callback which could be running in another thread and so SDL_LockAudio and
* SDL_UnlockAudio are used to lockout the callback function to prevent it
* from interfering with what we're doing here */
void sdl_sound_frame(unsigned char *data, int len) {
static int ovfcnt = 0;
SDL_LockAudio();
while (len--) {
sdl_sound.buffer[sdl_sound.buffer_end++] = *(data++);
if (sdl_sound.buffer_end >= SOUND_BUFFER_SIZE) sdl_sound.buffer_end = 0;
if (sdl_sound.buffer_end == sdl_sound.buffer_start) {
sdl_sound.buffer_start++;
if (sdl_sound.buffer_start >= SOUND_BUFFER_SIZE) sdl_sound.buffer_start = 0;
if (ovfcnt++ < 10) fprintf(stderr, "%s: Sound buffer overflow\n", __func__);
}
}
SDL_UnlockAudio();
}
/***************************************************************************
* Sound End *
***************************************************************************/
void sdl_sound_end(void) {
if (sdl_sound.state) {
sdl_sound.state = FALSE;
SDL_CloseAudio();
}
}
#endif /* OSS_SOUND_SUPPORT */