Skip to content

Commit b7d6e77

Browse files
committed
Add Crystal port of ex_audio_timer.c from the Allegro examples
1 parent 3efbd48 commit b7d6e77

File tree

3 files changed

+146
-1
lines changed

3 files changed

+146
-1
lines changed

Diff for: examples/ex_audio_timer.cr

+141
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
# Crystal port of ex_audio_timer.c from the Allegro examples.
2+
3+
#
4+
# Example program for the Allegro library.
5+
#
6+
7+
require "../src/crystal_allegro"
8+
require "./common"
9+
10+
class ExAudioTimer
11+
include Common
12+
13+
RESERVED_SAMPLES = 16
14+
PERIOD = 5
15+
16+
property! display : Pointer(LibAllegro::Display)?
17+
property! font : LibAllegro::Font?
18+
property! ping : LibAllegro::Sample?
19+
property! timer : LibAllegro::Timer*?
20+
property! event_queue : LibAllegro::EventQueue?
21+
22+
def create_sample_s16(freq, len)
23+
buf = CrystalAllegro.malloc(freq * len * sizeof(LibC::Int16T))
24+
25+
LibAllegro.create_sample(buf, len, freq, LibAllegro::AudioDepth::AudioDepthInt16,
26+
LibAllegro::ChannelConf::ChannelConf1, 1)
27+
end
28+
29+
# Adapted from SPEED.
30+
def generate_ping
31+
# ping consists of two sine waves
32+
len = 8192
33+
ping = create_sample_s16(22050, len)
34+
return nil unless ping
35+
36+
p = LibAllegro.get_sample_data(ping).as(Pointer(LibC::Int16T))
37+
38+
osc1 = 0.0
39+
osc2 = 0.0
40+
41+
len.times do |i|
42+
vol = (len - i).to_f / len.to_f * 4000
43+
44+
ramp = i.to_f / len.to_f * 8
45+
vol *= ramp if ramp < 1.0
46+
47+
p.value = ((Math.sin(osc1) + Math.sin(osc2) - 1) * vol).to_i16
48+
49+
osc1 += 0.1
50+
osc2 += 0.15
51+
52+
p += 1
53+
end
54+
55+
return ping
56+
end
57+
58+
def main
59+
trans = uninitialized LibAllegro::Transform
60+
event = uninitialized LibAllegro::Event
61+
bps = 4
62+
redraw = false
63+
last_timer = 0
64+
65+
abort_example("Could not init Allegro.\n") unless CrystalAllegro.init
66+
67+
open_log
68+
69+
LibAllegro.install_keyboard
70+
71+
display = self.display = LibAllegro.create_display(640, 480)
72+
abort_example("Could not create display\n") unless display
73+
74+
font = self.font = LibAllegro.create_builtin_font
75+
abort_example("Could not create font\n") unless font
76+
77+
abort_example("Could not init sound\n") unless LibAllegro.install_audio
78+
79+
if LibAllegro.reserve_samples(RESERVED_SAMPLES) == 0
80+
abort_example("Could not set up voice and mixer\n")
81+
end
82+
83+
ping = self.ping = generate_ping
84+
abort_example("Could not generate sample\n") unless ping
85+
86+
self.timer = LibAllegro.create_timer(1.0 / bps)
87+
LibAllegro.set_timer_count(timer, -1)
88+
89+
self.event_queue = LibAllegro.create_event_queue
90+
LibAllegro.register_event_source(event_queue, LibAllegro.get_keyboard_event_source)
91+
LibAllegro.register_event_source(event_queue, LibAllegro.get_timer_event_source(timer))
92+
93+
LibAllegro.identity_transform(pointerof(trans))
94+
LibAllegro.scale_transform(pointerof(trans), 16.0, 16.0)
95+
LibAllegro.use_transform(pointerof(trans))
96+
97+
LibAllegro.start_timer(timer)
98+
99+
loop do
100+
LibAllegro.wait_for_event(event_queue, pointerof(event))
101+
if event.type == LibAllegro::EventTimer
102+
speed = (21.0 / 20.0) ** (event.timer.count % PERIOD)
103+
if LibAllegro.play_sample(ping, 1.0, 0.0, speed, LibAllegro::Playmode::PlaymodeOnce, nil) == 0
104+
log_printf("Not enough reserved samples.\n")
105+
end
106+
redraw = true
107+
last_timer = event.timer.count.to_i
108+
elsif event.type == LibAllegro::EventKeyChar
109+
break if event.keyboard.keycode == LibAllegro::KeyEscape
110+
if event.keyboard.unichar == '+'.ord || event.keyboard.unichar == '='.ord
111+
if bps < 32
112+
bps += 1
113+
LibAllegro.set_timer_speed(timer, 1.0 / bps)
114+
end
115+
elsif event.keyboard.unichar == '-'.ord
116+
if bps > 1
117+
bps -= 1
118+
LibAllegro.set_timer_speed(timer, 1.0 / bps)
119+
end
120+
end
121+
end
122+
123+
if redraw && LibAllegro.is_event_queue_empty(event_queue) != 0
124+
if last_timer % PERIOD == 0
125+
c = LibAllegro.map_rgb_f(1, 1, 1)
126+
else
127+
c = LibAllegro.map_rgb_f(0.5, 0.5, 1.0)
128+
end
129+
130+
LibAllegro.clear_to_color(LibAllegro.map_rgb(0, 0, 0))
131+
LibAllegro.draw_textf(font, c, 640 / 32, 480 / 32 - 4, LibAllegro::AlignCentre,
132+
"%d", last_timer)
133+
LibAllegro.flip_display
134+
end
135+
end
136+
137+
close_log(false)
138+
end
139+
end
140+
141+
ExAudioTimer.new.main

Diff for: src/crystal_allegro.cr

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ module CrystalAllegro
55
LibAllegro.install_system(LibAllegro.get_allegro_version, nil)
66
end
77

8+
macro malloc(p)
9+
LibAllegro.malloc_with_context({{p}}, __LINE__, __FILE__, nil)
10+
end
11+
812
macro free(p)
913
LibAllegro.free_with_context({{p}}, __LINE__, __FILE__, nil)
1014
end

Diff for: src/crystal_allegro/lib_allegro.cr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1096,7 +1096,7 @@ lib LibAllegro
10961096
fun broadcast_cond = al_broadcast_cond(cond : Cond)
10971097
fun signal_cond = al_signal_cond(cond : Cond)
10981098
fun create_timer = al_create_timer(speed_secs : LibC::Double) : Timer*
1099-
alias Timer = Void
1099+
type Timer = Void
11001100
fun destroy_timer = al_destroy_timer(timer : Timer*)
11011101
fun start_timer = al_start_timer(timer : Timer*)
11021102
fun stop_timer = al_stop_timer(timer : Timer*)

0 commit comments

Comments
 (0)