hedgewars/uSound.pas
changeset 2515 51d3f4b6293a
parent 2501 51ebab1b446d
child 2599 c7153d2348f3
equal deleted inserted replaced
2514:df9d0728c5bb 2515:51d3f4b6293a
    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.