Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sound effects do not play without music on OSX. #4

Open
evanrinehart opened this issue Feb 4, 2015 · 9 comments
Open

Sound effects do not play without music on OSX. #4

evanrinehart opened this issue Feb 4, 2015 · 9 comments
Assignees
Labels

Comments

@evanrinehart
Copy link
Owner

This appears to be a combination of bugs in the OSX sound driver (see FILL_BUFFER macro) and in MikMod's main handling of pausing.

@evanrinehart evanrinehart self-assigned this Feb 4, 2015
@evanrinehart
Copy link
Owner Author

This issue can be reproduced by simply trying to run the sound effect examples from MikMod's documentation. They don't play sound. The reason is the following macro in drivers/drv_osx.c

124 #define FILL_BUFFER(_buffer,_size)                \
125       if (Player_Paused()) {              \
126         MUTEX_LOCK (vars);            \
127         VC_SilenceBytes ((SBYTE*) (_buffer), (ULONG) (_size));    \
128         MUTEX_UNLOCK (vars);            \
129       }                 \
130       else {                  \
131         MUTEX_LOCK (vars);            \
132         VC_WriteBytes ((SBYTE*) (_buffer), (ULONG) ((_size)));    \
133         MUTEX_UNLOCK (vars);            \
134       }

What's happening here is... OSX uses an audio callback instead of relying on polling MikMod_Update. OSX_Update, called by MikMod_Update when not paused, is a no-op. MikMod_Update is completely unnecessary to use on OSX, but doesn't hurt either.

Since OSX_Update doesn't do anything anyway, avoiding it during a pause doesn't have the effect of pausing sound. Therefore this hack in the fill code for the fill thread / core audio callback.

Checking if removing the silence case is a possible solution. Which means understanding how the song is being played in the first place on OSX.

@evanrinehart
Copy link
Owner Author

The example program attempts to play the samples, which will set their voices to kick=1, but they will not start playing until virtch runs (VC_WriteSamples) and reacts to this kick and sets active=1 (kick=0). Since no song is loaded and Player_Paused is true, the samples aren't playing, and the example exits immediately.

@evanrinehart
Copy link
Owner Author

If we remove the silence case of fill buffer, then as long as output is enabled (MikMod_EnableOutput) sound effects will work. The music will either play or not depending on the pause flag seen here in Player_HandleTick, called by virtch.

if ((!pf)||(pf->forbid)||(pf->sngpos>=pf->numpos)) return;

The only issue left would be hanging notes if you pause the song while it is playing. In another patch I fix this by simply silencing all music voices in Player_Pause. And so the OSX driver doesn't need to worry about pausing, it just needs to worry about outputting sound while sound is enabled.

@evanrinehart
Copy link
Owner Author

Checking what this does, the example indeed plays the first sound effect until the second one starts. However there is some delay between activating a sample and when Voice_Stopped reports 0, allowing the do-while to work. So it stops as soon as it hits the second sample instead of playing the second sample to the end.

@evanrinehart
Copy link
Owner Author

Putting a single extra usleep(10000) after playing the second sample makes the example work as intended. It plays both samples and exits. Next I will check that I can play, pause, and unpause music while these sound effects occur...

@evanrinehart
Copy link
Owner Author

And it works as expected. Of course Player_TogglePause and Player_Stop will cause stuck notes. The latter was a bug before I started working on this so isn't my fault! Nonetheless both problems are fixed in two other patches.

Here is the patch for the OSX issue

From ee22a703777be097738c834fd78d019d9e76021f Mon Sep 17 00:00:00 2001
From: EvanR <evanrinehart@gmail.com>
Date: Wed, 4 Feb 2015 17:37:01 -0600
Subject: [PATCH] Fix sound without music on OSX.

On OSX MikMod_Update has no role in regulating paused music, because it
doesn't do anything. Instead, the audio callback drives the sound by
calling to virtch, which drives the music player and the other sounds,
and then taking virtch's output and feeding it to core audio. In this
FILL_BUFFER macro it reacts to the paused state (which is true when no
song is loaded) by filling the output with silence instead. Not only
does this stop the advancement of the song, it "pauses" sound effects
too.

However if you remove that check from the FILL_BUFFER macro, pausing
of music still works, because md_player (Player_HandleTick) makes a
check to the pause flag as well. Sound effects work normally and the
music pauses. They are independent.

This change causes two issues, both of which are fixed in other
patches. 1) If you pause music, it will cause stuck notes. This is
solved by stopping all music voices in the function
Player_TogglePause_internal. 2) If you stop the music (Player_Stop) then
it will also cause stuck notes, but that was happening even without this
patch. This is an existing bug and is fixed the same way, in another
patch.
---
 drivers/drv_osx.c | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/drivers/drv_osx.c b/drivers/drv_osx.c
index 65adb5d..ca82960 100644
--- a/drivers/drv_osx.c
+++ b/drivers/drv_osx.c
@@ -122,12 +122,7 @@
            }

 #define FILL_BUFFER(_buffer,_size)                             \
-           if (Player_Paused()) {                          \
-               MUTEX_LOCK (vars);                      \
-               VC_SilenceBytes ((SBYTE*) (_buffer), (ULONG) (_size));      \
-               MUTEX_UNLOCK (vars);                        \
-           }                                   \
-           else {                                  \
+           {                                   \
                MUTEX_LOCK (vars);                      \
                VC_WriteBytes ((SBYTE*) (_buffer), (ULONG) ((_size)));      \
                MUTEX_UNLOCK (vars);                        \
-- 
1.8.3.4 (Apple Git-47)


@evanrinehart
Copy link
Owner Author

I should say that anyone trying to actually run the MikMod sound effect examples in the documentation should turn down the usleep numbers (on not OSX) because usleep(100000) is way too slow to play many samples found online. Again this doesn't make a difference on OSX except to determine how long the loops will take, they have no other effect.

@evanrinehart evanrinehart changed the title Sound effects do not play without music on OSX Sound effects do not play without music on OSX. Feb 5, 2015
@nfd
Copy link

nfd commented Jul 6, 2017

Thanks for tracking this down. I notice this still seems broken on OS X with the official release (though FILL_BUFFER has changed in the intervening time). Did the mikmod maintainer have any comments on your patch?

@evanrinehart
Copy link
Owner Author

evanrinehart commented Jul 7, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants