Import existing source tree; original VCS history is no longer available. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
227 lines
5.0 KiB
C
227 lines
5.0 KiB
C
/*(LGPL)
|
|
---------------------------------------------------------------------------
|
|
a_commands.c - Asynchronous Command Interface for the audio engine
|
|
---------------------------------------------------------------------------
|
|
* Copyright (C) 2001-2003, 2007 David Olofson
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation; either version 2.1 of the License, or (at
|
|
* your option) any later version.
|
|
*
|
|
* This program 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
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "kobolog.h"
|
|
#include "a_globals.h"
|
|
|
|
/*
|
|
* These really shouldn't be here, but are
|
|
* required for some shortcuts around here...
|
|
*/
|
|
#include "a_struct.h"
|
|
#include "a_sequencer.h"
|
|
#include "a_control.h"
|
|
|
|
#undef DBG2D
|
|
|
|
sfifo_t commands;
|
|
|
|
static inline void __push_command(command_t *cmd)
|
|
{
|
|
if(sfifo_space(&commands) < sizeof(command_t))
|
|
{
|
|
if(_audio_running)
|
|
log_printf(WLOG, "Audio command FIFO overflow!\n");
|
|
return;
|
|
}
|
|
sfifo_write(&commands, cmd, (unsigned)sizeof(command_t));
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------
|
|
Mixer Control
|
|
----------------------------------------------------------*/
|
|
void audio_bus_controlf(unsigned bus, unsigned slot, unsigned ctl, float arg)
|
|
{
|
|
audio_bus_control(bus, slot, ctl, (int)(arg * 65536.0));
|
|
}
|
|
|
|
void audio_bus_control(unsigned bus, unsigned slot, unsigned ctl, int arg)
|
|
{
|
|
command_t cmd;
|
|
#ifdef AUDIO_SAFE
|
|
if(bus >= AUDIO_MAX_BUSSES)
|
|
{
|
|
log_printf(ELOG, "audio_bus_control(): Bus out of range!\n");
|
|
return;
|
|
}
|
|
if(ctl >= ABC_COUNT)
|
|
{
|
|
log_printf(ELOG, "audio_bus_control(): Control out of range!\n");
|
|
return;
|
|
}
|
|
#endif
|
|
cmd.action = CMD_MCONTROL;
|
|
cmd.cid = (signed char)bus;
|
|
cmd.index = ctl;
|
|
cmd.arg1 = (int)slot;
|
|
cmd.arg2 = arg;
|
|
__push_command(&cmd);
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------
|
|
Group Control
|
|
----------------------------------------------------------*/
|
|
|
|
void audio_group_stop(unsigned gid)
|
|
{
|
|
int i;
|
|
#ifdef AUDIO_SAFE
|
|
if(gid >= AUDIO_MAX_GROUPS)
|
|
{
|
|
log_printf(ELOG, "audio_group_stop(): Group out of range!\n");
|
|
return;
|
|
}
|
|
#endif
|
|
/*
|
|
FIXME: This isn't exactly thread safe...
|
|
*/
|
|
for(i = 0; i < AUDIO_MAX_VOICES; i++)
|
|
{
|
|
audio_channel_t *c;
|
|
audio_voice_t *v = voicetab + i;
|
|
if(VS_STOPPED == v->state)
|
|
continue;
|
|
c = v->channel;
|
|
if((unsigned)c->ctl[ACC_GROUP] == gid)
|
|
audio_channel_stop(i, -1);
|
|
}
|
|
}
|
|
|
|
void audio_group_controlf(unsigned gid, unsigned ctl, float arg)
|
|
{
|
|
audio_group_control(gid, ctl, (int)(arg * 65536.0));
|
|
}
|
|
|
|
void audio_group_control(unsigned gid, unsigned ctl, int arg)
|
|
{
|
|
command_t cmd;
|
|
#ifdef AUDIO_SAFE
|
|
if(gid >= AUDIO_MAX_GROUPS)
|
|
{
|
|
log_printf(ELOG, "audio_group_control(): Group out of range!\n");
|
|
return;
|
|
}
|
|
if(ctl >= ACC_COUNT)
|
|
{
|
|
log_printf(ELOG, "audio_group_control(): Control out of range!\n");
|
|
return;
|
|
}
|
|
#endif
|
|
cmd.action = CMD_GCONTROL;
|
|
cmd.cid = (char)gid;
|
|
cmd.index = ctl;
|
|
cmd.arg1 = arg;
|
|
__push_command(&cmd);
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------
|
|
Channel Control
|
|
----------------------------------------------------------*/
|
|
|
|
void audio_channel_play(int cid, int tag, int pitch, int velocity)
|
|
{
|
|
command_t cmd;
|
|
#ifdef AUDIO_SAFE
|
|
if(cid < 0 || cid >= AUDIO_MAX_CHANNELS)
|
|
{
|
|
log_printf(ELOG, "audio_play(): Channel out of range!\n");
|
|
return;
|
|
}
|
|
#endif
|
|
cmd.action = CMD_PLAY;
|
|
cmd.cid = cid;
|
|
cmd.tag = tag;
|
|
cmd.arg1 = pitch;
|
|
cmd.arg2 = velocity;
|
|
__push_command(&cmd);
|
|
}
|
|
|
|
|
|
void audio_channel_controlf(int cid, int tag, int ctl, float arg)
|
|
{
|
|
if(ACC_IS_FIXEDPOINT(ctl))
|
|
arg *= 65536.0;
|
|
audio_channel_control(cid, tag, ctl, (int)arg);
|
|
}
|
|
|
|
void audio_channel_control(int cid, int tag, int ctl, int arg)
|
|
{
|
|
command_t cmd;
|
|
#ifdef AUDIO_SAFE
|
|
if(cid < 0 || cid >= AUDIO_MAX_CHANNELS)
|
|
{
|
|
log_printf(ELOG, "audio_channel_control(): Channel out of range!\n");
|
|
return;
|
|
}
|
|
if(ctl < 0 || ctl >= ACC_COUNT)
|
|
{
|
|
log_printf(ELOG, "audio_channel_control(): Control out of range!\n");
|
|
return;
|
|
}
|
|
#endif
|
|
cmd.action = CMD_CCONTROL;
|
|
cmd.cid = cid;
|
|
cmd.tag = tag;
|
|
cmd.index = (unsigned char)ctl;
|
|
cmd.arg1 = arg;
|
|
__push_command(&cmd);
|
|
}
|
|
|
|
|
|
void audio_channel_stop(int cid, int tag)
|
|
{
|
|
command_t cmd;
|
|
#ifdef AUDIO_SAFE
|
|
if(cid >= AUDIO_MAX_CHANNELS)
|
|
{
|
|
log_printf(ELOG, "audio_stop(): Channel out of range!\n");
|
|
return;
|
|
}
|
|
#endif
|
|
if(cid >= 0)
|
|
cmd.action = CMD_STOP;
|
|
else
|
|
cmd.action = CMD_STOP_ALL;
|
|
cmd.cid = cid;
|
|
cmd.tag = tag;
|
|
__push_command(&cmd);
|
|
}
|
|
|
|
|
|
int audio_channel_playing(int cid)
|
|
{
|
|
return channeltab[cid].playing;
|
|
}
|
|
|
|
|
|
void audio_bump(unsigned ms)
|
|
{
|
|
command_t cmd;
|
|
cmd.action = CMD_WAIT;
|
|
cmd.arg1 = (int)ms;
|
|
__push_command(&cmd);
|
|
}
|