|
| 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 |
0 commit comments