hedgewars/uSound.pas
changeset 2191 20c62f787a4d
parent 2171 8208946331ba
child 2192 4763a778c033
equal deleted inserted replaced
2190:cfcad6142d48 2191:20c62f787a4d
    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.