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