Browse Source

Made a primitive looping pedal

Hold space to record, then release to play back the recording. This
was a good way to test the input device.
pitch-detection
Macoy Madson 1 year ago
parent
commit
68d2e72ddb
  1. 176
      test/src/VocalGame.cake

176
test/src/VocalGame.cake

@ -2,7 +2,8 @@
(set-cakelisp-option executable-output "test/VocalGame")
(import "src/OgreCore.cake"
"src/SDL.cake")
"src/SDL.cake"
&comptime-only "Dependencies/cakelisp/runtime/Macros.cake")
;; TODO: Should this happen automatically, because import automatically adds current working dir?
;; Should it add working dir?
(add-c-search-directory ".")
@ -12,7 +13,12 @@
;; TODO: Somehow inherit this from SDL.cake?
(module-use-sdl-build-options)
(defun-local audio-callback (userdata (* void) stream (* Uint8) stream-length int)
(var audio-is-recording bool false)
(var audio-input-buffer ([] 44100 Uint8) (array 0))
(var audio-input-write-head int 0)
(var audio-input-read-head int 0)
(defun-local audio-output-callback (userdata (* void) stream (* Uint8) stream-length int)
;; (printf "Audio len %d\n" stream-length)
(static-var up bool false)
(set up (not up))
@ -21,18 +27,25 @@
(var num-channels int 2)
(var samples-per-channel int (/ stream-length num-channels))
(while (< i stream-length)
(var mono-sample int 0)
(var mono-sample int 127)
;; 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))))))
;; (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))))))
(if audio-is-recording
(set mono-sample 127) ;; Silence
(block ;; Else, play the recording
(var recording-index int (+ (/ i num-channels) audio-input-read-head))
(set recording-index (mod recording-index (array-size audio-input-buffer)))
(set mono-sample (at recording-index audio-input-buffer))))
;; Channels are interleaved, e.g. LRLR, not LLRR
(var channel int 0)
@ -40,7 +53,23 @@
(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))))
(set i (+ i num-channels)))
(set audio-input-read-head (mod (+ audio-input-read-head samples-per-channel) (array-size audio-input-buffer))))
(defun-local audio-input-callback (userdata (* void) stream (* Uint8) stream-length int)
(unless audio-is-recording
(return))
;; (printf "received audio %d %d %d\n"
;; (at 0 stream)
;; (at (/ stream-length 2) stream)
;; (at (- stream-length 1) stream))
(var i int 0)
(while (< i stream-length)
(set (at audio-input-write-head audio-input-buffer) (at i stream))
(if (= audio-input-write-head (- (array-size audio-input-buffer) 1))
(set audio-input-write-head 0)
(incr audio-input-write-head))
(incr i)))
;; Allocates both names and array
;; Returns number of devices in device-names-out
@ -60,6 +89,12 @@
(incr i))
(return num-devices))
(defun-local sdl-audio-list-specification (spec (* SDL_AudioSpec))
(printf "freq: %d\n" (path spec > freq))
(printf "format: %d\n" (path spec > format))
(printf "channels: %d\n" (path spec > channels))
(printf "samples: %d\n" (path spec > samples)))
(defun-local sdl-audio-free-device-list (device-names (* (* (const char))) num-devices int)
(var i int 0)
(while (< i num-devices)
@ -67,7 +102,8 @@
(incr i))
(free device-names))
(defun-local initialize-audio (&return bool)
(defun-local initialize-audio (output-device-out (* SDL_AudioDeviceID)
input-device-out (* SDL_AudioDeviceID) &return bool)
(scope ;; Drivers
(printf "Available drivers:\n")
(var num-drivers int (SDL_GetNumAudioDrivers))
@ -89,24 +125,17 @@
(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
(var selected-output-device (* (const char)) nullptr)
(var output-device-id SDL_AudioDeviceID 0)
(var obtained-output-spec SDL_AudioSpec (array 0))
(scope ;; Output device
(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-output-callback)
;; Use my HDMI output device
(var macoy-device int 2)
(unless (< macoy-device num-devices)
@ -115,26 +144,71 @@
(var device-name (* (const char)) (at 2 devices))
(var valid-device-start-num (const int) 2)
(set internal-device-id (SDL_OpenAudioDevice
(set output-device-id (SDL_OpenAudioDevice
;; null = reasonable default (doesn't work in my case)
;; null
device-name
false ;; iscapture
(addr desired-spec) (addr obtained-spec)
(addr desired-spec) (addr obtained-output-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)
(if (>= output-device-id valid-device-start-num)
(set selected-output-device device-name)
(sdl-print-error)))
(var selected-input-device (* (const char)) nullptr)
(var obtained-input-spec SDL_AudioSpec (array 0))
(var input-device-id SDL_AudioDeviceID 0)
(scope ;; input device
(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) 1) ;; 1 = Mono 2 = Stereo
;; 86 times per second. ~11ms delay (I think)
(set (field desired-spec samples) 512)
(set (field desired-spec callback) audio-input-callback)
(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))
;; Use my USB webcam
(var macoy-device int 2)
(unless (< macoy-device num-capture-devices)
(sdl-audio-free-device-list capture-devices num-capture-devices)
(return false))
(var device-name (* (const char)) (at 2 capture-devices))
(var valid-device-start-num (const int) 2)
(set input-device-id (SDL_OpenAudioDevice
;; null = reasonable default (doesn't work in my case)
device-name
true ;; iscapture
(addr desired-spec) (addr obtained-input-spec)
(bit-or SDL_AUDIO_ALLOW_FREQUENCY_CHANGE
SDL_AUDIO_ALLOW_SAMPLES_CHANGE
SDL_AUDIO_ALLOW_CHANNELS_CHANGE)))
(when (< input-device-id valid-device-start-num)
(sdl-print-error))
(set selected-input-device device-name)
(when selected-input-device ;; print final settings
(printf "Final input settings:\n")
(printf "device: %s\n" selected-input-device)
(sdl-audio-list-specification (addr obtained-input-spec))
;; 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 input-device-id 0))
(sdl-audio-free-device-list capture-devices num-capture-devices))
;; 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
;; (set output-device-id (SDL_OpenAudioDevice
;; ;; null = reasonable default (doesn't work in my case)
;; device-name
;; false ;; iscapture
@ -142,7 +216,7 @@
;; (bit-or SDL_AUDIO_ALLOW_FREQUENCY_CHANGE
;; SDL_AUDIO_ALLOW_SAMPLES_CHANGE
;; SDL_AUDIO_ALLOW_CHANNELS_CHANGE)))
;; (if (>= internal-device-id
;; (if (>= output-device-id
;; valid-device-start-num)
;; (block
;; (set selected-device device-name)
@ -151,27 +225,30 @@
;; (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))
(when selected-output-device ;; print final settings
(printf "Final output settings:\n")
(printf "device: %s\n" selected-output-device)
(sdl-audio-list-specification (addr obtained-output-spec))
;; 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_PauseAudioDevice output-device-id 0))
(sdl-audio-free-device-list devices num-devices)
(return selected-device))
(when output-device-out (set (deref output-device-out) output-device-id))
(when input-device-out (set (deref input-device-out) input-device-id))
(return (and output-device-id input-device-id)))
(defun main (&return int)
(var window (* SDL_Window) null)
(unless (sdl-initialize (addr window))
(return 1))
(unless (initialize-audio)
(var output-device SDL_AudioDeviceID 0)
(var input-device SDL_AudioDeviceID 0)
(unless (initialize-audio (addr output-device) (addr input-device))
(return 1))
;; Ogre uses exceptions for error handling, so we can't gracefully close without getting all that
@ -184,7 +261,7 @@
(var exit-reason (* (const char)) null)
(var x float 0.f)
(var x float -10.f)
(var y float 0.f)
(var z float 0.f)
(var move-speed float 10.f)
@ -214,16 +291,21 @@
(when (at SDL_SCANCODE_DOWN currentKeyStates)
(set (at 1 delta-position) (- (at 1 delta-position) move-speed)))
(set audio-is-recording (at SDL_SCANCODE_SPACE currentKeyStates))
(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)
(var read-head float (* 20.f
(/ audio-input-read-head
(type-cast (array-size audio-input-buffer) float))))
(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)
(ogre-node-set-position (addr monkey-node) (+ read-head x) y z)
(set last-frame-perf-count (SDL_GetPerformanceCounter))

Loading…
Cancel
Save