Browse Source

Added VocalGame as a prototype project

* Update Cakelisp for parentheses around deref and addr, resolving
ambiguities
* Added audio output to VocalGame. I had a few false starts due to not
having my good device selected as default. The current version won't
work on any other machine because I hard-coded the audio device
pitch-detection
Macoy Madson 2 years ago
parent
commit
a150956fb5
  1. 1
      .gitignore
  2. 11
      Build_Debug.sh
  3. 2
      Dependencies/cakelisp
  4. 6
      src/SDL.cake
  5. 238
      test/src/VocalGame.cake

1
.gitignore

@ -41,6 +41,7 @@ lib/
test/ogreApp
test/output/
test/autoTest
test/VocalGame
*.blend1

11
Build_Debug.sh

@ -8,12 +8,15 @@
# ./Dependencies/cakelisp/bin/cakelisp --verbose-compile-time-build-objects src/AutoTest.cake src/SDL.cake src/Tracy.cake
echo "\n\nOgre\n\n"
./Dependencies/cakelisp/bin/cakelisp --verbose-processes test/src/OgreApp.cake || exit $?
./Dependencies/cakelisp/bin/cakelisp test/src/OgreApp.cake || exit $?
echo "\n\nSDL Ogre\n\n"
./Dependencies/cakelisp/bin/cakelisp --verbose-processes test/src/SDLOgreApp.cake || exit $?
./Dependencies/cakelisp/bin/cakelisp test/src/SDLOgreApp.cake || exit $?
echo "\n\nAuto Test\n\n"
./Dependencies/cakelisp/bin/cakelisp --verbose-processes src/AutoTest.cake src/SDL.cake src/Tracy.cake || exit $?
./Dependencies/cakelisp/bin/cakelisp src/AutoTest.cake src/SDL.cake src/Tracy.cake || exit $?
echo "\n\nVocal Game\n\n"
./Dependencies/cakelisp/bin/cakelisp test/src/VocalGame.cake || exit $?
echo "\n\nRun Vocal Game\n\n"
cd test && ./VocalGame
# echo "\n\nOgre\n\n"
# ../cakelisp/bin/cakelisp --verbose-processes test/src/OgreApp.cake

2
Dependencies/cakelisp

@ -1 +1 @@
Subproject commit 4bacdedb037aee9f23bef9029746f2b045e159cf
Subproject commit 1dba3db6cc71a9efce8ee4328f4f31a557ca03c0

6
src/SDL.cake

