diff --git a/playdate_example/src/playdate_example.nim b/playdate_example/src/playdate_example.nim index 99c4ec7..c068a0b 100644 --- a/playdate_example/src/playdate_example.nim +++ b/playdate_example/src/playdate_example.nim @@ -3,6 +3,10 @@ import playdate/api const FONT_PATH = "/System/Fonts/Asheville-Sans-14-Bold.pft" const NIM_IMAGE_PATH = "/images/nim_logo" const PLAYDATE_NIM_IMAGE_PATH = "/images/playdate_nim" +const BACKGROUND_MUSIC_PATH = "/audio/finally_see_the_light" +const BACKGROUND_MUSIC_SAMPLE_RATE = 48_000 +const BACKGROUND_MUSIC_FADE_IN_SECONDS = 4.0 +const BACKGROUND_MUSIC_FADE_IN_SAMPLES = (BACKGROUND_MUSIC_SAMPLE_RATE * BACKGROUND_MUSIC_FADE_IN_SECONDS).int32 var font: LCDFont @@ -80,9 +84,11 @@ proc handler(event: PDSystemEvent, keycode: uint) {.raises: [].} = except: playdate.system.logToConsole(getCurrentExceptionMsg()) # Inline try/except - filePlayer = try: playdate.sound.newFilePlayer("/audio/finally_see_the_light") except: nil + filePlayer = try: playdate.sound.newFilePlayer(BACKGROUND_MUSIC_PATH) except: nil filePlayer.play(0) + fileplayer.volume = 0.0 # first set folume to 0% + filePlayer.fadeVolume(1.0, 1.0, BACKGROUND_MUSIC_FADE_IN_SAMPLES, nil) # then fade to 100% # Add a checkmark menu item that plays a sound when switched and unpaused discard playdate.system.addCheckmarkMenuItem("Checkmark", false, diff --git a/src/playdate/bindings/sound.nim b/src/playdate/bindings/sound.nim index 9edaabd..f9081a1 100644 --- a/src/playdate/bindings/sound.nim +++ b/src/playdate/bindings/sound.nim @@ -38,15 +38,15 @@ type PlaydateSoundFileplayer {.importc: "const struct playdate_sound_fileplayer" # start: cfloat; `end`: cfloat) {.cdecl.} # didUnderrun* {.importc: "didUnderrun".}: proc (player: ptr FilePlayer): cint {.cdecl.} setFinishCallback* {.importc: "setFinishCallback".}: proc ( - player: FilePlayerPtr; callback: PDSndCallbackProcRaw, userData: pointer = nil) {.cdecl, raises: [].} + player: FilePlayerPtr; callback: PDSndCallbackProcRaw, userdata: pointer = nil) {.cdecl, raises: [].} # setLoopCallback* {.importc: "setLoopCallback".}: proc (player: ptr FilePlayer; # callback: SndCallbackProc) {.cdecl.} getOffset {.importc: "getOffset".}: proc (player: FilePlayerPtr): cfloat {.cdecl, raises: [].} # getRate* {.importc: "getRate".}: proc (player: ptr FilePlayer): cfloat {.cdecl.} # setStopOnUnderrun* {.importc: "setStopOnUnderrun".}: proc ( # player: ptr FilePlayer; flag: cint) {.cdecl.} - # fadeVolume* {.importc: "fadeVolume".}: proc (player: ptr FilePlayer; left: cfloat; - # right: cfloat; len: int32T; finishCallback: SndCallbackProc) {.cdecl.} + fadeVolume* {.importc: "fadeVolume".}: proc (player: FilePlayerPtr; left: cfloat; + right: cfloat; len: cint; finishCallback: PDSndCallbackProcRaw, userdata: pointer = nil) {.cdecl, raises:[].} # setMP3StreamSource* {.importc: "setMP3StreamSource".}: proc ( # player: ptr FilePlayer; dataSource: proc (data: ptr uint8T; bytes: cint; # userdata: pointer): cint {.cdecl.}; userdata: pointer; bufferLen: cfloat) {. @@ -90,7 +90,7 @@ type PlaydateSoundSampleplayer {.importc: "const struct playdate_sound_samplepla setPlayRange* {.importc: "setPlayRange".}: proc (player: SamplePlayerPtr; start: cint; `end`: cint) {.cdecl, raises: [].} setFinishCallback* {.importc: "setFinishCallback".}: proc ( - player: SamplePlayerPtr; callback: PDSndCallbackProcRaw, userData: pointer = nil) {.cdecl, raises: [].} + player: SamplePlayerPtr; callback: PDSndCallbackProcRaw, userdata: pointer = nil) {.cdecl, raises: [].} # setLoopCallback* {.importc: "setLoopCallback".}: proc (player: ptr SamplePlayer; # callback: SndCallbackProc) {.cdecl.} getOffset* {.importc: "getOffset".}: proc (player: SamplePlayerPtr): cfloat {.cdecl , raises: [].} diff --git a/src/playdate/sound.nim b/src/playdate/sound.nim index 90cde0a..4293184 100644 --- a/src/playdate/sound.nim +++ b/src/playdate/sound.nim @@ -16,7 +16,7 @@ type resource: AudioSamplePtr AudioSample* = ref AudioSampleObj - PDSoundCallbackFunction* = proc(userData: pointer) {.raises: [].} + PDSoundCallbackFunction* = proc(userdata: pointer) {.raises: [].} proc `=destroy`(this: var AudioSampleObj) = privateAccess(PlaydateSound) @@ -55,6 +55,7 @@ type SoundSource* = ref SoundSourceObj type FilePlayerObj = object of SoundSourceObj finishCallback: PDFilePlayerCallbackFunction + fadeVolumeCallback: PDFilePlayerCallbackFunction FilePlayer* = ref FilePlayerObj PDFilePlayerCallbackFunction* = proc(player: FilePlayer) {.raises: [].} @@ -139,6 +140,11 @@ proc privateFilePlayerFinishCallback(soundSource: SoundSourcePtr, userdata: poin if filePlayer.finishCallback != nil: filePlayer.finishCallback(filePlayer) +proc privateFilePlayerFadeVolumeCallback(soundSource: SoundSourcePtr, userdata: pointer) {.cdecl, raises: [].} = + let filePlayer = cast[FilePlayer](userdata) + if filePlayer.fadeVolumeCallback != nil: + filePlayer.fadeVolumeCallback(filePlayer) + proc setFinishCallback*(this: FilePlayer, callback: PDFilePlayerCallbackFunction) = privateAccess(PlaydateSound) privateAccess(PlaydateSoundFileplayer) @@ -148,6 +154,15 @@ proc setFinishCallback*(this: FilePlayer, callback: PDFilePlayerCallbackFunction else: playdate.sound.fileplayer.setFinishCallback(this.resource, privateFilePlayerFinishCallback, cast[pointer](this)) +proc fadeVolume*(this: FilePlayer, left, right: float32, len: int32, callback: PDFilePlayerCallbackFunction) = + privateAccess(PlaydateSound) + privateAccess(PlaydateSoundFileplayer) + this.fadeVolumeCallback = callback + if callback == nil: + playdate.sound.fileplayer.fadeVolume(this.resource, left.cfloat, right.cfloat, len.cint , nil, nil) + else: + playdate.sound.fileplayer.fadeVolume(this.resource, left.cfloat, right.cfloat, len.cint , privateFilePlayerFadeVolumeCallback, cast[pointer](this)) + proc finishCallback*(this: FilePlayer): PDFilePlayerCallbackFunction = return this.finishCallback