Class: Doom::Wad::SoundManager

Inherits:
Object
  • Object
show all
Defined in:
lib/doom/wad/sound.rb

Overview

Loads DOOM sound effects from WAD and converts to WAV for Gosu playback. DOOM sound format: 8-byte header (2 format, 2 sample_rate, 4 num_samples) followed by unsigned 8-bit PCM samples.

Instance Method Summary collapse

Constructor Details

#initialize(wad) ⇒ SoundManager

Returns a new instance of SoundManager.



11
12
13
14
15
16
# File 'lib/doom/wad/sound.rb', line 11

def initialize(wad)
  @wad = wad
  @cache = {}  # name => Gosu::Sample
  @temp_dir = File.join(Dir.tmpdir, "doom_rb_sounds_#{Process.pid}")
  Dir.mkdir(@temp_dir) unless Dir.exist?(@temp_dir)
end

Instance Method Details

#[](name) ⇒ Object

Get or load a sound effect. Returns a Gosu::Sample or nil.



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/doom/wad/sound.rb', line 19

def [](name)
  return @cache[name] if @cache.key?(name)

  lump_name = name.start_with?('DS') ? name : "DS#{name}"
  entry = @wad.find_lump(lump_name)
  return @cache[name] = nil unless entry

  data = @wad.read_lump_at(entry)
  return @cache[name] = nil if data.size < 8

  # Parse DOOM sound header
  _format = data[0, 2].unpack1('v')
  sample_rate = data[2, 2].unpack1('v')
  num_samples = data[4, 4].unpack1('V')

  # PCM data starts at offset 8, skip 16 padding bytes at start and end
  pcm_start = 8 + 16
  pcm_end = 8 + num_samples - 16
  pcm_data = data[pcm_start...pcm_end]
  return @cache[name] = nil unless pcm_data && pcm_data.size > 0

  # Convert to WAV file for Gosu
  wav_path = File.join(@temp_dir, "#{lump_name}.wav")
  write_wav(wav_path, pcm_data, sample_rate) unless File.exist?(wav_path)

  @cache[name] = Gosu::Sample.new(wav_path)
rescue => e
  @cache[name] = nil
end

#cleanupObject



49
50
51
# File 'lib/doom/wad/sound.rb', line 49

def cleanup
  FileUtils.rm_rf(@temp_dir) if @temp_dir && Dir.exist?(@temp_dir)
end