Sound - kuimoani/defold GitHub Wiki

Sound

이 메뉴얼은 Defold ν”„λ‘œμ νŠΈλ‘œ μ‚¬μš΄λ“œλ₯Ό 가져와 μž¬μƒν•˜κ³  μ œμ–΄ν•˜λŠ” 방법에 λŒ€ν•˜ μ„±λ©Έν•©λ‹ˆλ‹€.

Defold의 μ‚¬μš΄λ“œ κ΅¬ν˜„μ€ κ°„λ‹¨ν•˜μ§€λ§Œ κ°•λ ₯ν•©λ‹ˆλ‹€. μ•Œμ•„ 두어야 ν•  κ°œλ…μ€ 두 κ°€μ§€ λΏμž…λ‹ˆλ‹€.

Sound components

이 μ»΄ν¬λ„ŒνŠΈλŠ” μ†Œλ¦¬λ₯Ό μž¬μƒν•˜κΈ° μœ„ν•œ μ‹€μ œ μ‚¬μš΄λ“œλ₯Ό ν¬ν•¨ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

Sound groups

각 μ‚¬μš΄λ“œ μ»΄ν¬λ„ŒνŠΈλ₯Ό 그룹에 μ†ν•˜λ„λ‘ μ§€μ •ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. 그룹을 μ‚¬μš©ν•˜μ—¬ μ†Œμ†λœ μ‚¬μš΄λ“œλ“€μ„ 직관적인 λ°©λ²•μœΌλ‘œ μ‰½κ²Œ 관리할 수 μžˆμŠ΅λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, "sound_fx" 같은 그룹을 λ§Œλ“€μ–΄ κ°„λ‹¨ν•œ ν•¨μˆ˜ 호좜둜 λ‹€λ₯Έ 그룹의 μ‚¬μš΄λ“œλ“€μ„ μ†Œλ¦¬κ°€ μž‘μ•„μ§€κ²Œ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Creating a sound component

μ‚¬μš΄λ“œ μ»΄ν¬λ„ŒνŠΈλŠ” κ²Œμž„ 였브젝트의 λ‚΄μž₯ 였브젝트둜만 λ§Œλ“€ 수 μžˆμŠ΅λ‹ˆλ‹€. μƒˆ κ²Œμž„ 였브젝트λ₯Ό λ§Œλ“€κ³  였λ₯Έμͺ½ ν΄λ¦­ν•˜κ³  Add Componentλ₯Ό μ„ νƒν•©λ‹ˆλ‹€. Soundλ₯Ό μ„ νƒν•˜κ³  OKλ₯Ό λˆ„λ₯΄μ„Έμš”.

Select component

μƒμ„±λœ μ»΄ν¬λ„ŒνŠΈμ—λŠ” μ•„λž˜μ™€ 같은 속성듀이 μžˆμŠ΅λ‹ˆλ‹€.

Sound

