From 534677086a1336c727261504ba75a7e169305532 Mon Sep 17 00:00:00 2001 From: David Thompson Date: Tue, 24 Jan 2017 21:26:10 -0500 Subject: Add audio support. * chickadee/audio.scm: New file. * Makefile.am (SOURCES): Add it. * chickadee.scm (run-game): Initialize audio. * doc/api.texi ("Audio"): Document it. --- Makefile.am | 1 + chickadee.scm | 1 + chickadee/audio.scm | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++++ doc/api.texi | 61 +++++++++++++++++++++- 4 files changed, 206 insertions(+), 1 deletion(-) create mode 100644 chickadee/audio.scm diff --git a/Makefile.am b/Makefile.am index 8e65d44..2e320c5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -41,6 +41,7 @@ godir=$(libdir)/guile/$(GUILE_EFFECTIVE_VERSION)/ccache SOURCES = \ chickadee/config.scm \ chickadee/utils.scm \ + chickadee/audio.scm \ chickadee/input/controller.scm \ chickadee/math.scm \ chickadee/math/vector.scm \ diff --git a/chickadee.scm b/chickadee.scm index fdf253e..c872f85 100644 --- a/chickadee.scm +++ b/chickadee.scm @@ -79,6 +79,7 @@ window-fullscreen? (update-hz 60)) (sdl-init) + ((@@ (chickadee audio) enable-audio)) (start-text-input) (let ((window (open-window #:title window-title #:width window-width diff --git a/chickadee/audio.scm b/chickadee/audio.scm new file mode 100644 index 0000000..d92ae94 --- /dev/null +++ b/chickadee/audio.scm @@ -0,0 +1,144 @@ +;;; Chickadee Game Toolkit +;;; Copyright © 2017 David Thompson +;;; +;;; Chickadee is free software: you can redistribute it and/or modify +;;; it under the terms of the GNU General Public License as published +;;; by the Free Software Foundation, either version 3 of the License, +;;; or (at your option) any later version. +;;; +;;; Chickadee is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;;; General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with this program. If not, see +;;; . + +;;; Commentary: +;; +;; Sound effects and music. +;; +;;; Code: + +(define-module (chickadee audio) + #:use-module (ice-9 format) + #:use-module (srfi srfi-9) + #:use-module (srfi srfi-9 gnu) + #:use-module ((sdl2 mixer) #:prefix sdl2:) + #:export (load-sample + sample? + sample-audio + set-sample-volume! + play-sample + load-music + music? + music-audio + music-volume + play-music + set-music-volume! + pause-music + resume-music + rewind-music + stop-music + music-paused? + music-playing?)) + +(define (enable-audio) + ;; The SDL mixer will throw an exception if it cannot initialize a + ;; particular audio format. We don't want this to be fatal, so we + ;; ignore it. + (false-if-exception (sdl2:mixer-init)) + (sdl2:open-audio)) + +;; Used to wrap SDL audio functions whose return values should be +;; ignored. +(define-syntax-rule (ignore-value body ...) + (begin + body ... + *unspecified*)) + +;; Wrapper over SDL audio objects. +(define-record-type + (make-sample audio) + sample? + (audio sample-audio)) + +(define (display-sample sample port) + (format port "#" (object-address sample))) + +(set-record-type-printer! display-sample) + +(define (load-sample file) + "Load audio sample from FILE." + (let ((audio (sdl2:load-chunk file))) + (if audio + (make-sample audio) + (error "cannot load audio sample:" file)))) + +(define (set-sample-volume! volume) + "Set the volume that all samples are played at to VOLUME, an integer +value between 0 and 128." + (ignore-value (sdl2:set-channel-volume! #f volume))) + +(define (play-sample sample) + "Play SAMPLE." + (ignore-value + ;; An exception will be thrown if too many samples are being played + ;; at once, but it can be safely ignored. + (false-if-exception + (sdl2:play-chunk! (sample-audio sample))))) + +;; Wrapper over SDL music objects. +(define-record-type + (make-music audio) + music? + (audio music-audio)) + +(define (display-music music port) + (format port "#" (object-address music))) + +(set-record-type-printer! display-music) + +(define (load-music file) + "Load music from FILE." + (make-music (sdl2:load-music file))) + +(define (music-volume) + "Return the volume level for music, an integer value between 0 and +128." + (sdl2:music-volume)) + +(define (set-music-volume! volume) + "Set the volume that music is played at to VOLUME, an integer value +between 0 and 128." + (ignore-value (sdl2:set-music-volume! volume))) + +(define* (play-music music #:key loop?) + "Play MUSIC. If LOOP?, play it over and over and over and over +and..." + (sdl2:play-music! (music-audio music) (if loop? #f 1))) + +(define (pause-music) + "Pause the current music track." + (sdl2:pause-music!)) + +(define (resume-music) + "Resume the current music track." + (sdl2:resume-music!)) + +(define (rewind-music) + "Restart the current music track from the beginning." + (sdl2:rewind-music!)) + +(define (stop-music) + "Stop playing the current music track." + (sdl2:stop-music!)) + +(define (music-playing?) + "Return #t if music is currently playing." + (sdl2:music-playing?)) + +(define (music-paused?) + "Return #t if music is currently paused." + (sdl2:music-paused?)) diff --git a/doc/api.texi b/doc/api.texi index 554b531..d72980a 100644 --- a/doc/api.texi +++ b/doc/api.texi @@ -732,4 +732,63 @@ considered an advanced feature. @node Audio @section Audio -There is no audio support yet. Stay tuned! +Chickadee has two data types for audio: samples and music. Samples +are for short sound effects like explosions. Music is for, well, +uh@dots{}, music. + +Supported file formats include WAV and OGG. + +@deffn {Scheme Procedure} load-sample @var{file} +Load audio sample from @var{file}. +@end deffn + +@deffn {Scheme Procedure} set-sample-volume! @var{volume} +Set the volume that all samples are played at to @var{volume}, an +integer value between 0 and 128. +@end deffn + +@deffn {Scheme Procedure} play-sample @var{sample} +Play @var{sample}. Pretty straightforward! +@end deffn + +@deffn {Scheme Procedure} load-music @var{file} +Load music from @var{file}. +@end deffn + +@deffn {Scheme Procedure} music-volume +Return the volume level for music, an integer value between 0 and 128. +@end deffn + +@deffn {Scheme Procedure} set-music-volume! @var{volume} +Set the volume that music is played at to @var{volume}, an integer +value between 0 and 128. +@end deffn + +@deffn {Scheme Procedure} play-music @var{music} [@var{loop?}] +Play @var{music}. If @var{loop?}, play it over and over and over and +over and@dots{} +@end deffn + +@deffn {Scheme Procedure} pause-music +Pause the current music track. +@end deffn + +@deffn {Scheme Procedure} resume-music +Resume the current music track. +@end deffn + +@deffn {Scheme Procedure} rewind-music +estart the current music track from the beginning. +@end deffn + +@deffn {Scheme Procedure} stop-music +Stop playing the current music track. +@end deffn + +@deffn {Scheme Procedure} music-playing? +Return @code{#t} if music is currently playing. +@end deffn + +@deffn {Scheme Procedure} music-paused? +Return @code{#t} if music is currently paused. +@end deffn -- cgit v1.2.3