note
	description: "[
		i_sound.c
		System interface for sound.
	]"
	license: "[
				Copyright (C) 1993-1996 by id Software, Inc.
				Copyright (C) 2005-2014 Simon Howard
				Copyright (C) 2021 Ilgiz Mustafin
		
				This program is free software; you can redistribute it and/or modify
				it under the terms of the GNU General Public License as published by
				the Free Software Foundation; either version 2 of the License, or
				(at your option) any later version.
		
				This program is distributed in the hope that it will be useful,
				but WITHOUT ANY WARRANTY; without even the implied warranty of
				MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
				GNU General Public License for more details.
		
				You should have received a copy of the GNU General Public License along
				with this program; if not, write to the Free Software Foundation, Inc.,
				51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
	]"

class 
	I_SOUND

create 
	make

feature -- Chocolate doom snddevice_t

	Snddevice_none: INTEGER_32 = 0

	Snddevice_pcspeaker: INTEGER_32 = 1

	Snddevice_adlib: INTEGER_32 = 2

	Snddevice_sb: INTEGER_32 = 3

	Snddevice_pas: INTEGER_32 = 4

	Snddevice_gus: INTEGER_32 = 5

	Snddevice_waveblaster: INTEGER_32 = 6

	Snddevice_soundcanvas: INTEGER_32 = 7

	Snddevice_genmidi: INTEGER_32 = 8

	Snddevice_awe32: INTEGER_32 = 9

	Snddevice_cd: INTEGER_32 = 10
	
feature 

	Norm_pitch: INTEGER_32 = 127

	Snd_pitchshift: INTEGER_32 = 0
			-- Doom defaults to pitch-shifting off
	
feature 

	i_main: I_MAIN

	make (a_i_main: like i_main)
		do
			i_main := a_i_main
			snd_musicdevice := Snddevice_genmidi
			snd_sfxdevice := Snddevice_sb
			create music_pack_module.make
		end
	
feature -- Chocolate doom

	Snd_musiccmd: STRING_8 = ""

	Snd_samplerate: INTEGER_32 = 44100
			-- Sound sample rate to use for digital output (Hz)

	Snd_maxslicetime_ms: INTEGER_32 = 28
			-- Config variable that controls the sound buffer size.
			-- We default to 28ms (1000 / 35fps = 1 buffer per tic).

	snd_musicdevice: INTEGER_32

	snd_sfxdevice: INTEGER_32

	active_music_module: detachable MUSIC_MODULE_T

	music_packs_active: BOOLEAN

	sound_module: detachable SOUND_MODULE_T

	music_module: detachable MUSIC_MODULE_T

	Sound_modules: ARRAY [detachable SOUND_MODULE_T]
		once
			Result := ARRAY [detachable SOUND_MODULE_T] <<{SOUND_SDL_MODULE}.sound_sdl_module (i_main), {SOUND_PCSOUND_MODULE}.sound_pcsound_module, Void>>
		end

	Music_sdl_module: MUSIC_SDL_MODULE
		once
			Result := {MUSIC_SDL_MODULE}.music_sdl_module (i_main)
		end

	Music_modules: ARRAY [detachable MUSIC_MODULE_T]
		once
			Result := ARRAY [detachable MUSIC_MODULE_T] <<Music_sdl_module, {MUSIC_OPL_MODULE}.music_opl_module, Void>>
		end
	
feature -- Chocolate doom Sound modules

	music_pack_module: I_MUSICPACK
	
feature 

	Steptable: ARRAY [INTEGER_32]
			-- Pitch to stepping lookup, unused.
		once
			create Result.make_filled (0, 0, 255)
		end

	Vol_lookup: ARRAY [INTEGER_32]
			-- Volume lookups.
		once
			create Result.make_filled (0, 0, 128 * 256 - 1)
		end
	
