2
* OpenTyrian: A modern cross-platform port of Tyrian
3
* Copyright (C) 2007-2009 The OpenTyrian Development Team
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public License
7
* as published by the Free Software Foundation; either version 2
8
* of the License, or (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26
float music_volume = 0, sample_volume = 0;
28
bool music_stopped = true;
29
unsigned int song_playing = 0;
31
bool audio_disabled = false, music_disabled = false, samples_disabled = false;
33
/* SYN: These shouldn't be used outside this file. Hands off! */
34
FILE *music_file = NULL;
36
Uint16 song_count = 0;
39
SAMPLE_TYPE *channel_buffer[SFX_CHANNELS] = { NULL };
40
SAMPLE_TYPE *channel_pos[SFX_CHANNELS] = { NULL };
41
Uint32 channel_len[SFX_CHANNELS] = { 0 };
42
Uint8 channel_vol[SFX_CHANNELS];
44
int sound_init_state = false;
45
int freq = 11025 * OUTPUT_QUALITY;
47
static SDL_AudioCVT audio_cvt; // used for format conversion
49
void audio_cb( void *userdata, unsigned char *feedme, int howmuch );
51
void load_song( unsigned int song_num );
53
bool init_audio( void )
58
SDL_AudioSpec ask, got;
61
ask.format = (BYTES_PER_SAMPLE == 2) ? AUDIO_S16SYS : AUDIO_S8;
64
ask.callback = audio_cb;
66
printf("\trequested %d Hz, %d channels, %d samples\n", ask.freq, ask.channels, ask.samples);
68
if (SDL_OpenAudio(&ask, &got) == -1)
70
fprintf(stderr, "error: failed to initialize SDL audio: %s\n", SDL_GetError());
71
audio_disabled = true;
75
printf("\tobtained %d Hz, %d channels, %d samples\n", got.freq, got.channels, got.samples);
77
SDL_BuildAudioCVT(&audio_cvt, ask.format, ask.channels, ask.freq, got.format, got.channels, got.freq);
81
SDL_PauseAudio(0); // unpause
86
void audio_cb( void *user_data, unsigned char *sdl_buffer, int howmuch )
90
// prepare for conversion
91
howmuch /= audio_cvt.len_mult;
92
audio_cvt.buf = sdl_buffer;
93
audio_cvt.len = howmuch;
97
SAMPLE_TYPE *feedme = (SAMPLE_TYPE *)sdl_buffer;
99
if (!music_disabled && !music_stopped)
101
/* SYN: Simulate the fm synth chip */
102
SAMPLE_TYPE *music_pos = feedme;
103
long remaining = howmuch / BYTES_PER_SAMPLE;
104
while (remaining > 0)
109
lds_update(); /* SYN: Do I need to use the return value for anything here? */
111
/* SYN: Okay, about the calculations below. I still don't 100% get what's going on, but...
112
- freq is samples/time as output by SDL.
113
- REFRESH is how often the play proc would have been called in Tyrian. Standard speed is
114
70Hz, which is the default value of 70.0f
115
- ct represents the margin between play time (representing # of samples) and tick speed of
116
the songs (70Hz by default). It keeps track of which one is ahead, because they don't
119
/* set i to smaller of data requested by SDL and a value calculated from the refresh rate */
120
long i = (long)((ct / REFRESH) + 4) & ~3;
121
i = (i > remaining) ? remaining : i; /* i should now equal the number of samples we get */
122
opl_update((SAMPLE_TYPE *)music_pos, i);
125
ct -= (long)(REFRESH * i);
128
/* Reduce the music volume. */
129
int qu = howmuch / BYTES_PER_SAMPLE;
130
for (int smp = 0; smp < qu; smp++)
132
feedme[smp] *= music_volume;
136
if (!samples_disabled)
138
/* SYN: Mix sound channels and shove into audio buffer */
139
for (int ch = 0; ch < SFX_CHANNELS; ch++)
141
float volume = sample_volume * (channel_vol[ch] / (float)SFX_CHANNELS);
143
/* SYN: Don't copy more data than is in the channel! */
144
unsigned int qu = ((unsigned)howmuch > channel_len[ch] ? channel_len[ch] : (unsigned)howmuch) / BYTES_PER_SAMPLE;
145
for (unsigned int smp = 0; smp < qu; smp++)
147
#if (BYTES_PER_SAMPLE == 2)
148
Sint32 clip = (Sint32)feedme[smp] + (Sint32)(channel_pos[ch][smp] * volume);
149
feedme[smp] = (clip > 0x7fff) ? 0x7fff : (clip <= -0x8000) ? -0x8000 : (Sint16)clip;
150
#else /* BYTES_PER_SAMPLE */
151
Sint16 clip = (Sint16)feedme[smp] + (Sint16)(channel_pos[ch][smp] * volume);
152
feedme[smp] = (clip > 0x7f) ? 0x7f : (clip <= -0x80) ? -0x80 : (Sint8)clip;
153
#endif /* BYTES_PER_SAMPLE */
156
channel_pos[ch] += qu;
157
channel_len[ch] -= qu * BYTES_PER_SAMPLE;
159
/* SYN: If we've emptied a channel buffer, let's free the memory and clear the channel. */
160
if (channel_len[ch] == 0)
162
free(channel_buffer[ch]);
163
channel_buffer[ch] = channel_pos[ch] = NULL;
169
SDL_ConvertAudio(&audio_cvt);
172
void deinit_audio( void )
177
SDL_PauseAudio(1); // pause
181
for (unsigned int i = 0; i < SFX_CHANNELS; i++)
183
free(channel_buffer[i]);
184
channel_buffer[i] = channel_pos[i] = NULL;
192
void load_music( void )
194
if (music_file == NULL)
196
music_file = dir_fopen_die(data_dir(), "music.mus", "rb");
198
efread(&song_count, sizeof(song_count), 1, music_file);
200
song_offset = malloc((song_count + 1) * sizeof(*song_offset));
202
efread(song_offset, 4, song_count, music_file);
203
song_offset[song_count] = ftell_eof(music_file);
207
void load_song( unsigned int song_num )
214
if (song_num < song_count)
216
unsigned int song_size = song_offset[song_num + 1] - song_offset[song_num];
217
lds_load(music_file, song_offset[song_num], song_size);
221
fprintf(stderr, "warning: failed to load song %d\n", song_num + 1);
227
void play_song( unsigned int song_num )
229
if (song_num != song_playing)
232
song_playing = song_num;
235
music_stopped = false;
238
void restart_song( void )
240
unsigned int temp = song_playing;
245
void stop_song( void )
247
music_stopped = true;
250
void fade_song( void )
252
/* STUB: we have no implementation of this to port */
255
void set_volume( unsigned int music, unsigned int sample )
257
music_volume = music * (1.5f / 255.0f);
258
sample_volume = sample * (1.0f / 255.0f);
261
void JE_multiSamplePlay(JE_byte *buffer, JE_word size, JE_byte chan, JE_byte vol)
263
if (audio_disabled || samples_disabled)
268
free(channel_buffer[chan]);
270
channel_len[chan] = size * BYTES_PER_SAMPLE * SAMPLE_SCALING;
271
channel_buffer[chan] = malloc(channel_len[chan]);
272
channel_pos[chan] = channel_buffer[chan];
273
channel_vol[chan] = vol + 1;
275
for (int i = 0; i < size; i++)
277
for (int ex = 0; ex < SAMPLE_SCALING; ex++)
279
#if (BYTES_PER_SAMPLE == 2)
280
channel_buffer[chan][(i * SAMPLE_SCALING) + ex] = (Sint8)buffer[i] << 8;
281
#else /* BYTES_PER_SAMPLE */
282
channel_buffer[chan][(i * SAMPLE_SCALING) + ex] = (Sint8)buffer[i];
283
#endif /* BYTES_PER_SAMPLE */