Use enum class for sound_channel

This commit is contained in:
Kp 2022-12-17 13:16:28 +00:00
parent 57a9c384e8
commit 5f39ffc2f5
8 changed files with 177 additions and 117 deletions

View file

@ -14,6 +14,7 @@
#ifdef dsx
namespace dcx {
enum class sound_pan : int;
enum class sound_channel : uint8_t;
struct sound_object;
constexpr std::integral_constant<int, 16> digi_max_channels{};
}
@ -21,12 +22,12 @@ namespace dsx {
int digi_audio_init();
void digi_audio_close();
void digi_audio_stop_all_channels();
int digi_audio_start_sound(short, fix, sound_pan, int, int, int, sound_object *);
int digi_audio_is_channel_playing(int );
void digi_audio_set_channel_volume(int, int);
void digi_audio_set_channel_pan(int, sound_pan);
void digi_audio_stop_sound(int );
void digi_audio_end_sound(int );
sound_channel digi_audio_start_sound(short, fix, sound_pan, int, int, int, sound_object *);
int digi_audio_is_channel_playing(sound_channel);
void digi_audio_set_channel_volume(sound_channel, int);
void digi_audio_set_channel_pan(sound_channel, sound_pan);
void digi_audio_stop_sound(sound_channel);
void digi_audio_end_sound(sound_channel);
void digi_audio_set_digi_volume(int);
}
#endif

View file

@ -15,17 +15,17 @@ namespace dcx {
enum class sound_pan : int;
struct sound_object;
void digi_mixer_close();
void digi_mixer_set_channel_volume(int, int);
void digi_mixer_set_channel_pan(int, sound_pan);
void digi_mixer_stop_sound(int);
void digi_mixer_end_sound(int);
void digi_mixer_set_channel_volume(sound_channel, int);
void digi_mixer_set_channel_pan(sound_channel, sound_pan);
void digi_mixer_stop_sound(sound_channel);
void digi_mixer_end_sound(sound_channel);
void digi_mixer_set_digi_volume(int);
int digi_mixer_is_channel_playing(int);
int digi_mixer_is_channel_playing(sound_channel);
void digi_mixer_stop_all_channels();
}
namespace dsx {
int digi_mixer_init();
int digi_mixer_start_sound(short, fix, sound_pan, int, int, int, sound_object *);
sound_channel digi_mixer_start_sound(short, fix, sound_pan, int, int, int, sound_object *);
}
#endif

View file

