Playing spatialized 3D sound
Mix.install([
{:zexray, github: "jn-jairo/zexray", depth: 1}
])
Code example
Example complexity rating: [★★☆☆] 2/4
defmodule Example do
@resources_dir System.tmp_dir!() <> "/zexray/resources"
@resources_url "https://github.com/raysan5/raylib/raw/3e336e4470f7975af67f716d4d809441883d7eef"
use Zexray.Enum
use Zexray.Type
def download_resources do
File.mkdir_p!(@resources_dir)
resources = %{
"#{@resources_dir}/coin.wav" => "#{@resources_url}/examples/audio/resources/coin.wav"
}
:inets.start()
:ssl.start()
Enum.each(resources, fn {file, url} ->
if not File.exists?(file) do
{:ok, :saved_to_file} =
:httpc.request(:get, {~c"#{url}", []}, [], stream: ~c"#{file}")
end
end)
end
@screen_width 800
@screen_height 450
@title "zexray [audio] example - Playing spatialized 3D sound"
@buffer_size 4096
def init do
# Initialize window
Zexray.Window.with_window(@screen_width, @screen_height, @title, fn ->
# Initialize audio device
Zexray.Audio.with_audio(fn ->
# Set our game to run at 60 frames-per-second
Zexray.Timing.set_target_fps(60)
Zexray.Audio.set_buffer_size(@buffer_size)
Zexray.Cursor.disable()
# Manage resources loading/unloading
Zexray.Resource.with_resource(
fn ->
sound =
Zexray.Resource.with_resource_async(
fn ->
Zexray.Audio.load_wave("#{@resources_dir}/coin.wav", :resource)
# Format to 32 bits stereo to allow extra positioning effect
|> Zexray.Audio.wave_format(44_100, 32, 2)
end,
fn wave ->
Zexray.Audio.load_sound_stream_from_wave(wave, :resource)
end
)
|> Zexray.Audio.set_looping(true)
|> Zexray.Audio.play()
camera =
type_camera_3d(
position: type_vector3(x: 0, y: 1, z: 0),
target: type_vector3(x: 0, y: 1, z: 1),
up: type_vector3(x: 0, y: 1, z: 0),
fovy: 60,
projection: enum_camera_projection(:perspective)
)
|> Zexray.Resource.new!()
max_distance = 20
{
sound,
camera,
max_distance
}
end,
&loop/1
)
end)
end)
end
defp loop({sound, camera, max_distance} = state) do
# Detect window close button or ESC key
if Zexray.Window.should_close?() do
:ok
else
# Update
Zexray.Camera.update(camera, enum_camera_mode(:free))
th = Zexray.Timing.get_time()
sphere_pos =
type_vector3(
x: 5 * :math.cos(th),
y: 0,
z: 5 * :math.sin(th)
)
Zexray.Audio.with_mode_3d(camera, max_distance, fn ->
sound
|> Zexray.Audio.set_position(sphere_pos)
|> Zexray.Audio.update()
end)
# Draw
Zexray.Drawing.with_drawing(fn ->
Zexray.Drawing.clear_background(enum_color(:raywhite))
Zexray.Drawing.with_mode_3d(camera, fn ->
Zexray.Shape3D.draw_grid(10, 2)
Zexray.Shape3D.draw_sphere(sphere_pos, 0.5, enum_color(:red))
end)
end)
loop(state)
end
end
end
Example.download_resources()
Example.init()