feature 

	i_initsound (use_sfx_prefix: BOOLEAN)
		local
			nomusicpacks: BOOLEAN
			nosound: BOOLEAN
			nomusic: BOOLEAN
			nosfx: BOOLEAN
		do
			{NOT_IMPLEMENTED}.not_implemented ("I_InitSound", False)
			nosound := i_main.m_argv.m_checkparm ("-nosound").to_boolean
			nomusic := i_main.m_argv.m_checkparm ("-nomusic").to_boolean
			nomusicpacks := True
			{M_CONFIG}.m_setmusicpackdir
			if not nosound and not i_main.I_video.screensaver_mode then
				if not nosfx then
					initsfxmodule (use_sfx_prefix)
				end
				if not nomusic then
					initmusicmodule
					active_music_module := music_module
				end
				if not nomusicpacks and attached music_module as m then
					music_packs_active := music_pack_module.init
				end
			end
		end

	initsfxmodule (use_sfx_prefix: BOOLEAN)
			-- Find and initialize a sound_module_t appropriate for the setting
			-- in snd_sfxdevice.
		do
			sound_module := Void
			across
				Sound_modules as i
			loop
				if sound_module = Void and then attached i.item as sm then
					if across
						sm.sound_devices is x
					some
						snd_sfxdevice = x
					end then
						if sm.init (use_sfx_prefix) then
							sound_module := sm
						end
					end
				end
			end
		end

	initmusicmodule
		do
			music_module := Void
			across
				Music_modules as i
			loop
				if music_module = Void and then attached i.item as m then
					if across
						m.sound_devices is d
					some
						snd_musicdevice = d
					end then
						if m.init then
							music_module := m
						end
					end
				end
			end
		end

	i_stopsound (channel: INTEGER_32)
		do
			if attached sound_module as m then
				m.stop_sound (channel)
			end
		end

	i_soundisplaying (channel: INTEGER_32): BOOLEAN
			-- from chocolate doom
		do
			if attached sound_module as m then
				Result := m.sound_is_playing (channel)
			end
		end

	i_updatesoundparams (channel, vol, sep: INTEGER_32)
			-- from chocolate doom
		do
			if attached sound_module as m then
				m.update_sound_params (channel, check_volume (vol), check_separation (sep))
			end
		end

	i_setchannels
			-- SFX API
			-- Note: this was called by S_Init.
			-- However, whatever they did in the
			-- old DPMS based DOS version, this
			-- were simply dummies in the Linux
			-- version.
			-- See soundserver initdata().
		local
			i, j: INTEGER_32
			steptablemid: INTEGER_32
		do
			steptablemid := 128
			from
				i := -128
			until
				i >= 128
			loop
				Steptable [steptablemid + i] := ((2).to_real.power (i / 64) * 65536.to_double).floor
				i := i + 1
			end
			from
				i := 0
			until
				i >= 128
			loop
				from
					j := 0
				until
					j >= 256
				loop
					Vol_lookup [i * 256 + j] := (i * (j - 128) * 256) // 127
					j := j + 1
				end
				i := i + 1
			end
		end

	i_setmusicvolume (volume: INTEGER_32)
		do
			if attached active_music_module as m then
				m.set_music_volume (volume)
			end
		end

	i_pausesong
		do
			if attached active_music_module as m then
				m.pause_music
			end
		end

	i_resumesong
		do
			if attached active_music_module as m then
				m.resumemusic
			end
		end

	i_stopsong
		do
			if attached active_music_module as m then
				m.stopsong
			end
		end

	i_unregistersong (handle: detachable ANY)
		do
			if attached active_music_module as m then
				m.unregistersong (handle)
			end
		end

	i_registersong (data: detachable ANY; len: INTEGER_32): detachable ANY
		local
			handle: ANY
		do
			if music_packs_active then
				handle := music_pack_module.registersong (data, len)
				if attached handle as h then
					active_music_module := music_pack_module
					Result := h
				end
			end
			if Result = Void then
				active_music_module := music_module
				if attached active_music_module as m then
					Result := m.registersong (data, len)
				end
			end
		end

	i_playsong (handle: detachable ANY; looping: BOOLEAN)
		do
			if attached active_music_module as m then
				m.playsong (handle, looping)
			end
		end

	i_getsfxlumpnum (sfxinfo: SFXINFO_T): INTEGER_32
		do
			if attached sound_module as m then
				Result := m.get_sfx_lump_num (sfxinfo)
			else
				Result := 0
			end
		end

	i_updatesound
		do
			if attached sound_module as m then
				m.update
			end
			if attached active_music_module as mm then
				mm.poll
			end
		end

	i_startsound (sfxinfo: SFXINFO_T; channel, vol, sep, pitch: INTEGER_32): INTEGER_32
		do
			if attached sound_module as m then
				Result := m.start_sound (sfxinfo, channel, check_volume (vol), check_separation (sep), pitch)
			end
		end

	check_volume (volume: INTEGER_32): INTEGER_32
		do
			Result := volume.max (0).min (127)
		end

	check_separation (separation: INTEGER_32): INTEGER_32
		do
			Result := separation.max (0).min (254)
		end
	
end -- class I_SOUND

Generated by ISE EiffelStudio