@ -19,6 +19,7 @@ class enumerated_bitset : std::bitset<N>
using base_type = std::bitset<N>;
public:
using base_type::base_type;
using base_type::size;
constexpr typename base_type::reference operator[](E position)
{
return this->base_type::operator[](static_cast<std::size_t>(position));
@ -27,6 +28,18 @@ public:
{
return this->base_type::operator[](static_cast<std::size_t>(position));
}
enumerated_bitset &reset()
{
return static_cast<enumerated_bitset &>(this->base_type::reset());
}
enumerated_bitset &reset(E position)
{
return static_cast<enumerated_bitset &>(this->base_type::reset(static_cast<std::size_t>(position)));
}
enumerated_bitset &set(E position)
{
return static_cast<enumerated_bitset &>(this->base_type::set(static_cast<std::size_t>(position)));
}
[[nodiscard]]
static constexpr bool valid_index(std::size_t s)
{

View file

@ -40,7 +40,15 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
#ifdef dsx
namespace dcx {
enum class sound_pan : int;
enum class sound_pan : int
{
};
enum class sound_channel : uint8_t
{
None = UINT8_MAX,
};
struct sound_object;
extern int digi_volume;
@ -135,7 +143,10 @@ struct digi_sound
}
};
extern sound_channel SoundQ_channel;
}
namespace dsx {
extern int digi_init();
@ -166,21 +177,21 @@ extern void digi_resume_digi_sounds();
extern int digi_xlat_sound(int soundno);
extern void digi_stop_sound( int channel );
void digi_stop_sound(sound_channel channel);
// Volume 0-F1_0
constexpr sound_object *sound_object_none = nullptr;
int digi_start_sound(short soundnum, fix volume, sound_pan pan, int looping, int loop_start, int loop_end, sound_object *);
sound_channel digi_start_sound(short soundnum, fix volume, sound_pan pan, int looping, int loop_start, int loop_end, sound_object *);
// Stops all sounds that are playing
void digi_stop_all_channels();
void digi_stop_digi_sounds();
extern void digi_end_sound( int channel );
void digi_set_channel_pan(int channel, sound_pan pan);
extern void digi_set_channel_volume( int channel, int volume );
extern int digi_is_channel_playing(int channel);
void digi_end_sound(sound_channel channel);
void digi_set_channel_pan(sound_channel channel, sound_pan pan);
void digi_set_channel_volume(sound_channel channel, int volume);
int digi_is_channel_playing(sound_channel channel);
extern void digi_play_sample_looping( int soundno, fix max_volume,int loop_start, int loop_end );
extern void digi_change_looping_volume( fix volume );
@ -211,7 +222,6 @@ extern void digi_start_sound_queued( short soundnum, fix volume );
extern int digi_sample_rate;
#endif
extern int Dont_start_sound_objects;
extern int SoundQ_channel;
void digi_select_system();
#ifdef _WIN32
@ -225,7 +235,7 @@ void digi_win32_stop_midi_song();
void digi_end_soundobj(sound_object &);
void SoundQ_end();
#ifndef NDEBUG
int verify_sound_channel_free( int channel );
void verify_sound_channel_free(sound_channel channel);
#endif
}
@ -234,9 +244,9 @@ namespace dsx {
class RAIIdigi_sound
{
static constexpr auto invalid_channel = std::integral_constant<int, -1>{};
int channel = invalid_channel;
static void stop(int channel)
static constexpr std::integral_constant<sound_channel, sound_channel::None> invalid_channel{};
sound_channel channel = invalid_channel;
static void stop(const sound_channel channel)
{
if (channel != invalid_channel)
digi_stop_sound(channel);
@ -246,7 +256,7 @@ public:
{
stop(channel);
}
void reset(int c = invalid_channel)
void reset(const sound_channel c = invalid_channel)
{
stop(std::exchange(channel, c));
}

View file

@ -66,12 +66,12 @@ struct sound_function_table_t
{
int (*init)();
void (*close)();
void (*set_channel_volume)(int, int);
void (*set_channel_pan)(int, sound_pan);
int (*start_sound)(short, fix, sound_pan, int, int, int, sound_object *);
void (*stop_sound)(int);
void (*end_sound)(int);
int (*is_channel_playing)(int);
void (*set_channel_volume)(sound_channel, int);
void (*set_channel_pan)(sound_channel, sound_pan);
sound_channel (*start_sound)(short, fix, sound_pan, int, int, int, sound_object *);
void (*stop_sound)(sound_channel);
void (*end_sound)(sound_channel);
int (*is_channel_playing)(sound_channel);
void (*stop_all_channels)();
void (*set_digi_volume)(int);
};
@ -224,18 +224,36 @@ int digi_init()
void digi_close() { fptr->close(); }
void digi_set_channel_volume(int channel, int volume) { fptr->set_channel_volume(channel, volume); }
void digi_set_channel_pan(const int channel, const sound_pan pan) { fptr->set_channel_pan(channel, pan); }
void digi_set_channel_volume(const sound_channel channel, int volume)
{
fptr->set_channel_volume(channel, volume);
}
int digi_start_sound(const short soundnum, const fix volume, const sound_pan pan, const int looping, const int loop_start, const int loop_end, sound_object *const soundobj)
void digi_set_channel_pan(const sound_channel channel, const sound_pan pan)
{
fptr->set_channel_pan(channel, pan);
}
sound_channel digi_start_sound(const short soundnum, const fix volume, const sound_pan pan, const int looping, const int loop_start, const int loop_end, sound_object *const soundobj)
{
return fptr->start_sound(soundnum, volume, pan, looping, loop_start, loop_end, soundobj);
}
void digi_stop_sound(int channel) { fptr->stop_sound(channel); }
void digi_end_sound(int channel) { fptr->end_sound(channel); }
void digi_stop_sound(const sound_channel channel)
{
fptr->stop_sound(channel);
}
void digi_end_sound(const sound_channel channel)
{
fptr->end_sound(channel);
}
int digi_is_channel_playing(const sound_channel channel)
{
return fptr->is_channel_playing(channel);
}
int digi_is_channel_playing(int channel) { return fptr->is_channel_playing(channel); }
void digi_stop_all_channels() { fptr->stop_all_channels(); }
void digi_set_digi_volume(int dvolume) { fptr->set_digi_volume(dvolume); }

View file

@ -26,6 +26,7 @@
#include "piggy.h"
#include "compiler-range_for.h"
#include "d_underlying_value.h"
namespace dcx {
@ -115,9 +116,18 @@ static void digi_audio_stop_sound(sound_slot &s)
s.persistent = 0;
}
static std::array<sound_slot, 32> SoundSlots;
static enumerated_array<sound_slot, 32, sound_channel> SoundSlots;
static SDL_AudioSpec WaveSpec;
static int next_channel;
static sound_channel next_channel;
/* Return the next sound_channel after `c`, and roll back to 0 if incrementing
* `c` exceeds the maximum available channels.
*/
static sound_channel next(const sound_channel c)
{
const std::underlying_type<sound_channel>::type v = underlying_value(c) + 1;
return (v >= digi_max_channels) ? sound_channel{} : sound_channel{v};
}
}
@ -234,17 +244,17 @@ void digi_audio_stop_all_channels()
// Volume 0-F1_0
int digi_audio_start_sound(short soundnum, fix volume, sound_pan pan, int looping, int, int, sound_object *const soundobj)
sound_channel digi_audio_start_sound(short soundnum, fix volume, sound_pan pan, int looping, int, int, sound_object *const soundobj)
{
int i, starting_channel;
if (!digi_initialised)
return sound_channel::None;
if (!digi_initialised) return -1;
if (soundnum < 0) return -1;
if (soundnum < 0)
return sound_channel::None;
SDL_LockAudio();
starting_channel = next_channel;
const auto starting_channel = next_channel;
while(1)
{
@ -254,13 +264,11 @@ int digi_audio_start_sound(short soundnum, fix volume, sound_pan pan, int loopin
if (!SoundSlots[next_channel].persistent)
break; // use this channel!
next_channel++;
if (next_channel >= digi_max_channels)
next_channel = 0;
next_channel = next(next_channel);
if (next_channel == starting_channel)
{
SDL_UnlockAudio();
return -1;
return sound_channel::None;
}
}
if (SoundSlots[next_channel].playing)
@ -290,11 +298,8 @@ int digi_audio_start_sound(short soundnum, fix volume, sound_pan pan, int loopin
if (soundobj || looping || volume > F1_0)
SoundSlots[next_channel].persistent = 1;
i = next_channel;
next_channel++;
if (next_channel >= digi_max_channels)
next_channel = 0;
const auto i = next_channel;
next_channel = next(next_channel);
SDL_UnlockAudio();
return i;
@ -317,7 +322,7 @@ void digi_audio_set_digi_volume( int dvolume )
}
//end edit by adb
int digi_audio_is_channel_playing(int channel)
int digi_audio_is_channel_playing(const sound_channel channel)
{
if (!digi_initialised)
return 0;
@ -325,7 +330,7 @@ int digi_audio_is_channel_playing(int channel)
return SoundSlots[channel].playing;
}
void digi_audio_set_channel_volume(int channel, int volume)
void digi_audio_set_channel_volume(const sound_channel channel, int volume)
{
if (!digi_initialised)
return;
@ -336,7 +341,7 @@ void digi_audio_set_channel_volume(int channel, int volume)
SoundSlots[channel].volume = fixmuldiv(volume, digi_volume, F1_0);
}
void digi_audio_set_channel_pan(int channel, const sound_pan pan)
void digi_audio_set_channel_pan(const sound_channel channel, const sound_pan pan)
{
if (!digi_initialised)
return;
@ -347,12 +352,12 @@ void digi_audio_set_channel_pan(int channel, const sound_pan pan)
SoundSlots[channel].pan = pan;
}
void digi_audio_stop_sound(int channel)
void digi_audio_stop_sound(const sound_channel channel)
{
digi_audio_stop_sound(SoundSlots[channel]);
}
void digi_audio_end_sound(int channel)
void digi_audio_end_sound(const sound_channel channel)
{
if (!digi_initialised)
return;

View file

@ -38,7 +38,9 @@
#include "piggy.h"
#include "u_mem.h"
#include <memory>
#include "d_bitset.h"
#include "d_range.h"
#include "d_underlying_value.h"
#define MIX_DIGI_DEBUG 0
#define MIX_OUTPUT_FORMAT AUDIO_S16
@ -85,14 +87,16 @@ public:
std::span<const T> span() const && = delete;
};
enumerated_bitset<64, sound_channel> channels;
/* channel management */
static unsigned digi_mixer_find_channel(const std::bitset<64> &channels, const unsigned max_channels)
static sound_channel digi_mixer_find_channel(const enumerated_bitset<64, sound_channel> &channels, const unsigned max_channels)
{
unsigned i = 0;
uint8_t i{};
for (; i < max_channels; ++i)
if (!channels[i])
if (!channels[(sound_channel{i})])
break;
return i;
return sound_channel{i};
}
struct RAIIMix_Chunk : public Mix_Chunk
@ -118,12 +122,12 @@ static uint8_t fix2byte(const fix f)
}
uint8_t digi_initialised;
std::bitset<64> channels;
unsigned digi_mixer_max_channels = channels.size();
unsigned digi_mixer_max_channels = std::size(channels);
void digi_mixer_free_channel(const int channel_num)
{
channels.reset(channel_num);
if (const std::size_t u = channel_num; channels.valid_index(u))
channels.reset(static_cast<sound_channel>(channel_num));
}
}
@ -346,19 +350,21 @@ static void mixdigi_convert_sound(const unsigned i)
}
// Volume 0-F1_0
int digi_mixer_start_sound(short soundnum, const fix volume, const sound_pan pan, const int looping, const int loop_start, const int loop_end, sound_object *)
sound_channel digi_mixer_start_sound(short soundnum, const fix volume, const sound_pan pan, const int looping, const int loop_start, const int loop_end, sound_object *)
{
if (!digi_initialised) return -1;
if (!digi_initialised)
return sound_channel::None;
if (soundnum < 0)
return -1;
return sound_channel::None;
const unsigned max_channels = digi_mixer_max_channels;
if (max_channels > channels.size())
return -1;
const auto channel = digi_mixer_find_channel(channels, max_channels);
return sound_channel::None;
const auto c = digi_mixer_find_channel(channels, max_channels);
const auto channel = underlying_value(c);
if (channel >= max_channels)
return -1;
return sound_channel::None;
mixdigi_convert_sound(soundnum);
@ -374,37 +380,38 @@ int digi_mixer_start_sound(short soundnum, const fix volume, const sound_pan pan
Mix_PlayChannel(channel, &(SoundChunks[soundnum]), mix_loop);
Mix_SetPanning(channel, 255-mix_pan, mix_pan);
Mix_SetDistance(channel, UINT8_MAX - fix2byte(volume));
channels.set(channel);
return channel;
channels.set(c);
return c;
}
}
namespace dcx {
void digi_mixer_set_channel_volume(int channel, int volume)
void digi_mixer_set_channel_volume(const sound_channel channel, const int volume)
{
if (!digi_initialised) return;
Mix_SetDistance(channel, UINT8_MAX - fix2byte(volume));
Mix_SetDistance(underlying_value(channel), UINT8_MAX - fix2byte(volume));
}
void digi_mixer_set_channel_pan(int channel, const sound_pan pan)
void digi_mixer_set_channel_pan(const sound_channel channel, const sound_pan pan)
{
int mix_pan = fix2byte(static_cast<fix>(pan));
Mix_SetPanning(channel, 255-mix_pan, mix_pan);
Mix_SetPanning(underlying_value(channel), 255 - mix_pan, mix_pan);
}
void digi_mixer_stop_sound(int channel) {
void digi_mixer_stop_sound(const sound_channel channel)
{
if (!digi_initialised) return;
const auto c = underlying_value(channel);
#if MIX_DIGI_DEBUG
con_printf(CON_DEBUG, "digi_stop_sound %d", channel);
con_printf(CON_DEBUG, "%s:%u: %d", __FUNCTION__, __LINE__, c);
#endif
Mix_HaltChannel(channel);
Mix_HaltChannel(c);
channels.reset(channel);
}
void digi_mixer_end_sound(int channel)
void digi_mixer_end_sound(const sound_channel channel)
{
digi_mixer_stop_sound(channel);
channels.reset(channel);
@ -417,7 +424,7 @@ void digi_mixer_set_digi_volume( int dvolume )
Mix_Volume(-1, fix2byte(dvolume));
}
int digi_mixer_is_channel_playing(const int c)
int digi_mixer_is_channel_playing(const sound_channel c)
{
return channels[c];
}

View file

@ -63,6 +63,8 @@ constexpr std::integral_constant<unsigned, 150> MAX_SOUND_OBJECTS{};
}
sound_channel SoundQ_channel;
struct sound_object
{
short signature; // A unique signature to this sound
@ -72,7 +74,7 @@ struct sound_object
vm_distance max_distance; // The max distance that this sound can be heard at...
int volume; // Volume that this sound is playing at
sound_pan pan; // Pan value that this sound is playing at
int channel; // What channel this is playing on, -1 if not playing
sound_channel channel; // What channel this is playing on, sound_channel::None if not playing
short soundnum; // The sound number that is playing
int loop_start; // The start point of the loop. -1 means no loop
int loop_end; // The end point of the loop
@ -104,9 +106,10 @@ static int N_active_sound_objects;
static void digi_kill_sound(sound_object &s)
{
s.flags = 0; // Mark as dead, so some other sound can use this sound
if (s.channel > -1) {
if (s.channel != sound_channel::None)
{
N_active_sound_objects--;
digi_stop_sound(std::exchange(s.channel, -1));
digi_stop_sound(std::exchange(s.channel, sound_channel::None));
}
}
@ -286,7 +289,7 @@ void digi_init_sounds()
digi_stop_looping_sound();
range_for (auto &i, SoundObjects)
{
i.channel = -1;
i.channel = sound_channel::None;
i.flags = 0; // Mark as dead, so some other sound can use this sound
}
N_active_sound_objects = 0;
@ -304,7 +307,7 @@ static int digi_looping_sound = -1;
static int digi_looping_volume;
static int digi_looping_start = -1;
static int digi_looping_end = -1;
static int digi_looping_channel = -1;
static sound_channel digi_looping_channel = sound_channel::None;
static void digi_play_sample_looping_sub()
{
@ -320,7 +323,7 @@ void digi_play_sample_looping( int soundno, fix max_volume,int loop_start, int l
if (soundno < 0 ) return;
if (digi_looping_channel>-1)
if (digi_looping_channel != sound_channel::None)
digi_stop_sound( digi_looping_channel );
digi_looping_sound = soundno;
@ -333,7 +336,7 @@ void digi_play_sample_looping( int soundno, fix max_volume,int loop_start, int l
void digi_change_looping_volume( fix volume )
{
digi_looping_volume = volume;
if ( digi_looping_channel > -1 )
if (digi_looping_channel != sound_channel::None)
digi_set_channel_volume( digi_looping_channel, volume );
}
@ -342,9 +345,9 @@ namespace {
static void digi_pause_looping_sound()
{
const auto c = digi_looping_channel;
if (c > -1)
if (c != sound_channel::None)
{
digi_looping_channel = -1;
digi_looping_channel = sound_channel::None;
digi_stop_sound(c);
}
}
@ -374,7 +377,7 @@ namespace {
static void digi_start_sound_object(sound_object &s)
{
// start sample structures
s.channel = -1;
s.channel = sound_channel::None;
if ( s.volume <= 0 )
return;
@ -395,7 +398,7 @@ static void digi_start_sound_object(sound_object &s)
s.loop_start,
s.loop_end, &s);
if (s.channel > -1 )
if (s.channel != sound_channel::None)
N_active_sound_objects++;
}
@ -411,7 +414,7 @@ static void digi_link_sound_common(const object_base &viewer, sound_object &so,
so.pan = {};
if (Dont_start_sound_objects) { //started at level start
so.flags |= SOF_PERMANENT;
so.channel = -1;
so.channel = sound_channel::None;
}
else
{
@ -419,7 +422,8 @@ static void digi_link_sound_common(const object_base &viewer, sound_object &so,
digi_start_sound_object(so);
// If it's a one-shot sound effect, and it can't start right away, then
// just cancel it and be done with it.
if ( (so.channel < 0) && (!(so.flags & SOF_PLAY_FOREVER)) ) {
if (so.channel == sound_channel::None && !(so.flags & SOF_PLAY_FOREVER))
{
so.flags = 0;
return;
}
@ -604,7 +608,8 @@ void digi_sync_sounds()
if ( !(s.flags & SOF_PLAY_FOREVER) ) {
// Check if its done.
if (s.channel > -1 ) {
if (s.channel != sound_channel::None)
{
if ( !digi_is_channel_playing(s.channel) ) {
digi_end_sound( s.channel );
s.flags = 0; // Mark as dead, so some other sound can use this sound
@ -628,7 +633,8 @@ void digi_sync_sounds()
if ((objp.type==OBJ_NONE) || (objp.signature!=s.link_type.obj.objsignature)) {
// The object that this is linked to is dead, so just end this sound if it is looping.
if ( s.channel>-1 ) {
if (s.channel != sound_channel::None)
{
if (s.flags & SOF_PLAY_FOREVER)
digi_stop_sound( s.channel );
else
@ -647,9 +653,9 @@ void digi_sync_sounds()
// Sound is too far away, so stop it from playing.
const auto c = s.channel;
if (c > -1)
if (c != sound_channel::None)
{
s.channel = -1;
s.channel = sound_channel::None;
if (s.flags & SOF_PLAY_FOREVER)
digi_stop_sound(c);
else
@ -663,7 +669,8 @@ void digi_sync_sounds()
}
} else {
if (s.channel<0) {
if (s.channel == sound_channel::None)
{
digi_start_sound_object(s);
} else {
digi_set_channel_volume( s.channel, s.volume );
@ -672,7 +679,7 @@ void digi_sync_sounds()
}
if (oldpan != s.pan) {
if (s.channel>-1)
if (s.channel != sound_channel::None)
digi_set_channel_pan( s.channel, s.pan );
}
@ -688,9 +695,9 @@ void digi_pause_digi_sounds()
if (!(s.flags & SOF_USED))
continue;
const auto c = s.channel;
if (c > -1)
if (c != sound_channel::None)
{
s.channel = -1;
s.channel = sound_channel::None;
if (! (s.flags & SOF_PLAY_FOREVER))
s.flags = 0; // Mark as dead, so some other sound can use this sound
N_active_sound_objects--;
@ -713,10 +720,10 @@ void digi_resume_digi_sounds()
void digi_end_soundobj(sound_object &s)
{
Assert(s.flags & SOF_USED);
Assert(s.channel > -1);
assert(s.channel != sound_channel::None);
N_active_sound_objects--;
s.channel = -1;
s.channel = sound_channel::None;
}
void digi_stop_digi_sounds()
@ -726,7 +733,8 @@ void digi_stop_digi_sounds()
{
if (s.flags & SOF_USED)
{
if ( s.channel > -1 ) {
if (s.channel != sound_channel::None)
{
digi_stop_sound( s.channel );
N_active_sound_objects--;
}
@ -739,19 +747,16 @@ void digi_stop_digi_sounds()
}
#ifndef NDEBUG
int verify_sound_channel_free( int channel )
void verify_sound_channel_free(const sound_channel channel)
{
const auto predicate = [channel](const sound_object &s) {
return (s.flags & SOF_USED) && s.channel == channel;
};
if (std::any_of(SoundObjects.begin(), SoundObjects.end(), predicate))
throw std::runtime_error("sound busy");
return 0;
}
#endif
int SoundQ_channel;
namespace {
struct sound_q
@ -768,12 +773,12 @@ void SoundQ_init()
{
SoundQ_head = SoundQ_tail = 0;
SoundQ_num = 0;
SoundQ_channel = -1;
SoundQ_channel = sound_channel::None;
}
void SoundQ_pause()
{
SoundQ_channel = -1;
SoundQ_channel = sound_channel::None;
}
}
@ -785,15 +790,16 @@ void SoundQ_end()
if (SoundQ_head >= SoundQ.size())
SoundQ_head = 0;
SoundQ_num--;
SoundQ_channel = -1;
SoundQ_channel = sound_channel::None;
}
namespace {
void SoundQ_process()
{
if ( SoundQ_channel > -1 ) {
if ( digi_is_channel_playing(SoundQ_channel) )
if (const auto channel = SoundQ_channel; channel != sound_channel::None)
{
if (digi_is_channel_playing(channel))
return;
SoundQ_end();
}