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 <SDL/SDL.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include "dynlist.h"
22 #include "sndsrv.h"
23
24 #ifdef SOUND
25
26 // Wave //
27
28 /*
29 load a wave from file
30 */
Wv_Ld(char * fname)31 Wv* Wv_Ld(char *fname)
32 {
33 Wv *w;
34 char path[strlen(SRC_DIR) + strlen(fname) + 1];
35 sprintf(path,"%s%s",SRC_DIR,fname);
36 w = (Wv*)malloc(sizeof(Wv));
37 if (w == 0) {
38 fprintf(stderr, "ERR: wv_load: not enough memory\n");
39 exit(1);
40 }
41 w->buf = 0;
42 w->len = 0;
43 if (SDL_LoadWAV(path, &w->spc, &w->buf, &w->len) == 0) {
44 fprintf(stderr, "ERR: wv_load: %s\n", SDL_GetError());
45 exit(1);
46 }
47 w->spc.callback = 0;
48 w->spc.userdata = 0;
49 return w;
50 }
51
52 /*
53 free wave
54 */
Wv_Fr(Wv * w)55 void Wv_Fr(Wv *w)
56 {
57 if (w->buf) SDL_FreeWAV(w->buf);
58 free(w);
59 }
60
61 /*
62 format a wave
63 IS NOT WORKING YET!!!
64 */
65
Wv_Fmt(Wv * w,SDL_AudioSpec dest)66 void Wv_Fmt(Wv *w, SDL_AudioSpec dest)
67 {
68 SDL_AudioCVT cvt;
69
70 printf("dst:\n");
71 printf("ch: %i | smpls: %i | fmt: %i\n", dest.channels, dest.format, dest.samples);
72 printf("src:\n");
73 printf("ch: %i | smpls: %i | fmt: %i\n", w->spc.channels, w->spc.format, w->spc.samples);
74
75 if (dest.channels != w->spc.channels || dest.format != w->spc.format || dest.samples != w->spc.samples) {
76 SDL_BuildAudioCVT(&cvt, w->spc.format, w->spc.channels, w->spc.samples, dest.format, dest.channels, dest.samples);
77 cvt.len = w->len;
78 cvt.buf = (char*)malloc(cvt.len * cvt.len_mult);
79 memcpy(cvt.buf, w->buf, w->len);
80 SDL_ConvertAudio(&cvt);
81 SDL_FreeWAV(w->buf);
82 w->buf = cvt.buf;
83 }
84 }
85
86 // Soundserver //
87
88 SSrv ssrv;
89
90 /*
91 initialize soundserver with this format, frequency, channels and samples
92 lmt is the limit of tracks mixed at one time
93 */
SSrv_Ini(int fmt,int frq,int ch,int smpls,int lmt)94 int SSrv_Ini(int fmt, int frq, int ch, int smpls, int lmt)
95 {
96 ssrv.spc.format = fmt;
97 ssrv.spc.freq = frq;
98 ssrv.spc.channels = ch;
99 ssrv.spc.samples = smpls;
100 ssrv.spc.callback = SSrv_CB;
101 ssrv.spc.userdata = 0;
102 ssrv.lmt = lmt;
103
104 dl_init(&ssrv.trks, AUTO_DELETE | NO_CALLBACK, 0 );
105
106 SSrv_StV(8);
107
108 ssrv.ok = 1;
109 if (SDL_OpenAudio(&ssrv.spc, 0) < 0) {
110 fprintf(stderr, "ERR: ssrv_open: %s\n", SDL_GetError());
111 ssrv.ok = 0;
112 return 1;
113 }
114 SSrv_Ps(0);
115
116 ssrv.ply = 0;
117 ssrv.slp = 0;
118 return 0;
119 }
120
121 /*
122 close soundserver
123 */
SSrv_Trm()124 void SSrv_Trm()
125 {
126 if (ssrv.ok)
127 SDL_CloseAudio();
128 dl_clear(&ssrv.trks);
129 }
130
131 /*
132 pause soundserver
133 */
SSrv_Ps(int p)134 void SSrv_Ps(int p)
135 {
136 if (ssrv.ok)
137 SDL_PauseAudio(p);
138 if (p) ssrv.ply = 0;
139 }
140
141 /*
142 play a wave
143 creates or overwrites a track
144 */
SSrv_Ply(Wv * w,int p)145 void SSrv_Ply(Wv *w, int p)
146 {
147 DL_Entry *e = ssrv.trks.head.next;
148 Trck *t;
149 if (!ssrv.ok || ssrv.slp) return;
150
151 if (ssrv.trks.coun < ssrv.lmt) {
152 // can create a new track //
153 t = malloc(sizeof(Trck));
154 t->wv = w;
155 t->a_pos = w->buf;
156 t->len = w->len;
157 t->pri = p;
158 dl_add(&ssrv.trks, t);
159 ssrv.ply++;
160 SSrv_Ps(0);
161 return;
162 }
163 while (e != &ssrv.trks.tail) {
164 // overwrite a track //
165 t = (Trck*)e->data;
166 if (t->pri < p) {
167 t->wv = w;
168 t->a_pos = w->buf;
169 t->len = w->len;
170 t->pri = p;
171 ssrv.ply++;
172 SSrv_Ps(0);
173 return;
174 }
175 e = e->next;
176 }
177 return; //cannot play sound, no track available
178 }
179
180 /*
181 set volume
182 */
SSrv_StV(char v)183 void SSrv_StV(char v)
184 {
185 ssrv.vol = v < 0 ? 0 : v > 8 ? 8 : v;
186 if (ssrv.vol) ssrv.vol = ssrv.vol * 16 - 1;
187 }
188
189 /*
190 activate / deavctivate soundserver
191 */
SSrv_StA(int a)192 void SSrv_StA(int a)
193 {
194 ssrv.slp = !a;
195 }
196
197 /*
198 callback which mixes tracks and deletes finished tracks
199 */
SSrv_CB(void * udata,unsigned char * stream,int str_len)200 void SSrv_CB(void *udata, unsigned char *stream, int str_len)
201 {
202 int len;
203 Trck *t;
204 DL_Entry *e = ssrv.trks.head.next, *n;
205 if (!ssrv.ok || ssrv.slp) return;
206 while (e != &ssrv.trks.tail) {
207 n = e->next;
208 t = (Trck*)e->data;
209 len = str_len < t->len ? str_len : t->len;
210 SDL_MixAudio(stream, t->a_pos, len, ssrv.vol);
211 t->len -= len;
212 t->a_pos += len;
213 if (t->len == 0) {
214 dl_delete_entry(&ssrv.trks, e);
215 ssrv.ply--;
216 }
217 e = n;
218 }
219 if (!ssrv.ply) SSrv_Ps(1);
220 }
221
222 #endif
223