@ -7,14 +7,14 @@
"SDL.h"
"SDL_syswm.h")
(defun-local sdl-print-error ()
(defun sdl-print-error ()
(printf "SDL_Error: %s\n" (SDL_GetError)))
(forward-declare (struct SDL_Window))
;; I'm not sure SDL won't use OpenGL under the hood. This supports drawing using SDL functions
(defun sdl-initialize-nogl (window-out (* (* SDL_Window)) &return bool)
(when (< (SDL_Init (bit-or SDL_INIT_VIDEO SDL_INIT_TIMER)) 0)
(when (< (SDL_Init (bit-or SDL_INIT_VIDEO SDL_INIT_AUDIO SDL_INIT_TIMER)) 0)
(sdl-print-error)
(return false))
@ -30,7 +30,7 @@
;; This is the OpenGL version, which may not support SDL drawing functions, only OpenGL
(defun sdl-initialize (window-out (* (* SDL_Window)) &return bool)
(when (< (SDL_Init (bit-or SDL_INIT_VIDEO SDL_INIT_TIMER)) 0)
(when (< (SDL_Init (bit-or SDL_INIT_VIDEO SDL_INIT_AUDIO SDL_INIT_TIMER)) 0)
(sdl-print-error)
(return false))

238
test/src/VocalGame.cake

@ -0,0 +1,238 @@
(set-cakelisp-option cakelisp-src-dir "Dependencies/cakelisp/src")
(set-cakelisp-option executable-output "test/VocalGame")
(import "src/OgreCore.cake"
"src/SDL.cake")
;; TODO: Should this happen automatically, because import automatically adds current working dir?
;; Should it add working dir?
(add-c-search-directory ".")
(c-import "SDL.h" "SDL_syswm.h" "SDL_timer.h"
"<math.h>")
;; TODO: Somehow inherit this from SDL.cake?
(module-use-sdl-build-options)
(defun-local audio-callback (userdata (* void) stream (* Uint8) stream-length int)
;; (printf "Audio len %d\n" stream-length)
(static-var up bool false)
(set up (not up))
(var i int 0)
(var pi (const float) 3.14159f)
(var num-channels int 2)
(var samples-per-channel int (/ stream-length num-channels))
(while (< i stream-length)
(var mono-sample int 0)
;; Square
;; (set mono-sample (? up 255 0))
;; Triangle
;; (set mono-sample (mod (/ i 4) 255))
;; Sine
;; Map to 0-255
(set mono-sample (+ 127 (* 127
;; Map to -1 to +1
(sin
;; Map from position in buffer to 2pi range
(/ (* i 2 pi) (type-cast samples-per-channel float))))))
;; Channels are interleaved, e.g. LRLR, not LLRR
(var channel int 0)
(while (< channel num-channels)
(set (at (+ i channel) stream) mono-sample)
;; (printf "[%d][%d] %d\n" (+ i channel) channel (at i stream))
(incr channel))
(set i (+ i num-channels))))
;; Allocates both names and array
;; Returns number of devices in device-names-out
(defun-local sdl-audio-get-devices (device-names-out (* (* (* (const char))))
is-capture bool &return int)
(var num-devices int (SDL_GetNumAudioDevices is-capture))
(set (deref device-names-out) (type-cast
(calloc (sizeof (type (* (const char)))) num-devices)
(* (* (const char)))))
(printf "Available %s devices:\n" (? is-capture "recording" "playback"))
(var i int 0)
(while (< i num-devices)
(var device-name (* (const char)) (SDL_GetAudioDeviceName i is-capture))
(when device-name
(printf "\t[%d] %s\n" i device-name)
(set (at i (deref device-names-out)) (strdup device-name)))
(incr i))
(return num-devices))
(defun-local sdl-audio-free-device-list (device-names (* (* (const char))) num-devices int)
(var i int 0)
(while (< i num-devices)
(free (type-cast (at i device-names) (* void)))
(incr i))
(free device-names))
(defun-local initialize-audio (&return bool)
(scope ;; Drivers
(printf "Available drivers:\n")
(var num-drivers int (SDL_GetNumAudioDrivers))
(var i int 0)
(while (< i num-drivers)
(var driver-name (* (const char)) (SDL_GetAudioDriver i))
(when driver-name
(printf "\t[%d] %s\n" i driver-name))
(incr i))
(var audio-driver (* (const char)) (SDL_GetCurrentAudioDriver))
(unless audio-driver
(printf "No audio driver found")
(return false))
(printf "Active audio driver: %s\n" audio-driver))
(var is-capture bool false)
(var devices (* (* (const char))) null)
(var num-devices int (sdl-audio-get-devices (addr devices) is-capture))
(unless num-devices (return false))
(scope ;; Capture devices
(var capture-devices (* (* (const char))) null)
(var num-capture-devices int (sdl-audio-get-devices (addr capture-devices) true))
(unless num-capture-devices (return false))
(sdl-audio-free-device-list capture-devices num-capture-devices))
(var desired-spec SDL_AudioSpec (array 0))
(set (field desired-spec freq) 44100)
(set (field desired-spec format) AUDIO_U8)
(set (field desired-spec channels) 2) ;; 1 = Mono 2 = Stereo
;; 86 times per second. ~11ms delay (I think)
(set (field desired-spec samples) 512)
(set (field desired-spec callback) audio-callback)
(var selected-device (* (const char)) nullptr)
(var internal-device-id SDL_AudioDeviceID 0)
(var obtained-spec SDL_AudioSpec (array 0))
(scope
;; Use my HDMI output device
(var macoy-device int 2)
(unless (< macoy-device num-devices)
(sdl-audio-free-device-list devices num-devices)
(return false))
(var device-name (* (const char)) (at 2 devices))
(var valid-device-start-num (const int) 2)
(set internal-device-id (SDL_OpenAudioDevice
;; null = reasonable default (doesn't work in my case)
;; null
device-name
false ;; iscapture
(addr desired-spec) (addr obtained-spec)
(bit-or SDL_AUDIO_ALLOW_FREQUENCY_CHANGE
SDL_AUDIO_ALLOW_SAMPLES_CHANGE
SDL_AUDIO_ALLOW_CHANNELS_CHANGE)))
(if (<= internal-device-id valid-device-start-num)
(set selected-device device-name)
(sdl-print-error)))
;; Pick the first working device
;; This doesn't actually make sense for my case, where the first device does open
;; (var i int 0)
;; (while (< i num-devices)
;; (var device-name (* (const char)) (at i devices))
;; (var valid-device-start-num (const int) 2)
;; (set internal-device-id (SDL_OpenAudioDevice
;; ;; null = reasonable default (doesn't work in my case)
;; device-name
;; false ;; iscapture
;; (addr desired-spec) (addr obtained-spec)
;; (bit-or SDL_AUDIO_ALLOW_FREQUENCY_CHANGE
;; SDL_AUDIO_ALLOW_SAMPLES_CHANGE
;; SDL_AUDIO_ALLOW_CHANNELS_CHANGE)))
;; (if (>= internal-device-id
;; valid-device-start-num)
;; (block
;; (set selected-device device-name)
;; (break))
;; (block
;; (sdl-print-error)
;; (incr i))))
(when selected-device ;; print final settings
(printf "Final settings:\n")
(printf "device: %s\n" selected-device)
(printf "freq: %d\n" (field obtained-spec freq))
(printf "format: %d\n" (field obtained-spec format))
(printf "channels: %d\n" (field obtained-spec channels))
(printf "samples: %d\n" (field obtained-spec samples))
;; Start playing
;; Important note: SDL_PauseAudio works on the default device, NOT the opened one
;; This tripped me up when my audio wasn't actually getting played on my opened one
(SDL_PauseAudioDevice internal-device-id 0))
(sdl-audio-free-device-list devices num-devices)
(return selected-device))
(defun main (&return int)
(var window (* SDL_Window) null)
(unless (sdl-initialize (addr window))
(return 1))
(unless (initialize-audio)
(return 1))
;; Ogre uses exceptions for error handling, so we can't gracefully close without getting all that
;; stuff set up (which I don't really want to do; it belongs in Gamelib)
(unless (ogre-initialize-sdl)
(return 1))
(var monkey-mesh mesh-handle (ogre-load-mesh "Suzanne.mesh"))
(var monkey-node scene-node (ogre-node-from-item monkey-mesh))
(var exit-reason (* (const char)) null)
(var x float 0.f)
(var y float 0.f)
(var z float 0.f)
(var move-speed float 10.f)
(var counter-num-ticks-per-second (const Uint64) (SDL_GetPerformanceFrequency))
(var last-frame-perf-count Uint64 (* 0.016f counter-num-ticks-per-second))
;; Main loop
(while (not exit-reason)
(var event SDL_Event)
(while (SDL_PollEvent (addr event))
(when (= (field event type) SDL_QUIT)
(set exit-reason "Window closed")))
;; Note: this requires SDL_PollEvent in order to be up-to-date
(var currentKeyStates (* (const Uint8)) (SDL_GetKeyboardState null))
(when (at SDL_SCANCODE_ESCAPE currentKeyStates)
(set exit-reason "Escape pressed"))
(var delta-position ([] 3 float) (array 0))
(when (at SDL_SCANCODE_RIGHT currentKeyStates)
(set (at 0 delta-position) (+ (at 0 delta-position) move-speed)))
(when (at SDL_SCANCODE_LEFT currentKeyStates)
(set (at 0 delta-position) (- (at 0 delta-position) move-speed)))
(when (at SDL_SCANCODE_UP currentKeyStates)
(set (at 1 delta-position) (+ (at 1 delta-position) move-speed)))
(when (at SDL_SCANCODE_DOWN currentKeyStates)
(set (at 1 delta-position) (- (at 1 delta-position) move-speed)))
(var current-counter-ticks Uint64 (SDL_GetPerformanceCounter))
(var frame-diff-ticks Uint64 (- current-counter-ticks last-frame-perf-count))
(var delta-time float (/ frame-diff-ticks
(type-cast counter-num-ticks-per-second float)))
;; (printf "%lu %f\n" frame-diff-ticks delta-time)
(set x (+ x (* delta-time (at 0 delta-position))))
(set y (+ y (* delta-time (at 1 delta-position))))
(set z (+ z (* delta-time (at 2 delta-position))))
(ogre-node-set-position (addr monkey-node) x y z)
(set last-frame-perf-count (SDL_GetPerformanceCounter))
(unless (ogre-render-frame)
(set exit-reason "Failed to render frame")
(break)))
(ogre-shutdown)
(sdl-shutdown window)
(when exit-reason
(printf "Exit reason: %s\n" exit-reason))
(return 0))
Loading…
Cancel
Save