SoundλŠ” ν”„λ‘œμ νŠΈμ— μžˆλŠ” μ‚¬μš΄λ“œ 파일둜 μ„€μ •λ˜λ©° Waveλ‚˜ Ogg Vorbis 포멧을 μ§€μ›ν•©λ‹ˆλ‹€. (μžμ„Έν•œ λ‚΄μš©μ€ http://en.wikipedia.org/wiki/WAV 와 http://en.wikipedia.org/wiki/Vorbis μ°Έκ³ )

Looping

μ²΄ν¬λ˜μ–΄ μžˆλ‹€λ©΄ μ§μ ‘μ μœΌλ‘œ 쀑단 μ‹œν‚¬λ•Œ κΉŒμ§€ μž¬μƒμ΄ λ°˜λ³΅λ©λ‹ˆλ‹€.

Gain

이 μ»΄ν¬λ„ŒνŠΈμ—μ„œ μ‚¬μš΄λ“œμ˜ 게인(gain)을 직접 μ„€μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 이λ₯Ό 톡해 μ‚¬μš΄λ“œ νŽΈμ§‘ ν”„λ‘œκ·Έλž¨μœΌλ‘œ λ˜λŒμ•„κ°€μ„œ μž¬μž‘μ—…ν•˜κ³  λ‹€μ‹œ μ΅μŠ€ν¬νŠΈν•˜λŠ” 과정없이 μ‰½κ²Œ 게인(gain)을 μ‘°μ ˆν•˜κ²Œ ν•΄ μ€λ‹ˆλ‹€. μ–΄λ–»κ²Œ 게인(gain)이 κ³„μ‚°λ˜λŠ”μ§€ μžμ„Ένžˆ μ•Œλ €λ©΄ μ•„λž˜λ₯Ό μ°Έκ³ ν•˜μ‹­μ‹œμ˜€.

Group

μ‚¬μš΄λ“œκ°€ 속할 μ‚¬μš΄λ“œ 그룹의 μ΄λ¦„μž…λ‹ˆλ‹€. 이 속성값이 λΉ„μ–΄μžˆλ‹€λ©΄, μ‚¬μš΄λ“œλŠ” 기본적으둜 "master" 그룹에 ν• λ‹Ήλ©λ‹ˆλ‹€.

Create component

Gain

Gain

μ‚¬μš΄λ“œ μ‹œμŠ€ν…œμ€ 4κ°€μ§€ λ‹¨κ³„λ‘œ 게인(gain)을 κ³„μ‚°ν•˜μ—¬ μ²˜λ¦¬ν•©λ‹ˆλ‹€.

  1. μ‚¬μš΄λ“œ μ»΄ν¬λ„ŒνŠΈμ—μ„œ μ…‹νŒ…λœ 게인(gain)
  2. "play_sound" λ©”μ„Έμ§€λ₯Ό 톡해 μ…‹νŒ…λ˜κ±°λ‚˜ "set_gain" λ©”μ„Έμ§€λ₯Ό 톡해 λ³€κ²½λ˜λŠ” 게인(gain)
  3. sound.set_group_gain() ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•΄μ„œ 그룹에 μ…‹νŒ…λ˜λŠ” 게인(gain)
  4. "master" 그룹에 μ…‹νŒ…λœ 게인(gain). μ΄λŠ” sound.set_group_gain(hash("master")) 둜 λ³€κ²½ κ°€λŠ₯

μœ„μ˜ 4λ‹¨κ³„μ˜ 게인(gain)을 κ³±ν•˜μ—¬ 졜총 좜λ ₯ 게인(gain)을 κ³„μ‚°ν•©λ‹ˆλ‹€. κΈ°λ³Έ 게인(gain)은 μ–΄λ””μ—μ„œλ‚˜ 1.0μž…λ‹ˆλ‹€. (0 dB)

Sound groups

μ‚¬μš΄λ“œ 그룹의 이름이 μ§€μ •λœ μ‚¬μš΄λ“œ μ»΄ν¬λ„ŒνŠΈλŠ” ν•΄λ‹Ή μ΄λ¦„μ˜ μ‚¬μš΄λ“œ 그룹에 μ†ν•˜κ²Œ λ©λ‹ˆλ‹€. λ§Œμ•½ 그룹을 μ§€μ •ν•˜μ§€ μ•Šμ•˜λ‹€λ©΄ 기본적으둜 "master" 그룹에 ν• λ‹Ήλ©λ‹ˆλ‹€. λ˜ν•œ μ‚¬μš΄λ“œ μ»΄ν¬λ„ŒνŠΈμ˜ 그룹을 λͺ…μ‹œμ μœΌλ‘œ "master" 그룹을 지정해도 λ©λ‹ˆλ‹€.

λͺ‡ ν•¨μˆ˜λŠ” μ‚¬μš©κ°€λŠ₯ν•œ λͺ¨λ“  그룹을 가져와 그룹의 이름을 μ•Œμ•„λ‚΄κ³  게인(gain), rms( http://en.wikipedia.org/wiki/Root_mean_square μ°Έκ³ ), 피크 게인(peak gain)을 μ–»κ±°λ‚˜ μ„€μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€. λ˜ν•œ λŒ€μƒ λ””λ°”μ΄μŠ€μ˜ μŒμ•… ν”Œλ ˆμ΄μ–΄κ°€ 싀행쀑인지 ν…ŒμŠ€νŠΈν•˜λŠ” ν•¨μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

-- μ•„μ΄ν°μ΄λ‚˜ μ•ˆλ“œλ‘œμ΄λ“œ λ””λ°”μ΄μŠ€μ—μ„œ μ‚¬μš΄λ“œκ°€ ν”Œλ ˆμ΄ 쀑이라면, λͺ¨λ“  μ†Œλ¦¬λ₯Ό 쀄여버림
if sound.is_music_playing() then
    for i, group_hash in ipairs(sound.get_groups()) do
        sound.set_group_gain(group_hash, 0)
    end
end

이 그룹듀은 해쉬(hash) κ°’μœΌλ‘œ μ‹λ³„λ©λ‹ˆλ‹€. λ¬Έμžμ—΄λ‘œ 된 이름은 sound.get_group_name() 을 μ‚¬μš©ν•˜μ—¬ κ°€μ Έμ˜¬ 수 있으며 이 이름은 κ°œλ°œλ„κ΅¬μ—μ„œ μ‚¬μš΄λ“œ κ·Έλ£Ή 이름을 ν‘œμ‹œν•΄μ•Όν•  경우 μ‚¬μš©λ  수 μžˆμŠ΅λ‹ˆλ‹€. (μ˜ˆλ“€ λ“€μ–΄ μ‚¬μš΄λ“œλ₯Ό μ‘°μ ˆν•˜λŠ” λ―Ήμ„œ λ“±)

Sound group mixer

릴리즈된 λΉŒλ“œμ—μ„œλŠ” μ‚¬μš©ν•  수 μ—†μœΌλ―€λ‘œ μ‚¬μš΄λ“œ 그룹의 λ¬Έμžμ—΄κ°’μ— μ˜μ‘΄ν•˜λŠ” μ½”λ“œλ₯Ό μž‘μ„±ν•˜λ©΄ μ•ˆλ©λ‹ˆλ‹€.

λͺ¨λ“  값은 0κ³Ό 1.0(0 dB) μ‚¬μ΄μ˜ κ°’μž…λ‹ˆλ‹€. λ°μ‹œλ²¨λ‘œ λ³€ν™˜ν•˜λ €λ©΄, κ°„λ‹¨ν•˜κ²Œ db = 20 * math.log10(gain) ν‘œμ€€κ³΅μ‹μ„ μ‚¬μš©ν•˜λ©΄ λ©λ‹ˆλ‹€.

for i, group_hash in ipairs(sound.get_groups()) do
	-- λ¬Έμžμ—΄ 이름은 디버그 λΉŒλ“œμ—μ„œλ§Œ μ‚¬μš©κ°€λŠ₯함. λ¦΄λ¦¬μ¦ˆλΉŒλ“œμ—μ„  "unknown_*"라고 λ°˜ν™˜λ¨
	local name = sound.get_group_name(group_hash)
    local gain = sound.get_group_gain(group_hash)

    -- λ°μ‹œλ²¨λ‘œ λ³€ν™˜ν•˜κΈ°
	local db = 20 * math.log10(gain)

    -- RMS (gain Root Mean Square) μ–»κΈ°. μ™Όμͺ½ 였λ₯Έμͺ½ 채널 뢄리
	local left_rms, right_rms = sound.get_rms(group_hash, 2048 / 65536.0)
    left_rmsdb = 20 * math.log10(left_rms)
	right_rmsdb = 20 * math.log10(right_rms)

	-- gain peak μ–»κΈ°. μ™Όμͺ½ 였λ₯Έμͺ½μœΌλ‘œ 뢄리
	left_peak, right_peak = sound.get_peak(group_hash, 2048 * 10 / 65536.0)
    left_peakdb = 20 * math.log10(left_peak)
	right_peakdb = 20 * math.log10(right_peak)
end

-- master gain을 +6 dB 둜 μ„€μ •ν•˜κΈ° (math.pow(10, 6/20))
sound.set_group_gain("master", 1.995)

Gating sounds

λ§Œμ•½ κ²Œμž„μ΄ νŠΉμ • μ΄λ²€νŠΈλ§ˆλ‹€ λ™μΌν•œ μ‚¬μš΄λ“œλ‘œ μž¬μƒλ˜κ³  이 μ΄λ²€νŠΈκ°€ 자주 트리거 λœλ‹€λ©΄, 동일 μ‚¬μš΄λ“œλ₯Ό 거의 λ™μ‹œμ— μž¬μƒλ˜μ–΄ λ²„λ¦¬λŠ” λ¬Έμ œκ°€ λ°œμƒν•©λ‹ˆλ‹€. λˆˆμ— λ„λŠ” ν˜„μƒμœΌλ‘œλŠ” μœ„μƒ 변이(phase-shift ) ν˜„μƒμ΄ μƒκΈ°λŠ” λ¬Έμ œκ°€ μžˆμŠ΅λ‹ˆλ‹€.

Phase shift

이 문제λ₯Ό ν•΄κ²°ν•˜λŠ” κ°€μž₯ μ‰¬μš΄ 방법은 μ‚¬μš΄λ“œ λ©”μ„Έμ§€λ₯Ό ν•„ν„°λ§ν•˜λŠ” κΈ°λŠ₯(gate)을 λ§Œλ“€μ–΄ νŠΉμ • μ‹œκ°„ 간격 λ‚΄μ—μ„œλŠ” λ™μΌν•œ μ‚¬μš΄λ“œκ°€ μž¬μƒλ˜λŠ” 것을 λ§‰λŠ” 방법이 μžˆμŠ΅λ‹ˆλ‹€.

-- gate_time μ‹œκ°„ λ‚΄μ—μ„œ λ™μΌν•œ μ‚¬μš΄λ“œκ°€ μž¬μƒλ˜λŠ”κ±Έ λ§‰μž
local gate_time = 0.3

function init(self)
	-- μž¬μƒλœ μ‚¬μš΄λ“œμ˜ 타이머듀을 ν…Œμ΄λΈ”λ‘œ κ΄€λ¦¬ν•˜κ³  λ§€ ν”„λ ˆμž„λ§ˆλ‹€ "gate_time" μ΄ˆκ°€ 될 λ•ŒκΉŒμ§€ 카운트 λ‹€μš΄ν•¨. 그리고 λ‚˜μ„œ μ‚­μ œ
	self.sounds = {}
end

function update(self, dt)
	-- μ €μž₯된 타이머듀을 카운트 λ‹€μš΄ 함
	for k,_ in pairs(self.sounds) do
		self.sounds[k] = self.sounds[k] - dt
		if self.sounds[k] < 0 then
			self.sounds[k] = nil
		end
	end
end

function on_message(self, message_id, message, sender)
	if message_id == hash("play_gated_sound") then
		-- ν˜„μž¬ κ²Œμ΄νŒ… ν…Œμ΄λΈ”(gating table)에 μ—†λŠ” μ‚¬μš΄λ“œλ§Œ μž¬μƒν•˜μž
		if self.sounds[message.soundcomponent] == nil then
			-- ν…Œμ΄λΈ”μ— μ‚¬μš΄λ“œ 타이머λ₯Ό μ €μž₯함
			self.sounds[message.soundcomponent] = gate_time
			-- "play_sound" λ©”μ„Έμ§€λ₯Ό μ‹€μ œ νƒ€κ²ŸμœΌλ‘œ 보냄
			msg.post(message.soundcomponent, "play_sound", { gain = message.gain })
		else
            -- μž¬μƒν•˜λ €λŠ” μ‚¬μš΄λ“œλ₯Ό λ§‰μ•˜μŒ
			print("gated " .. message.soundcomponent)
		end
	end
end

게이트(gate)λ₯Ό μ‚¬μš©ν•˜λ €λ©΄, κ°„λ‹¨νžˆ "play_gated_sound" 메세지에 νƒ€κ²Ÿ μ‚¬μš΄λ“œ μ»΄ν¬λ„ŒνŠΈμ™€ μ‚¬μš΄λ“œ 게인(gain)을 μ§€μ •ν•΄μ„œ μ „μ†‘ν•˜λ©΄ λ©λ‹ˆλ‹€. 이 κ²Œμ΄νŠΈλŠ” κ²Œμ΄νŠΈκ°€ μ—΄λ € μžˆλ‹€λ©΄ "play_sound" λ©”μ„Έμ§€λ₯Ό νƒ€κ²Ÿ μ‚¬μš΄λ“œ μ»΄ν¬λ„ŒνŠΈλ‘œ λ³΄λ‚΄κ²Œ λ©λ‹ˆλ‹€.

msg.post("/sound_gate#script", "play_gated_sound", { soundcomponent = "/sounds#explosion1, gain = 1.0 })

"play_sound"λŠ” Defold 엔진에 μ˜ν•΄ μ˜ˆμ•½λœ μ΄λ¦„μ΄λ―€λ‘œ κ²Œμ΄νŠΈλŠ” 이 λ©”μ„Έμ§€λ₯Ό 듀을 수 μ—†μŠ΅λ‹ˆλ‹€. μ˜ˆμ•½λœ λ©”μ„Έμ§€ 이름을 μ‚¬μš©ν•˜λ©΄ 예기치 μ•Šμ€ λ™μž‘μ΄ λ°œμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€.