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 uses SDLh, uConsts; |
21 |
|
22 {$IFDEF DARWIN} |
|
23 {$linkframework OpenAL} |
|
24 {$linkframework Ogg} |
|
25 {$linkframework Vorbis} |
|
26 {$linklib openalbridge} |
|
27 {$ELSE} |
|
28 {$linklib openal} |
|
29 {$linklib ogg} |
|
30 {$linklib vorbis} |
|
31 {$linklib vorbisfile} |
|
32 {$ENDIF} |
|
33 |
|
34 uses uConsts; |
22 {$INCLUDE options.inc} |
35 {$INCLUDE options.inc} |
23 |
36 |
24 type PVoicepack = ^TVoicepack; |
37 type PVoicepack = ^TVoicepack; |
25 TVoicepack = record |
38 TVoicepack = record |
26 name: shortstring; |
39 name: shortstring; |
27 chunks: array [TSound] of PMixChunk; |
40 chunks: array [TSound] of LongInt; |
28 end; |
41 end; |
|
42 |
|
43 const OpenALBridge = 'libopenalbridge'; |
29 |
44 |
30 procedure InitSound; |
45 procedure InitSound; |
31 procedure ReleaseSound; |
46 procedure ReleaseSound; |
32 procedure SoundLoad; |
47 procedure SoundLoad; |
33 procedure PlaySound(snd: TSound; infinite: boolean; voicepack: PVoicepack); |
48 procedure PlaySound(snd: TSound; infinite: boolean; voicepack: PVoicepack); |
34 procedure PlayMusic; |
49 procedure PlayMusic; |
35 procedure PauseMusic; |
50 procedure PauseMusic; |
36 procedure ResumeMusic; |
51 procedure ResumeMusic; |
37 procedure StopSound(snd: TSound); |
52 procedure StopSound(snd: TSound); |
38 function ChangeVolume(voldelta: LongInt): LongInt; |
53 function ChangeVolume(voldelta: LongInt): LongInt; |
39 |
|
40 function AskForVoicepack(name: shortstring): Pointer; |
54 function AskForVoicepack(name: shortstring): Pointer; |
41 |
55 |
|
56 |
|
57 function openal_init (memsize: LongInt) : boolean; cdecl; external OpenALBridge; |
|
58 function openal_close : boolean; cdecl; external OpenALBridge; |
|
59 function openal_loadfile (filename: PChar) : LongInt; cdecl; external OpenALBridge; |
|
60 function openal_toggleloop (index: LongInt) : boolean; cdecl; external OpenALBridge; |
|
61 function openal_setvolume (index: LongInt; percentage: byte) : boolean; cdecl; external OpenALBridge; |
|
62 function openal_fadeout (index: LongInt; quantity: byte) : boolean; cdecl; external OpenALBridge; |
|
63 function openal_fadein (index: LongInt; quantity: byte) : boolean; cdecl; external OpenALBridge; |
|
64 function openal_playsound (index: LongInt) : boolean; cdecl; external OpenALBridge; |
|
65 function openal_pausesound (index: LongInt) : boolean; cdecl; external OpenALBridge; |
|
66 function openal_stopsound (index: LongInt) : boolean; cdecl; external OpenALBridge; |
|
67 function openal_setglobalvolume (percentage: byte) : boolean; cdecl; external OpenALBridge; |
|
68 |
42 var MusicFN: shortstring = ''; |
69 var MusicFN: shortstring = ''; |
43 |
70 |
44 implementation |
71 implementation |
|
72 |
45 uses uMisc, uConsole; |
73 uses uMisc, uConsole; |
46 |
74 |
47 const chanTPU = 12; |
75 const chanTPU = 12; |
48 var Volume: LongInt; |
76 var lastChan: array [TSound] of LongInt; |
49 lastChan: array [TSound] of LongInt; |
|
50 voicepacks: array[0..cMaxTeams] of TVoicepack; |
77 voicepacks: array[0..cMaxTeams] of TVoicepack; |
51 defVoicepack: PVoicepack; |
78 defVoicepack: PVoicepack; |
52 Mus: PMixMusic = nil; |
79 Mus: LongInt = 0; |
53 |
80 |
54 function AskForVoicepack(name: shortstring): Pointer; |
81 function AskForVoicepack(name: shortstring): Pointer; |
55 var i: Longword; |
82 var i: Longword; |
56 begin |
83 begin |
57 i:= 0; |
84 i:= 0; |
64 voicepacks[i].name:= name; |
91 voicepacks[i].name:= name; |
65 AskForVoicepack:= @voicepacks[i] |
92 AskForVoicepack:= @voicepacks[i] |
66 end; |
93 end; |
67 |
94 |
68 procedure InitSound; |
95 procedure InitSound; |
|
96 const numSounds = 200; |
69 begin |
97 begin |
70 if not isSoundEnabled then exit; |
98 if not isSoundEnabled then exit; |
71 WriteToConsole('Init sound...'); |
99 WriteToConsole('Init OpenAL sound...'); |
72 isSoundEnabled:= SDL_Init(SDL_INIT_AUDIO) >= 0; |
100 isSoundEnabled:= openal_init(numSounds); |
73 if isSoundEnabled then |
|
74 isSoundEnabled:= Mix_OpenAudio(22050, $8010, 2, 512) = 0; |
|
75 if isSoundEnabled then WriteLnToConsole(msgOK) |
101 if isSoundEnabled then WriteLnToConsole(msgOK) |
76 else WriteLnToConsole(msgFailed); |
102 else WriteLnToConsole(msgFailed); |
77 Mix_AllocateChannels(Succ(chanTPU)); |
|
78 if isMusicEnabled then Mix_VolumeMusic(50); |
|
79 |
|
80 Volume:= 0; |
|
81 ChangeVolume(cInitVolume) |
103 ChangeVolume(cInitVolume) |
82 end; |
104 end; |
83 |
105 |
84 procedure ReleaseSound; |
106 procedure ReleaseSound; |
85 var i: TSound; |
107 begin |
86 t: Longword; |
108 openal_close(); |
87 begin |
|
88 for t:= 0 to cMaxTeams do |
|
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 |
|
96 end; |
109 end; |
97 |
110 |
98 procedure SoundLoad; |
111 procedure SoundLoad; |
99 var i: TSound; |
112 var i: TSound; |
100 s: shortstring; |
113 s: shortstring; |
107 for i:= Low(TSound) to High(TSound) do |
120 for i:= Low(TSound) to High(TSound) do |
108 if Soundz[i].Path <> ptVoices then |
121 if Soundz[i].Path <> ptVoices then |
109 begin |
122 begin |
110 s:= Pathz[Soundz[i].Path] + '/' + Soundz[i].FileName; |
123 s:= Pathz[Soundz[i].Path] + '/' + Soundz[i].FileName; |
111 WriteToConsole(msgLoading + s + ' '); |
124 WriteToConsole(msgLoading + s + ' '); |
112 defVoicepack^.chunks[i]:= Mix_LoadWAV_RW(SDL_RWFromFile(Str2PChar(s), 'rb'), 1); |
125 defVoicepack^.chunks[i]:= openal_loadfile (Str2PChar(s)); |
113 TryDo(defVoicepack^.chunks[i] <> nil, msgFailed, true); |
126 TryDo(defVoicepack^.chunks[i] >= 0, msgFailed, true); |
114 WriteLnToConsole(msgOK); |
127 WriteLnToConsole(msgOK); |
115 end; |
128 end; |
116 |
129 |
117 for t:= 0 to cMaxTeams do |
130 for t:= 0 to cMaxTeams do |
118 if voicepacks[t].name <> '' then |
131 if voicepacks[t].name <> '' then |
119 for i:= Low(TSound) to High(TSound) do |
132 for i:= Low(TSound) to High(TSound) do |
120 if Soundz[i].Path = ptVoices then |
133 if Soundz[i].Path = ptVoices then |
121 begin |
134 begin |
122 s:= Pathz[Soundz[i].Path] + '/' + voicepacks[t].name + '/' + Soundz[i].FileName; |
135 s:= Pathz[Soundz[i].Path] + '/' + voicepacks[t].name + '/' + Soundz[i].FileName; |
123 WriteToConsole(msgLoading + s + ' '); |
136 WriteToConsole(msgLoading + s + ' '); |
124 {$IFNDEF IPHONEOS} |
137 voicepacks[t].chunks[i]:= openal_loadfile (Str2PChar(s)); |
125 //broken for unknown reasons (most likely poor SDL_Mixer) |
138 if voicepacks[t].chunks[i] < 0 then |
126 voicepacks[t].chunks[i]:= Mix_LoadWAV_RW(SDL_RWFromFile(Str2PChar(s), 'rb'), 1); |
|
127 {$ENDIF} |
|
128 if voicepacks[t].chunks[i] = nil then |
|
129 WriteLnToConsole(msgFailed) |
139 WriteLnToConsole(msgFailed) |
130 else |
140 else |
131 WriteLnToConsole(msgOK) |
141 WriteLnToConsole(msgOK) |
132 end; |
142 end; |
133 end; |
143 end; |
134 |
144 |
135 procedure PlaySound(snd: TSound; infinite: boolean; voicepack: PVoicepack); |
145 procedure PlaySound(snd: TSound; infinite: boolean; voicepack: PVoicepack); |
136 var loops: LongInt; |
|
137 begin |
146 begin |
138 if (not isSoundEnabled) or fastUntilLag then exit; |
147 if (not isSoundEnabled) or fastUntilLag then exit; |
139 if infinite then loops:= -1 else loops:= 0; |
148 |
140 |
149 if (voicepack <> nil) and (voicepack^.chunks[snd] >= 0) then |
141 if (voicepack <> nil) and (voicepack^.chunks[snd] <> nil) then |
150 begin |
142 lastChan[snd]:= Mix_PlayChannelTimed(-1, voicepack^.chunks[snd], loops, -1) |
151 if infinite then openal_toggleloop(voicepack^.chunks[snd]); |
|
152 openal_playsound(voicepack^.chunks[snd]); |
|
153 lastChan[snd]:=voicepack^.chunks[snd]; |
|
154 end |
143 else |
155 else |
144 lastChan[snd]:= Mix_PlayChannelTimed(-1, defVoicepack^.chunks[snd], loops, -1) |
156 begin |
|
157 if infinite then openal_toggleloop(defVoicepack^.chunks[snd]); |
|
158 openal_playsound(defVoicepack^.chunks[snd]); |
|
159 lastChan[snd]:=defVoicepack^.chunks[snd]; |
|
160 |
|
161 end |
145 end; |
162 end; |
146 |
163 |
147 procedure StopSound(snd: TSound); |
164 procedure StopSound(snd: TSound); |
148 begin |
165 begin |
149 if not isSoundEnabled then exit; |
166 if not isSoundEnabled then exit; |
150 if Mix_Playing(lastChan[snd]) <> 0 then |
167 openal_stopsound(lastChan[snd]) |
151 Mix_HaltChannel(lastChan[snd]) |
|
152 end; |
168 end; |
153 |
169 |
154 procedure PlayMusic; |
170 procedure PlayMusic; |
155 var s: string; |
171 var s: string; |
156 begin |
172 begin |
159 or (not isMusicEnabled) then exit; |
175 or (not isMusicEnabled) then exit; |
160 |
176 |
161 s:= PathPrefix + '/Music/' + MusicFN; |
177 s:= PathPrefix + '/Music/' + MusicFN; |
162 WriteToConsole(msgLoading + s + ' '); |
178 WriteToConsole(msgLoading + s + ' '); |
163 |
179 |
164 Mus:= Mix_LoadMUS(Str2PChar(s)); |
180 Mus:= openal_loadfile(Str2PChar(s)); |
165 TryDo(Mus <> nil, msgFailed, false); |
181 TryDo(Mus >= 0, msgFailed, false); |
166 WriteLnToConsole(msgOK); |
182 WriteLnToConsole(msgOK); |
167 |
183 |
168 SDLTry(Mix_FadeInMusic(Mus, -1, 3000) <> -1, false) |
184 openal_fadein(Mus, 50); |
|
185 openal_toggleloop(Mus); |
169 end; |
186 end; |
170 |
187 |
171 function ChangeVolume(voldelta: LongInt): LongInt; |
188 function ChangeVolume(voldelta: LongInt): LongInt; |
172 begin |
189 begin |
173 if not isSoundEnabled then |
190 if not isSoundEnabled then exit(0); |
174 exit(0); |
191 openal_setglobalvolume(voldelta); |
175 |
|
176 inc(Volume, voldelta); |
|
177 if Volume < 0 then Volume:= 0; |
|
178 Mix_Volume(-1, Volume); |
|
179 Volume:= Mix_Volume(-1, -1); |
|
180 if isMusicEnabled then Mix_VolumeMusic(Volume * 4 div 8); |
|
181 ChangeVolume:= Volume * 100 div MIX_MAX_VOLUME |
|
182 end; |
192 end; |
183 |
193 |
184 procedure PauseMusic; |
194 procedure PauseMusic; |
185 begin |
195 begin |
186 if (MusicFN = '') or (not isMusicEnabled) then exit; |
196 if (MusicFN = '') or (not isMusicEnabled) then exit; |
187 |
197 openal_pausesound(Mus); |
188 Mix_PauseMusic(Mus); |
|
189 end; |
198 end; |
190 |
199 |
191 procedure ResumeMusic; |
200 procedure ResumeMusic; |
192 begin |
201 begin |
193 if (MusicFN = '') or (not isMusicEnabled) then exit; |
202 if (MusicFN = '') or (not isMusicEnabled) then exit; |
194 |
203 openal_playsound(Mus); |
195 Mix_ResumeMusic(Mus); |
|
196 end; |
204 end; |
197 |
205 |
198 end. |
206 end. |