1 /***************************************************************************
2                           sndsrv.c  -  description
3                              -------------------
4     begin                : Thu Apr 20 2000
5     copyright            : (C) 2000 by Michael Speck
6     email                : kulkanie@gmx.net
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #include "sndsrv.h"
19 
20 #ifdef SOUND
21 
22 #include <stdlib.h>
23 #include <string.h>
24 #include <SDL_video.h>
25 
26 extern char *src_dir;
27 
28 // Wave //
29 
Wave_Load(char * fname)30 Wave* Wave_Load(char *fname)
31 {
32     Wave *w;
33     char path[strlen(src_dir) + strlen(fname) + 1];
34     sprintf(path,"%s%s",src_dir,fname);
35     w = (Wave*)malloc(sizeof(Wave));
36     if (w == 0) {
37         fprintf(stderr, "ERR: wave_load: not enough memory\n");
38         exit(1);
39     }
40     w->buf = 0;
41     w->len = 0;
42     if (SDL_LoadWAV(path, &w->spec, &w->buf, &w->len) == 0) {
43         fprintf(stderr, "ERR: wave_load: %s\n", SDL_GetError());
44         exit(1);
45     }
46     w->spec.callback = 0;
47     w->spec.userdata = 0;
48     return w;
49 }
50 
Wave_Free(Wave * w)51 void Wave_Free(Wave *w)
52 {
53     if (w->buf) SDL_FreeWAV(w->buf);
54     free(w);
55 }
56 
Wave_Format(Wave * w,SDL_AudioSpec dest)57 void Wave_Format(Wave *w, SDL_AudioSpec dest)
58 {
59     SDL_AudioCVT cvt;
60 
61     printf("dst:\n");
62     printf("ch: %i | smpls: %i | fmt: %i\n", dest.channels, dest.format, dest.samples);
63     printf("src:\n");
64     printf("ch: %i | smpls: %i | fmt: %i\n", w->spec.channels, w->spec.format, w->spec.samples);
65 
66     if (dest.channels != w->spec.channels || dest.format != w->spec.format || dest.samples != w->spec.samples) {
67         SDL_BuildAudioCVT(&cvt, w->spec.format, w->spec.channels, w->spec.samples, dest.format, dest.channels, dest.samples);
68         cvt.len = w->len;
69         cvt.buf = (char*)malloc(cvt.len * cvt.len_mult);
70         memcpy(cvt.buf, w->buf, w->len);
71         SDL_ConvertAudio(&cvt);
72         SDL_FreeWAV(w->buf);
73         w->buf = cvt.buf;
74     }
75 }
76 
77 // Soundserver //
78 
79 SndSrv sndsrv;
80 
SndSrv_Init(int t)81 void SndSrv_Init(int t)
82 {
83     int i;
84     sndsrv.tracks = (Track*)malloc(sizeof(Track) * t);
85     sndsrv.track_num = t;
86     for (i = 0; i < t; i++)
87         sndsrv.tracks[i].wave = 0;
88     SndSrv_SetVolume(8);
89     sndsrv.playing = 0;
90     sndsrv.ok = 1;
91 }
92 
SndSrv_Quit()93 void SndSrv_Quit()
94 {
95     free(sndsrv.tracks);
96 }
97 
SndSrv_Open(SDL_AudioSpec wanted)98 int SndSrv_Open(SDL_AudioSpec wanted) {
99     sndsrv.spec.callback = SndSrv_Callback;
100     sndsrv.spec.userdata = 0;
101     if (SDL_OpenAudio(&sndsrv.spec, 0) < 0) {
102     	fprintf(stderr, "ERR: sndsrv_open: %s\n", SDL_GetError());
103     	sndsrv.ok = 0;
104     	return 1;
105     }
106     SndSrv_Pause(0);
107     sndsrv.playing = 0;
108     sndsrv.sleeping = 0;
109     return 0;
110 }
111 
SndSrv_Close()112 void SndSrv_Close()
113 {
114     if (sndsrv.ok)
115         SDL_CloseAudio();
116 }
117 
SndSrv_Pause(int p)118 void SndSrv_Pause(int p)
119 {
120     if (!sndsrv.ok) return;
121     SDL_PauseAudio(p);
122     if (p) sndsrv.playing = 0;
123 }
124 
SndSrv_Play(Wave * w,int p)125 void SndSrv_Play(Wave *w, int p)
126 {
127     int j;
128     if (sndsrv.sleeping || !sndsrv.ok) return;
129     //use free track if possible
130     for (j = 0; j < sndsrv.track_num; j++)
131         if (sndsrv.tracks[j].wave == 0) {
132             //empty
133             sndsrv.tracks[j].wave = w;
134             sndsrv.tracks[j].audio_pos = w->buf;
135             sndsrv.tracks[j].len = w->len;
136             sndsrv.playing++;
137             SndSrv_Pause(0);
138             return;
139         }
140     for (j = 0; j < sndsrv.track_num; j++)
141         if (sndsrv.tracks[j].priority <= p) {
142            	//lower priority found
143             sndsrv.tracks[j].wave = w;
144             sndsrv.tracks[j].audio_pos = w->buf;
145             sndsrv.tracks[j].len = w->len;
146             sndsrv.playing++;
147             SndSrv_Pause(0);
148             return;
149         }
150     return; //cannot play sound, no track available
151 }
152 
SndSrv_SetVolume(char v)153 void SndSrv_SetVolume(char v)
154 {
155     sndsrv.volume = v < 0 ? 0 : v > 8 ? 8 : v;
156     if (sndsrv.volume) sndsrv.volume = sndsrv.volume * 16 - 1;
157 }
158 
SndSrv_SetActive(int a)159 void SndSrv_SetActive(int a)
160 {
161     sndsrv.sleeping = !a;
162 }
163 
SndSrv_Callback(void * udata,unsigned char * stream,int str_len)164 void SndSrv_Callback(void *udata, unsigned char *stream, int str_len)
165 {
166     int i, len;
167     Track *track;
168     if (sndsrv.sleeping || !sndsrv.ok) return;
169     for (i = 0; i < sndsrv.track_num; i++) {
170        	track = &sndsrv.tracks[i];
171         if (track->wave == 0) continue;
172         len = str_len < track->len ? str_len : track->len;
173         SDL_MixAudio(stream, track->audio_pos, len, sndsrv.volume);
174         track->len -= len;
175         track->audio_pos += len;
176         if (track->len == 0) {
177             track->wave = 0;
178             sndsrv.playing--;
179         }
180         if (!sndsrv.playing) SndSrv_Pause(1);
181     }
182 }
183 
184 #endif
185 
186