#include "std.h"
#include <io.h>
#include <fcntl.h>
#include <sys/stat.h>
#include "emul.h"
#include "vars.h"
#include "bass.h"
#include "snd_bass.h"
#include "gshle.h"
#include "gs.h"
#include "init.h"
#include "util.h"
#ifdef MOD_GSBASS
//=============================================================================
void GSHLE::reportError(const char *err, bool fatal)
{
color(CONSCLR_ERROR);
printf("BASS library reports error in %s\n", err);
color(CONSCLR_ERRCODE);
printf("error code is 0x%04X\n", BASS::ErrorGetCode());
//-------------------------------------------------------------------------
if (fatal)
{
exit();
}
//-------------------------------------------------------------------------
}
//=============================================================================
//=============================================================================
void GSHLE::runBASS()
{
//-------------------------------------------------------------------------
if (BASS::Initialized)
return;
//-------------------------------------------------------------------------
if (BASS::Init(-1, conf.sound.fq, BASS_DEVICE_LATENCY, wnd, nullptr))
{
DWORD len = BASS::GetConfig(BASS_CONFIG_UPDATEPERIOD);
BASS_INFO info;
BASS::GetInfo(&info);
BASS::SetConfig(BASS_CONFIG_BUFFER, len + info.minbuf);
color(CONSCLR_HARDITEM);
printf("BASS device latency is ");
color(CONSCLR_HARDINFO);
printf("%lums\n", len + info.minbuf);
}
//-------------------------------------------------------------------------
else
{
color(CONSCLR_WARNING);
reportError("warning: can't use default BASS device, trying silence\n", false);
//---------------------------------------------------------------------
if (!BASS::Init(-2, 11025, 0, wnd, nullptr))
errexit("can't init BASS");
//---------------------------------------------------------------------
}
//-------------------------------------------------------------------------
BASS::Initialized = true;
hmod = 0;
//-------------------------------------------------------------------------
for (int ch = 0; ch < 4; ch++)
chan[ch].bass_ch = 0;
//-------------------------------------------------------------------------
DebugCh.bass_ch = 0;
}
//=============================================================================
//=============================================================================
void GSHLE::reset_sound()
{
// runBASS();
// BASS_Stop(); // todo: move to silent state?
}
//=============================================================================
DWORD CALLBACK gs_render(HSTREAM handle, void *buffer, DWORD length, void *user);
//=============================================================================
void GSHLE::initChannels()
{
//-------------------------------------------------------------------------
if (chan[0].bass_ch)
return;
//-------------------------------------------------------------------------
for (int ch = 0; ch < 4; ch++)
{
chan[ch].bass_ch = BASS::StreamCreate(conf.sound.fq, 1, BASS_SAMPLE_8BITS, gs_render, &chan[ch]);
//---------------------------------------------------------------------
if (!chan[ch].bass_ch)
reportError("BASS_StreamCreate()");
//---------------------------------------------------------------------
}
//-------------------------------------------------------------------------
DebugCh.bass_ch = BASS::StreamCreate(conf.sound.fq, 1, BASS_SAMPLE_8BITS, gs_render, &DebugCh);
//-------------------------------------------------------------------------
if (!DebugCh.bass_ch)
reportError("BASS_StreamCreate()");
//-------------------------------------------------------------------------
}
//=============================================================================
//=============================================================================
void GSHLE::setmodvol(unsigned vol)
{
//-------------------------------------------------------------------------
if (!hmod)
return;
//-------------------------------------------------------------------------
runBASS();
float v = (int(vol) * conf.sound.bass_vol) / float(8192 * 64);
assert(v <= 1.0f);
//-------------------------------------------------------------------------
if (!BASS::ChannelSetAttribute(hmod, BASS_ATTRIB_VOL, v))
reportError("BASS_ChannelSetAttribute() [music volume]");
//-------------------------------------------------------------------------
}
//=============================================================================
//=============================================================================
void GSHLE::SetModSpeed()
{
// ╘єэъЎш эх юЄырцхэр, эхшчтхёЄэю т ъръшї яЁюуЁрььрї фрээр ъюьрэфр шёяюы№чєхЄё
//-------------------------------------------------------------------------
if (!hmod)
return;
//-------------------------------------------------------------------------
runBASS();
// printf("%s, speed=%u\n", __FUNCTION__, speed);
//-------------------------------------------------------------------------
if (!BASS::ChannelSetAttribute(hmod, BASS_ATTRIB_MUSIC_SPEED, speed))
reportError("BASS_ChannelSetAttribute() [music speed]");
//-------------------------------------------------------------------------
}
//=============================================================================
//=============================================================================
void GSHLE::init_mod()
{
runBASS();
//-------------------------------------------------------------------------
if (hmod)
BASS::MusicFree(hmod);
//-------------------------------------------------------------------------
hmod = 0;
hmod = BASS::MusicLoad(1, mod, 0, modsize, BASS_MUSIC_LOOP | BASS_MUSIC_POSRESET | BASS_MUSIC_RAMP, 0);
//-------------------------------------------------------------------------
if (!hmod)
reportError("BASS_MusicLoad()", false);
//-------------------------------------------------------------------------
setmodvol(modvol); // ╙ёЄрэютър эрўры№эющ уЁюьъюёЄш
}
//=============================================================================
//=============================================================================
void GSHLE::restart_mod(unsigned order, unsigned row)
{
//-------------------------------------------------------------------------
if (!hmod)
return;
//-------------------------------------------------------------------------
SetModSpeed();
//-------------------------------------------------------------------------
if (!BASS::ChannelSetPosition(hmod, QWORD(MAKELONG(order,row)), BASS_POS_MUSIC_ORDER))
reportError("BASS_ChannelSetPosition() [music]");
//-------------------------------------------------------------------------
if (!BASS::ChannelFlags(hmod, BASS_MUSIC_LOOP | BASS_MUSIC_POSRESET | BASS_MUSIC_RAMP, -1U))
reportError("BASS_ChannelFlags() [music]");
//-------------------------------------------------------------------------
BASS::Start();
//-------------------------------------------------------------------------
if (!BASS::ChannelPlay(hmod, FALSE/*TRUE*/))
reportError("BASS_ChannelPlay() [music]"); //molodcov_alex 0.36.2
//-------------------------------------------------------------------------
mod_playing = 1;
}
//=============================================================================
//=============================================================================
void GSHLE::resetmod()
{
//-------------------------------------------------------------------------
if (hmod)
BASS::MusicFree(hmod);
//-------------------------------------------------------------------------
hmod = 0;
}
//=============================================================================
//=============================================================================
void GSHLE::resetfx()
{
runBASS();
//-------------------------------------------------------------------------
for (int i = 0; i < 4; i++)
{
if (chan[i].bass_ch)
{
BASS::StreamFree(chan[i].bass_ch);
chan[i].bass_ch = 0;
}
}
//-------------------------------------------------------------------------
}
//=============================================================================
//=============================================================================
DWORD GSHLE::modgetpos()
{
runBASS();
return (DWORD)BASS::ChannelGetPosition(hmod, BASS_POS_MUSIC_ORDER);
// return BASS_MusicGetOrderPosition(hmod);
}
//=============================================================================
//=============================================================================
void GSHLE::stop_mod()
{
runBASS();
//-------------------------------------------------------------------------
if (!hmod)
return;
//-------------------------------------------------------------------------
if (BASS::ChannelIsActive(hmod) != BASS_ACTIVE_PLAYING)
return;
//-------------------------------------------------------------------------
if (!BASS::ChannelPause(hmod))
reportError("BASS_ChannelPause() [music]");
}
//=============================================================================
//=============================================================================
void GSHLE::pause_mod() // [NS]
{
BASS::Pause();
// їч тююс∙х ўЄю ¤Єю чр ю°шсъш
//-------------------------------------------------------------------------
if (!hmod)
return;
//-------------------------------------------------------------------------
if (BASS::ChannelIsActive(hmod) != BASS_ACTIVE_PLAYING)
return;
//-------------------------------------------------------------------------
// if (!BASS::ChannelPause(hmod))
// reportError("BASS_ChannelPause() [music]");
}
//=============================================================================
void GSHLE::play_mod() // [NS]
{ // фюыцхэ эртхЁэю эрч√трЄёю resume_mod !!!!
BASS::Start();
// їч тююс∙х ўЄю ¤Єю чр ю°шсъш
//-------------------------------------------------------------------------
if (!hmod)
return;
//-------------------------------------------------------------------------
if (BASS::ChannelIsActive(hmod) != BASS_ACTIVE_PLAYING)
return;
//-------------------------------------------------------------------------
// if (!BASS::ChannelPause(hmod))
// reportError("BASS_ChannelPause() [music]");
}
//=============================================================================
//=============================================================================
void GSHLE::cont_mod()
{
runBASS();
//-------------------------------------------------------------------------
if (!hmod)
return;
//-------------------------------------------------------------------------
if (!BASS::ChannelPlay(hmod, TRUE))
reportError("BASS_ChannelPlay() [music]");
//-------------------------------------------------------------------------
}
//=============================================================================
//=============================================================================
void GSHLE::startfx(CHANNEL *ch, float pan)
{
initChannels();
float vol = (int(ch->volume) * conf.sound.gs_vol) / float(8192*64);
assert(vol <= 1.0f);
//-------------------------------------------------------------------------
if (BASS::ChannelIsActive(ch->bass_ch) == BASS_ACTIVE_PLAYING)
{
if (!BASS::ChannelStop(ch->bass_ch))
reportError("BASS_ChannelStop()");
}
//-------------------------------------------------------------------------
if (!BASS::ChannelSetAttribute(ch->bass_ch, BASS_ATTRIB_VOL, vol))
reportError("BASS_ChannelSetAttribute() [vol]");
//-------------------------------------------------------------------------
if (!BASS::ChannelSetAttribute(ch->bass_ch, BASS_ATTRIB_FREQ, ch->freq))
reportError("BASS_ChannelSetAttribute() [freq]");
//-------------------------------------------------------------------------
if (!BASS::ChannelSetAttribute(ch->bass_ch, BASS_ATTRIB_PAN, pan))
reportError("BASS_ChannelSetAttribute() [pan]");
//-------------------------------------------------------------------------
{ // Єръ ш фюыцэю с√Є№????
DWORD len = BASS::GetConfig(BASS_CONFIG_UPDATEPERIOD);
BASS_INFO info;
BASS::GetInfo(&info);
BASS::SetConfig(BASS_CONFIG_BUFFER, len + info.minbuf);
}
//-------------------------------------------------------------------------
if (!BASS::ChannelPlay(ch->bass_ch, FALSE))
reportError("BASS_ChannelPlay()");
//-------------------------------------------------------------------------
}
//=============================================================================
//=============================================================================
void GSHLE::flush_gs_frame()
{
unsigned lvl;
//-------------------------------------------------------------------------
if (!hmod || (lvl = BASS::ChannelGetLevel(hmod)) == -1U)
lvl = 0;
//-------------------------------------------------------------------------
gsleds[0].level = LOWORD(lvl) >> (15-4);
gsleds[0].attrib = 0x0D;
gsleds[1].level = HIWORD(lvl) >> (15-4);
gsleds[1].attrib = 0x0D;
//-------------------------------------------------------------------------
for (int ch = 0; ch < 4; ch++)
{
//---------------------------------------------------------------------
if (chan[ch].bass_ch && (lvl = BASS::ChannelGetLevel(chan[ch].bass_ch)) != -1U)
{
lvl = max(HIWORD(lvl), LOWORD(lvl));
lvl >>= (15-4);
}
//---------------------------------------------------------------------
else
{
lvl = 0;
}
//---------------------------------------------------------------------
gsleds[ch+2].level = lvl;
gsleds[ch+2].attrib = 0x0F;
}
//---------------------------------------------------------------------
}
//=============================================================================
//=============================================================================
void GSHLE::debug_note(unsigned i)
{
//-------------------------------------------------------------------------
if (BASS::ChannelIsActive(DebugCh.bass_ch) == BASS_ACTIVE_PLAYING)
{
if (!BASS::ChannelStop(DebugCh.bass_ch))
{
reportError("BASS_ChannelStop()");
}
}
//-------------------------------------------------------------------------
DebugCh.volume = sample[i].volume;
DebugCh.ptr = 0;
DebugCh.start = sample[i].start;
DebugCh.loop = sample[i].loop;
DebugCh.end = sample[i].end;
unsigned note = sample[i].note;
DebugCh.freq = note2rate[note];
startfx(&DebugCh, 0);
}
//=============================================================================
//=============================================================================
void GSHLE::debug_save_note(unsigned i, const char *FileName)
{
int f = open(FileName, O_CREAT | O_TRUNC | O_BINARY | O_WRONLY, S_IREAD | S_IWRITE);
//-------------------------------------------------------------------------
if (f >= 0)
{
write(f, sample[i].start, sample[i].end);
close(f);
}
//-------------------------------------------------------------------------
}
//=============================================================================
//=============================================================================
void GSHLE::debug_save_mod(const char *FileName)
{
int f = open(FileName, O_CREAT | O_TRUNC | O_BINARY | O_WRONLY, S_IREAD | S_IWRITE);
//-------------------------------------------------------------------------
if (f >= 0)
{
write(f, mod, modsize);
close(f);
}
//-------------------------------------------------------------------------
}
//=============================================================================
#endif