16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |
17 *) |
17 *) |
18 |
18 |
19 unit uSound; |
19 unit uSound; |
20 interface |
20 interface |
21 |
21 uses SDLh, uConsts; |
22 |
|
23 {$IFDEF DARWIN} |
|
24 {$linklib openalbridge} |
|
25 {$linkframework OpenAL} |
|
26 {$linkframework Ogg} |
|
27 {$linkframework Vorbis} |
|
28 {$ELSE} |
|
29 {$IFNDEF WIN32} |
|
30 {$linklib openal} |
|
31 {$linklib ogg} |
|
32 {$linklib vorbis} |
|
33 {$linklib vorbisfile} |
|
34 {$ENDIF} |
|
35 {$ENDIF} |
|
36 |
|
37 uses uConsts; |
|
38 {$INCLUDE options.inc} |
22 {$INCLUDE options.inc} |
39 |
23 |
40 type PVoicepack = ^TVoicepack; |
24 type PVoicepack = ^TVoicepack; |
41 TVoicepack = record |
25 TVoicepack = record |
42 name: shortstring; |
26 name: shortstring; |
43 chunks: array [TSound] of LongInt; |
27 chunks: array [TSound] of PMixChunk; |
44 end; |
28 end; |
45 |
|
46 const OpenALBridge = 'libopenalbridge'; |
|
47 |
29 |
48 procedure InitSound; |
30 procedure InitSound; |
49 procedure ReleaseSound; |
31 procedure ReleaseSound; |
50 procedure SoundLoad; |
32 procedure SoundLoad; |
51 procedure PlaySound(snd: TSound; infinite: boolean; voicepack: PVoicepack); |
33 procedure PlaySound(snd: TSound; infinite: boolean; voicepack: PVoicepack); |
52 procedure PlayMusic; |
34 procedure PlayMusic; |
53 procedure PauseMusic; |
35 procedure PauseMusic; |
54 procedure ResumeMusic; |
36 procedure ResumeMusic; |
55 procedure StopSound(snd: TSound); |
37 procedure StopSound(snd: TSound); |
|
38 function ChangeVolume(voldelta: LongInt): LongInt; |
56 |
39 |
57 function ChangeVolume(voldelta: LongInt): LongInt; |
40 function AskForVoicepack(name: shortstring): Pointer; |
58 function AskForVoicepack(name: shortstring): PVoicepack; |
|
59 function soundFadeOut(snd: TSound; qt: LongInt; voicepack: PVoicepack): LongInt; |
|
60 |
|
61 |
|
62 procedure oalb_close; cdecl; external OpenALBridge; |
|
63 function oalb_init (const app: PChar; const usehardware: Byte): Byte; cdecl; external OpenALBridge; |
|
64 function oalb_loadfile (const filename: PChar): LongInt; cdecl; external OpenALBridge; |
|
65 procedure oalb_playsound (const idx: LongInt; const loop: Byte); cdecl; external OpenALBridge; |
|
66 procedure oalb_stopsound (const idx: LongInt); cdecl; external OpenALBridge; |
|
67 procedure oalb_pausesound (const idx: LongInt); cdecl; external OpenALBridge; |
|
68 procedure oalb_continuesound (const idx: LongInt); cdecl; external OpenALBridge; |
|
69 procedure oalb_setvolume (const idx: LongInt; const percentage: Byte); cdecl; external OpenALBridge; |
|
70 procedure oalb_setglobalvolume (const percentage: Byte); cdecl; external OpenALBridge; |
|
71 procedure oalb_fadein (const idx: LongInt; quantity: Integer); cdecl; external OpenALBridge; |
|
72 procedure oalb_fadeout (const idx: LongInt; quantity: Integer); cdecl; external OpenALBridge; |
|
73 |
|
74 |
41 |
75 var MusicFN: shortstring = ''; |
42 var MusicFN: shortstring = ''; |
76 |
43 |
77 implementation |
44 implementation |
78 |
|
79 uses uMisc, uConsole; |
45 uses uMisc, uConsole; |
80 |
46 |
81 const chanTPU = 12; |
47 const chanTPU = 12; |
82 var Volume: LongInt; |
48 var Volume: LongInt; |
83 lastChan: array [TSound] of LongInt; |
49 lastChan: array [TSound] of LongInt; |
84 voicepacks: array[0..cMaxTeams] of TVoicepack; |
50 voicepacks: array[0..cMaxTeams] of TVoicepack; |
85 defVoicepack: PVoicepack; |
51 defVoicepack: PVoicepack; |
86 Mus: LongInt = 0; |
52 Mus: PMixMusic = nil; |
87 |
53 |
88 function AskForVoicepack(name: shortstring): PVoicepack; |
54 function AskForVoicepack(name: shortstring): Pointer; |
89 var i: Longword; |
55 var i: Longword; |
90 begin |
56 begin |
91 i:= 0; |
57 i:= 0; |
92 while (voicepacks[i].name <> name) and (voicepacks[i].name <> '') do |
58 while (voicepacks[i].name <> name) and (voicepacks[i].name <> '') do |
93 begin |
59 begin |
100 end; |
66 end; |
101 |
67 |
102 procedure InitSound; |
68 procedure InitSound; |
103 begin |
69 begin |
104 if not isSoundEnabled then exit; |
70 if not isSoundEnabled then exit; |
105 {*sound works in ipodtouch only if LAND_WIDTH = 1024; LAND_HEIGHT = 512; |
71 WriteToConsole('Init sound...'); |
106 or if ogg are loaded in stream or if sound is loaded by demand*} |
72 isSoundEnabled:= SDL_Init(SDL_INIT_AUDIO) >= 0; |
107 WriteToConsole('Init OpenAL sound...'); |
73 if isSoundEnabled then |
108 |
74 isSoundEnabled:= Mix_OpenAudio(44100, $8010, 2, 1024) = 0; |
109 isSoundEnabled:= oalb_init(str2PChar(ParamStr(0)), Byte(isSoundHardware)) = 1; |
|
110 if isSoundEnabled then WriteLnToConsole(msgOK) |
75 if isSoundEnabled then WriteLnToConsole(msgOK) |
111 else WriteLnToConsole(msgFailed); |
76 else WriteLnToConsole(msgFailed); |
|
77 Mix_AllocateChannels(Succ(chanTPU)); |
|
78 if isMusicEnabled then Mix_VolumeMusic(50); |
112 |
79 |
113 Volume:=0; |
80 Volume:= 0; |
114 ChangeVolume(cInitVolume); |
81 ChangeVolume(cInitVolume) |
115 end; |
82 end; |
116 |
83 |
117 procedure ReleaseSound; |
84 procedure ReleaseSound; |
|
85 var i: TSound; |
|
86 t: Longword; |
118 begin |
87 begin |
119 if isMusicEnabled then oalb_fadeout(Mus, 30); |
88 for t:= 0 to cMaxTeams do |
120 oalb_close(); |
89 if voicepacks[t].name <> '' then |
|
90 for i:= Low(TSound) to High(TSound) do |
|
91 if voicepacks[t].chunks[i] <> nil then |
|
92 Mix_FreeChunk(voicepacks[t].chunks[i]); |
|
93 |
|
94 Mix_FreeMusic(Mus); |
|
95 Mix_CloseAudio |
121 end; |
96 end; |
122 |
97 |
123 procedure SoundLoad; |
98 procedure SoundLoad; |
124 var i: TSound; |
99 var i: TSound; |
125 s: shortstring; |
100 s: shortstring; |
132 for i:= Low(TSound) to High(TSound) do |
107 for i:= Low(TSound) to High(TSound) do |
133 if Soundz[i].Path <> ptVoices then |
108 if Soundz[i].Path <> ptVoices then |
134 begin |
109 begin |
135 s:= Pathz[Soundz[i].Path] + '/' + Soundz[i].FileName; |
110 s:= Pathz[Soundz[i].Path] + '/' + Soundz[i].FileName; |
136 WriteToConsole(msgLoading + s + ' '); |
111 WriteToConsole(msgLoading + s + ' '); |
137 defVoicepack^.chunks[i]:= oalb_loadfile(Str2PChar(s)); |
112 defVoicepack^.chunks[i]:= Mix_LoadWAV_RW(SDL_RWFromFile(Str2PChar(s), 'rb'), 1); |
138 TryDo(defVoicepack^.chunks[i] >= 0, msgFailed, true); |
113 TryDo(defVoicepack^.chunks[i] <> nil, msgFailed, true); |
139 WriteLnToConsole(msgOK); |
114 WriteLnToConsole(msgOK); |
140 end; |
115 end; |
141 |
116 |
142 for t:= 0 to cMaxTeams do |
117 for t:= 0 to cMaxTeams do |
143 if voicepacks[t].name <> '' then |
118 if voicepacks[t].name <> '' then |
144 for i:= Low(TSound) to High(TSound) do |
119 for i:= Low(TSound) to High(TSound) do |
145 if Soundz[i].Path = ptVoices then |
120 if Soundz[i].Path = ptVoices then |
146 begin |
121 begin |
147 s:= Pathz[Soundz[i].Path] + '/' + voicepacks[t].name + '/' + Soundz[i].FileName; |
122 s:= Pathz[Soundz[i].Path] + '/' + voicepacks[t].name + '/' + Soundz[i].FileName; |
148 WriteToConsole(msgLoading + s + ' '); |
123 WriteToConsole(msgLoading + s + ' '); |
149 voicepacks[t].chunks[i]:= oalb_loadfile(Str2PChar(s)); |
124 // {$IFNDEF IPHONEOS} |
150 if voicepacks[t].chunks[i] < 0 then |
125 //broken for unknown reasons (most likely poor SDL_Mixer) |
|
126 voicepacks[t].chunks[i]:= Mix_LoadWAV_RW(SDL_RWFromFile(Str2PChar(s), 'rb'), 1); |
|
127 // {$ENDIF} |
|
128 if voicepacks[t].chunks[i] = nil then |
151 WriteLnToConsole(msgFailed) |
129 WriteLnToConsole(msgFailed) |
152 else |
130 else |
153 WriteLnToConsole(msgOK) |
131 WriteLnToConsole(msgOK) |
154 end; |
132 end; |
155 end; |
133 end; |
156 |
134 |
157 function soundFadeOut(snd: TSound; qt: LongInt; voicepack: PVoicepack): LongInt; |
|
158 begin |
|
159 if not isSoundEnabled then exit(0); |
|
160 if (voicepack <> nil) and (voicepack^.chunks[snd] >= 0) then oalb_fadeout(defVoicepack^.chunks[snd], qt) |
|
161 else if (defVoicepack^.chunks[snd] >= 0) then oalb_fadeout(defVoicepack^.chunks[snd], qt); |
|
162 end; |
|
163 |
|
164 procedure PlaySound(snd: TSound; infinite: boolean; voicepack: PVoicepack); |
135 procedure PlaySound(snd: TSound; infinite: boolean; voicepack: PVoicepack); |
|
136 var loops: LongInt; |
165 begin |
137 begin |
166 if (not isSoundEnabled) or fastUntilLag then exit; |
138 if (not isSoundEnabled) or fastUntilLag then exit; |
|
139 if infinite then loops:= -1 else loops:= 0; |
167 |
140 |
168 if voicepack = nil then voicepack:= defVoicepack; |
141 if (voicepack <> nil) and (voicepack^.chunks[snd] <> nil) then |
169 |
142 lastChan[snd]:= Mix_PlayChannelTimed(-1, voicepack^.chunks[snd], loops, -1) |
170 if voicepack^.chunks[snd] >= 0 then |
143 else |
171 begin |
144 lastChan[snd]:= Mix_PlayChannelTimed(-1, defVoicepack^.chunks[snd], loops, -1) |
172 oalb_playsound(voicepack^.chunks[snd], Byte(infinite)); |
|
173 lastChan[snd]:=voicepack^.chunks[snd]; |
|
174 end |
|
175 end; |
145 end; |
176 |
146 |
177 procedure StopSound(snd: TSound); |
147 procedure StopSound(snd: TSound); |
178 begin |
148 begin |
179 if isSoundEnabled then |
149 if not isSoundEnabled then exit; |
180 oalb_stopsound(lastChan[snd]) |
150 if Mix_Playing(lastChan[snd]) <> 0 then |
|
151 Mix_HaltChannel(lastChan[snd]) |
181 end; |
152 end; |
182 |
153 |
183 procedure PlayMusic; |
154 procedure PlayMusic; |
184 var s: string; |
155 var s: string; |
185 begin |
156 begin |
188 or (not isMusicEnabled) then exit; |
159 or (not isMusicEnabled) then exit; |
189 |
160 |
190 s:= PathPrefix + '/Music/' + MusicFN; |
161 s:= PathPrefix + '/Music/' + MusicFN; |
191 WriteToConsole(msgLoading + s + ' '); |
162 WriteToConsole(msgLoading + s + ' '); |
192 |
163 |
193 Mus:= oalb_loadfile(Str2PChar(s)); |
164 Mus:= Mix_LoadMUS(Str2PChar(s)); |
194 TryDo(Mus >= 0, msgFailed, false); |
165 TryDo(Mus <> nil, msgFailed, false); |
195 WriteLnToConsole(msgOK); |
166 WriteLnToConsole(msgOK); |
196 |
167 |
197 oalb_playsound(Mus, 1); |
168 SDLTry(Mix_FadeInMusic(Mus, -1, 3000) <> -1, false) |
198 oalb_fadein(Mus, 20); |
|
199 end; |
169 end; |
200 |
170 |
201 function ChangeVolume(voldelta: LongInt): LongInt; |
171 function ChangeVolume(voldelta: LongInt): LongInt; |
202 begin |
172 begin |
203 if not isSoundEnabled then exit(0); |
173 if not isSoundEnabled then |
|
174 exit(0); |
204 |
175 |
205 inc(Volume, voldelta); |
176 inc(Volume, voldelta); |
206 if Volume < 0 then Volume:= 0; |
177 if Volume < 0 then Volume:= 0; |
207 if Volume > 100 then Volume:= 100; |
178 Mix_Volume(-1, Volume); |
208 |
179 Volume:= Mix_Volume(-1, -1); |
209 oalb_setglobalvolume(Volume); |
180 if isMusicEnabled then Mix_VolumeMusic(Volume * 4 div 8); |
210 if isMusicEnabled then oalb_setvolume(Mus, Volume shr 1); |
181 ChangeVolume:= Volume * 100 div MIX_MAX_VOLUME |
211 ChangeVolume:= Volume; |
|
212 end; |
182 end; |
213 |
183 |
214 procedure PauseMusic; |
184 procedure PauseMusic; |
215 begin |
185 begin |
216 if (MusicFN = '') or (not isMusicEnabled) then exit; |
186 if (MusicFN = '') or (not isMusicEnabled) then exit; |
217 oalb_stopsound(Mus) |
187 |
|
188 Mix_PauseMusic(Mus); |
218 end; |
189 end; |
219 |
190 |
220 procedure ResumeMusic; |
191 procedure ResumeMusic; |
221 begin |
192 begin |
222 if (MusicFN = '') or (not isMusicEnabled) then exit; |
193 if (MusicFN = '') or (not isMusicEnabled) then exit; |
223 oalb_playsound(Mus, 0) |
194 |
|
195 Mix_ResumeMusic(Mus); |
224 end; |
196 end; |
225 |
197 |
|
198 end. |
226 |
199 |
227 var i: LongInt; |
|
228 c: TSound; |
|
229 |
|
230 initialization |
|
231 for i:= 0 to cMaxTeams do |
|
232 for c:= Low(TSound) to High(TSound) do |
|
233 voicepacks[i].chunks[c]:= -1 |
|
234 |
|
235 |
|
236 end. |
|