Rewrote sound and audio handling, implemented driveclick
WIP, performance is still slower
This commit is contained in:
parent
71a5994822
commit
cce84daaf8
30 changed files with 3416 additions and 923 deletions
|
@ -114,7 +114,7 @@
|
|||
<GenerateCtrlBreakInsteadOfCtrlC>false</GenerateCtrlBreakInsteadOfCtrlC>
|
||||
<SuppressArgumentVariablesCheck>false</SuppressArgumentVariablesCheck>
|
||||
<DeploymentTargetPath>/home/pi/projects/amiberry/$(TargetFileName)</DeploymentTargetPath>
|
||||
<X11WindowMode>Local</X11WindowMode>
|
||||
<X11WindowMode>Remote</X11WindowMode>
|
||||
<KeepConsoleAfterExit>false</KeepConsoleAfterExit>
|
||||
<RunGDBUnderSudo>false</RunGDBUnderSudo>
|
||||
<DeploymentMode>Auto</DeploymentMode>
|
||||
|
|
|
@ -114,7 +114,7 @@
|
|||
<GenerateCtrlBreakInsteadOfCtrlC>false</GenerateCtrlBreakInsteadOfCtrlC>
|
||||
<SuppressArgumentVariablesCheck>false</SuppressArgumentVariablesCheck>
|
||||
<DeploymentTargetPath>/home/pi/projects/amiberry/$(TargetFileName)</DeploymentTargetPath>
|
||||
<X11WindowMode>Local</X11WindowMode>
|
||||
<X11WindowMode>Remote</X11WindowMode>
|
||||
<KeepConsoleAfterExit>false</KeepConsoleAfterExit>
|
||||
<RunGDBUnderSudo>false</RunGDBUnderSudo>
|
||||
<DeploymentMode>Auto</DeploymentMode>
|
||||
|
|
|
@ -222,6 +222,7 @@
|
|||
<ClCompile Include="..\..\src\diskutil.cpp" />
|
||||
<ClCompile Include="..\..\src\dlopen.cpp" />
|
||||
<ClCompile Include="..\..\src\drawing.cpp" />
|
||||
<ClCompile Include="..\..\src\driveclick.cpp" />
|
||||
<ClCompile Include="..\..\src\events.cpp" />
|
||||
<ClCompile Include="..\..\src\expansion.cpp" />
|
||||
<ClCompile Include="..\..\src\fdi2raw.cpp" />
|
||||
|
@ -403,6 +404,7 @@
|
|||
<ClInclude Include="..\..\src\include\disk.h" />
|
||||
<ClInclude Include="..\..\src\include\diskutil.h" />
|
||||
<ClInclude Include="..\..\src\include\drawing.h" />
|
||||
<ClInclude Include="..\..\src\include\driveclick.h" />
|
||||
<ClInclude Include="..\..\src\include\events.h" />
|
||||
<ClInclude Include="..\..\src\include\execio.h" />
|
||||
<ClInclude Include="..\..\src\include\execlib.h" />
|
||||
|
|
|
@ -649,6 +649,9 @@
|
|||
<ClCompile Include="..\..\src\osdep\gui\PanelPrio.cpp">
|
||||
<Filter>Source files\osdep\gui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\driveclick.cpp">
|
||||
<Filter>Source files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\threaddep\thread.h">
|
||||
|
@ -1065,5 +1068,8 @@
|
|||
<ClInclude Include="..\..\src\osdep\amiberry_filesys.hpp">
|
||||
<Filter>Source files\osdep</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\include\driveclick.h">
|
||||
<Filter>Source files\include</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
BIN
data/floppy_sounds/drive_click.wav
Normal file
BIN
data/floppy_sounds/drive_click.wav
Normal file
Binary file not shown.
BIN
data/floppy_sounds/drive_snatch.wav
Normal file
BIN
data/floppy_sounds/drive_snatch.wav
Normal file
Binary file not shown.
BIN
data/floppy_sounds/drive_spin.wav
Normal file
BIN
data/floppy_sounds/drive_spin.wav
Normal file
Binary file not shown.
BIN
data/floppy_sounds/drive_spinnd.wav
Normal file
BIN
data/floppy_sounds/drive_spinnd.wav
Normal file
Binary file not shown.
BIN
data/floppy_sounds/drive_startup.wav
Normal file
BIN
data/floppy_sounds/drive_startup.wav
Normal file
Binary file not shown.
2200
src/audio.cpp
2200
src/audio.cpp
File diff suppressed because it is too large
Load diff
|
@ -438,23 +438,23 @@ static void audio_unpack (struct cdunit *cdu, struct cdtoc *t)
|
|||
sleep_millis(10);
|
||||
}
|
||||
|
||||
//static void next_cd_audio_buffer_callback(int bufnum, void *params)
|
||||
//{
|
||||
// struct cdunit *cdu = (struct cdunit*)params;
|
||||
// uae_sem_wait(&play_sem);
|
||||
// if (bufnum >= 0) {
|
||||
// cdu->cda_bufon[bufnum] = 0;
|
||||
// bufnum = 1 - bufnum;
|
||||
// if (cdu->cda_bufon[bufnum])
|
||||
// audio_cda_new_buffer(&cdu->cas, (uae_s16*)cdu->cda->buffers[bufnum], CDDA_BUFFERS * 2352 / 4, bufnum, next_cd_audio_buffer_callback, cdu);
|
||||
// else
|
||||
// bufnum = -1;
|
||||
// }
|
||||
// if (bufnum < 0) {
|
||||
// audio_cda_new_buffer(&cdu->cas, NULL, -1, 0, NULL, cdu);
|
||||
// }
|
||||
// uae_sem_post(&play_sem);
|
||||
//}
|
||||
static void next_cd_audio_buffer_callback(int bufnum, void *params)
|
||||
{
|
||||
struct cdunit *cdu = (struct cdunit*)params;
|
||||
uae_sem_wait(&play_sem);
|
||||
if (bufnum >= 0) {
|
||||
cdu->cda_bufon[bufnum] = 0;
|
||||
bufnum = 1 - bufnum;
|
||||
if (cdu->cda_bufon[bufnum])
|
||||
audio_cda_new_buffer(&cdu->cas, (uae_s16*)cdu->cda->buffers[bufnum], CDDA_BUFFERS * 2352 / 4, bufnum, next_cd_audio_buffer_callback, cdu);
|
||||
else
|
||||
bufnum = -1;
|
||||
}
|
||||
if (bufnum < 0) {
|
||||
audio_cda_new_buffer(&cdu->cas, NULL, -1, 0, NULL, cdu);
|
||||
}
|
||||
uae_sem_post(&play_sem);
|
||||
}
|
||||
|
||||
static bool cdda_play_func2 (struct cdunit *cdu, int *outpos)
|
||||
{
|
||||
|
@ -479,7 +479,7 @@ static bool cdda_play_func2 (struct cdunit *cdu, int *outpos)
|
|||
cdu->cda_bufon[0] = cdu->cda_bufon[1] = 0;
|
||||
bufnum = 0;
|
||||
|
||||
cdu->cda = new cda_audio (CDDA_BUFFERS, 2352, 44100);
|
||||
cdu->cda = new cda_audio (CDDA_BUFFERS, 2352, 44100, mode != 0);
|
||||
|
||||
while (cdu->cdda_play > 0) {
|
||||
|
||||
|
@ -583,7 +583,17 @@ static bool cdda_play_func2 (struct cdunit *cdu, int *outpos)
|
|||
}
|
||||
}
|
||||
|
||||
cdu->cda->wait(bufnum);
|
||||
if (mode) {
|
||||
while (cdu->cda_bufon[bufnum] && cdu->cdda_play > 0) {
|
||||
if (cd_audio_mode_changed) {
|
||||
restart = true;
|
||||
goto end;
|
||||
}
|
||||
sleep_millis(10);
|
||||
}
|
||||
} else {
|
||||
cdu->cda->wait(bufnum);
|
||||
}
|
||||
|
||||
cdu->cda_bufon[bufnum] = 0;
|
||||
if (cdu->cdda_play <= 0)
|
||||
|
@ -682,13 +692,22 @@ static bool cdda_play_func2 (struct cdunit *cdu, int *outpos)
|
|||
if (idleframes <= 0)
|
||||
cdu->cd_last_pos = cdda_pos;
|
||||
|
||||
cdu->cda_bufon[bufnum] = 1;
|
||||
cdu->cda->setvolume (cdu->cdda_volume[0], cdu->cdda_volume[1]);
|
||||
if (!cdu->cda->play (bufnum)) {
|
||||
if (cdu->cdda_play > 0)
|
||||
setstate (cdu, AUDIO_STATUS_PLAY_ERROR, -1);
|
||||
goto end;
|
||||
}
|
||||
if (mode) {
|
||||
if (cdu->cda_bufon[0] == 0 && cdu->cda_bufon[1] == 0) {
|
||||
cdu->cda_bufon[bufnum] = 1;
|
||||
next_cd_audio_buffer_callback(1 - bufnum, cdu);
|
||||
}
|
||||
audio_cda_volume(&cdu->cas, cdu->cdda_volume[0], cdu->cdda_volume[1]);
|
||||
cdu->cda_bufon[bufnum] = 1;
|
||||
} else {
|
||||
cdu->cda_bufon[bufnum] = 1;
|
||||
cdu->cda->setvolume (cdu->cdda_volume[0], cdu->cdda_volume[1]);
|
||||
if (!cdu->cda->play (bufnum)) {
|
||||
if (cdu->cdda_play > 0)
|
||||
setstate (cdu, AUDIO_STATUS_PLAY_ERROR, -1);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (first) {
|
||||
first = false;
|
||||
|
@ -719,8 +738,14 @@ static bool cdda_play_func2 (struct cdunit *cdu, int *outpos)
|
|||
|
||||
end:
|
||||
*outpos = cdda_pos;
|
||||
cdu->cda->wait (0);
|
||||
cdu->cda->wait (1);
|
||||
if (mode) {
|
||||
next_cd_audio_buffer_callback(-1, cdu);
|
||||
if (restart)
|
||||
audio_cda_new_buffer(&cdu->cas, NULL, -1, -1, NULL, NULL);
|
||||
} else {
|
||||
cdu->cda->wait (0);
|
||||
cdu->cda->wait (1);
|
||||
}
|
||||
|
||||
while (cdimage_unpack_active == 1)
|
||||
sleep_millis(10);
|
||||
|
@ -1955,12 +1980,15 @@ static int parsenrg(struct cdunit *cdu, struct zfile *znrg, const TCHAR *img, co
|
|||
} else {
|
||||
tracknum = frombcd(trk);
|
||||
int index = frombcd(buf[2]);
|
||||
if (index == 0 && tracknum >= 1 && tracknum <= 99) {
|
||||
uae_u32 address = get_long_host(buf + 4);
|
||||
if (tracknum >= 1 && tracknum <= 99) {
|
||||
struct cdtoc *t = &cdu->toc[tracknum - 1];
|
||||
t->address = get_long_host(buf + 4);
|
||||
t->ctrl = buf[0] >> 4;
|
||||
t->adr = buf[0] & 15;
|
||||
t->track = tracknum;
|
||||
if (index == 0) {
|
||||
t->address = address;
|
||||
t->ctrl = buf[0] >> 4;
|
||||
t->adr = buf[0] & 15;
|
||||
t->track = tracknum;
|
||||
}
|
||||
}
|
||||
}
|
||||
size -= 8;
|
||||
|
|
|
@ -379,11 +379,11 @@ static void l64111_setvolume(void)
|
|||
return;
|
||||
write_log(_T("L64111 mute %d\n"), volume ? 0 : 1);
|
||||
if (cda) {
|
||||
//if (audio_mode) {
|
||||
// audio_cda_volume(&cas, volume, volume);
|
||||
//} else {
|
||||
if (audio_mode) {
|
||||
audio_cda_volume(&cas, volume, volume);
|
||||
} else {
|
||||
cda->setvolume(volume, volume);
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1302,22 +1302,22 @@ void cd32_fmv_set_sync(double svpos, double adjust)
|
|||
fmv_syncadjust = adjust;
|
||||
}
|
||||
|
||||
//static void fmv_next_cd_audio_buffer_callback(int bufnum, void *param)
|
||||
//{
|
||||
// uae_sem_wait(&play_sem);
|
||||
// if (bufnum >= 0) {
|
||||
// fmv_bufon[bufnum] = 0;
|
||||
// bufnum = 1 - bufnum;
|
||||
// if (fmv_bufon[bufnum])
|
||||
// audio_cda_new_buffer(&cas, (uae_s16*)cda->buffers[bufnum], PCM_SECTORS * KJMP2_SAMPLES_PER_FRAME, bufnum, fmv_next_cd_audio_buffer_callback, param);
|
||||
// else
|
||||
// bufnum = -1;
|
||||
// }
|
||||
// if (bufnum < 0) {
|
||||
// audio_cda_new_buffer(&cas, NULL, 0, -1, NULL, NULL);
|
||||
// }
|
||||
// uae_sem_post(&play_sem);
|
||||
//}
|
||||
static void fmv_next_cd_audio_buffer_callback(int bufnum, void *param)
|
||||
{
|
||||
uae_sem_wait(&play_sem);
|
||||
if (bufnum >= 0) {
|
||||
fmv_bufon[bufnum] = 0;
|
||||
bufnum = 1 - bufnum;
|
||||
if (fmv_bufon[bufnum])
|
||||
audio_cda_new_buffer(&cas, (uae_s16*)cda->buffers[bufnum], PCM_SECTORS * KJMP2_SAMPLES_PER_FRAME, bufnum, fmv_next_cd_audio_buffer_callback, param);
|
||||
else
|
||||
bufnum = -1;
|
||||
}
|
||||
if (bufnum < 0) {
|
||||
audio_cda_new_buffer(&cas, NULL, 0, -1, NULL, NULL);
|
||||
}
|
||||
uae_sem_post(&play_sem);
|
||||
}
|
||||
|
||||
void cd32_fmv_vsync_handler(void)
|
||||
{
|
||||
|
@ -1335,13 +1335,13 @@ static void cd32_fmv_audio_handler(void)
|
|||
if (cd_audio_mode_changed || (cl450_play && !cda)) {
|
||||
cd_audio_mode_changed = false;
|
||||
if (cl450_play) {
|
||||
//if (audio_mode) {
|
||||
// audio_cda_new_buffer(&cas, NULL, -1, -1, NULL, NULL);
|
||||
//}
|
||||
if (audio_mode) {
|
||||
audio_cda_new_buffer(&cas, NULL, -1, -1, NULL, NULL);
|
||||
}
|
||||
audio_mode = currprefs.sound_cdaudio;
|
||||
fmv_bufon[0] = fmv_bufon[1] = 0;
|
||||
delete cda;
|
||||
cda = new cda_audio(PCM_SECTORS, KJMP2_SAMPLES_PER_FRAME * 4, 44100);
|
||||
cda = new cda_audio(PCM_SECTORS, KJMP2_SAMPLES_PER_FRAME * 4, 44100, audio_mode != 0);
|
||||
l64111_setvolume();
|
||||
}
|
||||
}
|
||||
|
@ -1357,13 +1357,13 @@ static void cd32_fmv_audio_handler(void)
|
|||
|
||||
if (!cda || !(l64111_regs[A_CONTROL1] & 1))
|
||||
return;
|
||||
//if (audio_mode) {
|
||||
// play0 = fmv_bufon[0];
|
||||
// play1 = fmv_bufon[1];
|
||||
//} else {
|
||||
if (audio_mode) {
|
||||
play0 = fmv_bufon[0];
|
||||
play1 = fmv_bufon[1];
|
||||
} else {
|
||||
play0 = cda->isplaying(0);
|
||||
play1 = cda->isplaying(1);
|
||||
//}
|
||||
}
|
||||
needsectors = PCM_SECTORS;
|
||||
if (!play0 && !play1) {
|
||||
needsectors *= 2;
|
||||
|
@ -1387,15 +1387,15 @@ static void cd32_fmv_audio_handler(void)
|
|||
memcpy(cda->buffers[bufnum] + i * KJMP2_SAMPLES_PER_FRAME * 4, pcmaudio[offset2].pcm, KJMP2_SAMPLES_PER_FRAME * 4);
|
||||
pcmaudio[offset2].ready = false;
|
||||
}
|
||||
//if (audio_mode) {
|
||||
// if (!play0 && !play1) {
|
||||
// fmv_bufon[bufnum] = 1;
|
||||
// fmv_next_cd_audio_buffer_callback(1 - bufnum, NULL);
|
||||
// }
|
||||
// fmv_bufon[bufnum] = 1;
|
||||
//} else {
|
||||
if (audio_mode) {
|
||||
if (!play0 && !play1) {
|
||||
fmv_bufon[bufnum] = 1;
|
||||
fmv_next_cd_audio_buffer_callback(1 - bufnum, NULL);
|
||||
}
|
||||
fmv_bufon[bufnum] = 1;
|
||||
} else {
|
||||
cda->play(bufnum);
|
||||
//}
|
||||
}
|
||||
offset += PCM_SECTORS;
|
||||
offset &= l64111_cb_mask;
|
||||
l64111_regs[A_CB_READ] = offset;
|
||||
|
@ -1469,12 +1469,12 @@ static void cd32_fmv_free(void)
|
|||
xfree(videoram);
|
||||
videoram = NULL;
|
||||
if (cda) {
|
||||
//if (audio_mode) {
|
||||
// fmv_next_cd_audio_buffer_callback(-1, NULL);
|
||||
//} else {
|
||||
if (audio_mode) {
|
||||
fmv_next_cd_audio_buffer_callback(-1, NULL);
|
||||
} else {
|
||||
cda->wait(0);
|
||||
cda->wait(1);
|
||||
//}
|
||||
}
|
||||
delete cda;
|
||||
}
|
||||
cda = NULL;
|
||||
|
|
|
@ -30,6 +30,9 @@
|
|||
#include "gensound.h"
|
||||
#include "gui.h"
|
||||
#include "drawing.h"
|
||||
#ifdef DRIVESOUND
|
||||
#include "driveclick.h"
|
||||
#endif
|
||||
#include "statusline.h"
|
||||
#include "uaeexe.h"
|
||||
#ifdef JIT
|
||||
|
@ -257,6 +260,7 @@ void devices_rethink(void)
|
|||
void devices_update_sound(double clk, double syncadjust)
|
||||
{
|
||||
update_sound(clk);
|
||||
update_cda_sound(clk / syncadjust);
|
||||
}
|
||||
|
||||
void devices_update_sync(double svpos, double syncadjust)
|
||||
|
|
|
@ -34,6 +34,9 @@ int disk_debug_track = -1;
|
|||
#ifdef FDI2RAW
|
||||
#include "fdi2raw.h"
|
||||
#endif
|
||||
#ifdef DRIVESOUND
|
||||
#include "driveclick.h"
|
||||
#endif
|
||||
#ifdef CAPS
|
||||
#include "uae/caps.h"
|
||||
#endif
|
||||
|
|
600
src/driveclick.cpp
Normal file
600
src/driveclick.cpp
Normal file
|
@ -0,0 +1,600 @@
|
|||
/*
|
||||
* UAE - The Un*x Amiga Emulator
|
||||
*
|
||||
* Drive Click Emulation Support Functions
|
||||
*
|
||||
* Copyright 2004 James Bagg, Toni Wilen
|
||||
*/
|
||||
|
||||
#include "sysconfig.h"
|
||||
#include "sysdeps.h"
|
||||
|
||||
#ifdef DRIVESOUND
|
||||
|
||||
#include "uae.h"
|
||||
#include "options.h"
|
||||
#include "audio.h"
|
||||
#include "sounddep/sound.h"
|
||||
#include "zfile.h"
|
||||
#include "fsdb.h"
|
||||
#include "events.h"
|
||||
#include "driveclick.h"
|
||||
|
||||
#ifdef AMIBERRY
|
||||
SDL_AudioSpec wav_spec;
|
||||
Uint32 wav_length;
|
||||
Uint8* wav_buffer;
|
||||
#endif
|
||||
|
||||
static struct drvsample drvs[4][DS_END];
|
||||
static int freq = 44100;
|
||||
|
||||
static int drv_starting[4], drv_spinning[4], drv_has_spun[4], drv_has_disk[4];
|
||||
|
||||
static int click_initialized, wave_initialized;
|
||||
#define DS_SHIFT 10
|
||||
static int sample_step;
|
||||
static uae_s16* clickbuffer;
|
||||
static int clickcnt;
|
||||
|
||||
uae_s16* decodewav(uae_u8* s, int* lenp)
|
||||
{
|
||||
uae_s16* dst;
|
||||
uae_u8* src = s;
|
||||
int len;
|
||||
|
||||
if (memcmp(s, "RIFF", 4))
|
||||
return 0;
|
||||
if (memcmp(s + 8, "WAVE", 4))
|
||||
return 0;
|
||||
s += 12;
|
||||
len = *lenp;
|
||||
while (s < src + len) {
|
||||
if (!memcmp(s, "fmt ", 4))
|
||||
freq = s[8 + 4] | (s[8 + 5] << 8);
|
||||
if (!memcmp(s, "data", 4)) {
|
||||
s += 4;
|
||||
len = s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24);
|
||||
dst = xmalloc(uae_s16, len / 2);
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
int8_t* dst8 = (int8_t*)dst;
|
||||
for (int i = 0; i < len; i += 2) {
|
||||
dst8[i] = s[i + 1];
|
||||
dst8[i + 1] = s[i];
|
||||
}
|
||||
#else
|
||||
memcpy(dst, s + 4, len);
|
||||
#endif
|
||||
* lenp = len / 2;
|
||||
return dst;
|
||||
}
|
||||
s += 8 + (s[4] | (s[5] << 8) | (s[6] << 16) | (s[7] << 24));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int loadsample(TCHAR* path, struct drvsample* ds)
|
||||
{
|
||||
struct zfile* f;
|
||||
uae_u8* buf;
|
||||
int size;
|
||||
TCHAR name[MAX_DPATH];
|
||||
|
||||
f = zfile_fopen(path, _T("rb"), ZFD_NORMAL);
|
||||
if (!f) {
|
||||
_tcscpy(name, path);
|
||||
_tcscat(name, _T(".wav"));
|
||||
f = zfile_fopen(name, _T("rb"), ZFD_NORMAL);
|
||||
if (!f) {
|
||||
write_log(_T("driveclick: can't open '%s' (or '%s')\n"), path, name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
zfile_fseek(f, 0, SEEK_END);
|
||||
size = zfile_ftell(f);
|
||||
buf = xmalloc(uae_u8, size);
|
||||
zfile_fseek(f, 0, SEEK_SET);
|
||||
zfile_fread(buf, size, 1, f);
|
||||
zfile_fclose(f);
|
||||
ds->len = size;
|
||||
ds->p = decodewav(buf, &ds->len);
|
||||
xfree(buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void freesample(struct drvsample* s)
|
||||
{
|
||||
xfree(s->p);
|
||||
s->p = nullptr;
|
||||
}
|
||||
|
||||
static void processclicks(struct drvsample* ds)
|
||||
{
|
||||
unsigned int nClick = 0;
|
||||
|
||||
for (int n = 0; n < CLICK_TRACKS; n++) {
|
||||
ds->indexes[n] = 0;
|
||||
ds->lengths[n] = 0;
|
||||
}
|
||||
for (int n = 0; n < ds->len; n++) {
|
||||
uae_s16 smp = ds->p[n];
|
||||
if (smp > 0x6ff0 && nClick < CLICK_TRACKS) {
|
||||
ds->indexes[nClick] = n - 128;
|
||||
ds->lengths[nClick] = 2800;
|
||||
nClick++;
|
||||
n += 3000;
|
||||
}
|
||||
}
|
||||
if (nClick == 0) {
|
||||
for (int n = 0; n < CLICK_TRACKS; n++) {
|
||||
ds->indexes[n] = 0;
|
||||
ds->lengths[n] = ds->len;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (nClick == 1) {
|
||||
ds->lengths[0] = ds->len - ds->indexes[0];
|
||||
for (int n = 1; n < CLICK_TRACKS; n++) {
|
||||
ds->indexes[n] = ds->indexes[0];
|
||||
ds->lengths[n] = ds->lengths[0];
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int n = nClick; n < CLICK_TRACKS; n++) {
|
||||
ds->indexes[n] = ds->indexes[nClick - 1];
|
||||
ds->lengths[n] = ds->lengths[nClick - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void driveclick_close(void)
|
||||
{
|
||||
driveclick_fdrawcmd_close(0);
|
||||
driveclick_fdrawcmd_close(1);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < DS_END; j++)
|
||||
freesample(&drvs[i][j]);
|
||||
}
|
||||
memset(drvs, 0, sizeof(drvs));
|
||||
click_initialized = 0;
|
||||
wave_initialized = 0;
|
||||
driveclick_reset();
|
||||
}
|
||||
|
||||
void driveclick_free(void)
|
||||
{
|
||||
driveclick_close();
|
||||
}
|
||||
|
||||
void driveclick_init(void)
|
||||
{
|
||||
int v, vv;
|
||||
TCHAR tmp[MAX_DPATH];
|
||||
|
||||
driveclick_fdrawcmd_detect();
|
||||
driveclick_close();
|
||||
vv = 0;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
struct floppyslot* fs = &currprefs.floppyslots[i];
|
||||
for (int j = 0; j < CLICK_TRACKS; j++) {
|
||||
drvs[i][DS_CLICK].indexes[j] = 0;
|
||||
drvs[i][DS_CLICK].lengths[j] = 0;
|
||||
}
|
||||
if (fs->dfxclick) {
|
||||
v = 0;
|
||||
if (fs->dfxclick > 0) {
|
||||
switch (fs->dfxclick)
|
||||
{
|
||||
case 1:
|
||||
if (driveclick_loadresource(drvs[i], fs->dfxclick))
|
||||
v = 3;
|
||||
for (int j = 0; j < CLICK_TRACKS; j++)
|
||||
drvs[i][DS_CLICK].lengths[j] = drvs[i][DS_CLICK].len;
|
||||
wave_initialized = 1;
|
||||
break;
|
||||
default:
|
||||
if (driveclick_fdrawcmd_open(fs->dfxclick - 2))
|
||||
v = 1;
|
||||
break;
|
||||
}
|
||||
} else if (fs->dfxclick == -1) {
|
||||
TCHAR path2[MAX_DPATH];
|
||||
wave_initialized = 1;
|
||||
for (int j = 0; j < CLICK_TRACKS; j++)
|
||||
drvs[i][DS_CLICK].lengths[j] = drvs[i][DS_CLICK].len;
|
||||
get_plugin_path (path2, sizeof path2 / sizeof (TCHAR), _T("floppysounds"));
|
||||
_stprintf (tmp, _T("%sdrive_click_%s"),
|
||||
path2, fs->dfxclickexternal);
|
||||
v = loadsample (tmp, &drvs[i][DS_CLICK]);
|
||||
if (v)
|
||||
processclicks (&drvs[i][DS_CLICK]);
|
||||
_stprintf (tmp, _T("%sdrive_spin_%s"),
|
||||
path2, fs->dfxclickexternal);
|
||||
v += loadsample (tmp, &drvs[i][DS_SPIN]);
|
||||
_stprintf (tmp, _T("%sdrive_spinnd_%s"),
|
||||
path2, fs->dfxclickexternal);
|
||||
v += loadsample (tmp, &drvs[i][DS_SPINND]);
|
||||
_stprintf (tmp, _T("%sdrive_startup_%s"),
|
||||
path2, fs->dfxclickexternal);
|
||||
v += loadsample (tmp, &drvs[i][DS_START]);
|
||||
_stprintf (tmp, _T("%sdrive_snatch_%s"),
|
||||
path2, fs->dfxclickexternal);
|
||||
v += loadsample (tmp, &drvs[i][DS_SNATCH]);
|
||||
}
|
||||
if (v == 0) {
|
||||
for (int j = 0; j < DS_END; j++)
|
||||
freesample(&drvs[i][j]);
|
||||
fs->dfxclick = changed_prefs.floppyslots[i].dfxclick = 0;
|
||||
} else {
|
||||
vv++;
|
||||
}
|
||||
for (int j = 0; j < DS_END; j++)
|
||||
drvs[i][j].len <<= DS_SHIFT;
|
||||
drvs[i][DS_CLICK].pos = drvs[i][DS_CLICK].len;
|
||||
drvs[i][DS_SNATCH].pos = drvs[i][DS_SNATCH].len;
|
||||
}
|
||||
}
|
||||
if (vv > 0) {
|
||||
click_initialized = 1;
|
||||
}
|
||||
driveclick_reset();
|
||||
}
|
||||
|
||||
void driveclick_reset (void)
|
||||
{
|
||||
xfree (clickbuffer);
|
||||
clickbuffer = NULL;
|
||||
clickcnt = 0;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
drv_starting[i] = 0;
|
||||
drv_spinning[i] = 0;
|
||||
drv_has_spun[i] = 0;
|
||||
drv_has_disk[i] = 0;
|
||||
if (currprefs.floppyslots[i].df[0])
|
||||
driveclick_insert(i, 0);
|
||||
}
|
||||
if (!wave_initialized)
|
||||
return;
|
||||
clickbuffer = xcalloc (uae_s16, paula_sndbufsize / 2);
|
||||
sample_step = (freq << DS_SHIFT) / currprefs.sound_freq;
|
||||
}
|
||||
|
||||
static int driveclick_active (void)
|
||||
{
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (currprefs.floppyslots[i].dfxclick) {
|
||||
if (drv_spinning[i] || drv_starting[i])
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uae_s16 getsample (void)
|
||||
{
|
||||
uae_s32 total_sample = 0;
|
||||
int total_div = 0;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int div = 0;
|
||||
if (currprefs.floppyslots[i].dfxclick) {
|
||||
uae_s32 smp = 0;
|
||||
struct drvsample* ds_start = &drvs[i][DS_START];
|
||||
struct drvsample* ds_spin = drv_has_disk[i] ? &drvs[i][DS_SPIN] : &drvs[i][DS_SPINND];
|
||||
struct drvsample* ds_click = &drvs[i][DS_CLICK];
|
||||
struct drvsample* ds_snatch = &drvs[i][DS_SNATCH];
|
||||
if (drv_spinning[i] || drv_starting[i]) {
|
||||
div++;
|
||||
if (drv_starting[i] && drv_has_spun[i]) {
|
||||
if (ds_start->p && ds_start->pos < ds_start->len) {
|
||||
smp = ds_start->p[ds_start->pos >> DS_SHIFT];
|
||||
ds_start->pos += sample_step;
|
||||
} else {
|
||||
drv_starting[i] = 0;
|
||||
}
|
||||
} else if (drv_starting[i] && drv_has_spun[i] == 0) {
|
||||
if (ds_snatch->p && ds_snatch->pos < ds_snatch->len) {
|
||||
smp = ds_snatch->p[ds_snatch->pos >> DS_SHIFT];
|
||||
ds_snatch->pos += sample_step;
|
||||
} else {
|
||||
drv_starting[i] = 0;
|
||||
ds_start->pos = ds_start->len;
|
||||
drv_has_spun[i] = 1;
|
||||
}
|
||||
}
|
||||
if (ds_spin->p && drv_starting[i] == 0) {
|
||||
if (ds_spin->pos >= ds_spin->len)
|
||||
ds_spin->pos -= ds_spin->len;
|
||||
smp = ds_spin->p[ds_spin->pos >> DS_SHIFT];
|
||||
ds_spin->pos += sample_step;
|
||||
}
|
||||
}
|
||||
if (ds_click->p && ds_click->pos < ds_click->len) {
|
||||
smp += ds_click->p[ds_click->pos >> DS_SHIFT];
|
||||
div++;
|
||||
ds_click->pos += sample_step;
|
||||
}
|
||||
if (div) {
|
||||
int vol;
|
||||
if (drv_has_disk[i])
|
||||
vol = currprefs.dfxclickvolume_disk[i];
|
||||
else
|
||||
vol = currprefs.dfxclickvolume_empty[i];
|
||||
total_sample += (smp * (100 - vol) / 100) / div;
|
||||
total_div++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!total_div)
|
||||
return 0;
|
||||
return total_sample / total_div;
|
||||
}
|
||||
|
||||
static void mix(void)
|
||||
{
|
||||
int total = ((uae_u8*)paula_sndbufpt - (uae_u8*)paula_sndbuffer) / (get_audio_nativechannels(currprefs.sound_stereo) * 2);
|
||||
while (clickcnt < total) {
|
||||
clickbuffer[clickcnt++] = getsample();
|
||||
}
|
||||
}
|
||||
|
||||
STATIC_INLINE uae_s16 limit(uae_s32 v)
|
||||
{
|
||||
if (v < -32768)
|
||||
v = -32768;
|
||||
if (v > 32767)
|
||||
v = 32767;
|
||||
return v;
|
||||
}
|
||||
|
||||
void driveclick_mix(uae_s16* sndbuffer, int size, int channelmask)
|
||||
{
|
||||
if (!wave_initialized)
|
||||
return;
|
||||
mix();
|
||||
clickcnt = 0;
|
||||
switch (get_audio_nativechannels(currprefs.sound_stereo))
|
||||
{
|
||||
case 6:
|
||||
for (int i = 0; i < size / 6; i++) {
|
||||
uae_s16 s = clickbuffer[i];
|
||||
if (channelmask & 1)
|
||||
sndbuffer[0] = limit(((sndbuffer[0] + s) * 2) / 3);
|
||||
else
|
||||
sndbuffer[0] = sndbuffer[0] * 2 / 3;
|
||||
if (channelmask & 2)
|
||||
sndbuffer[1] = limit(((sndbuffer[1] + s) * 2) / 3);
|
||||
else
|
||||
sndbuffer[1] = sndbuffer[1] * 2 / 3;
|
||||
if (channelmask & 4)
|
||||
sndbuffer[2] = limit(((sndbuffer[2] + s) * 2) / 3);
|
||||
else
|
||||
sndbuffer[2] = sndbuffer[2] * 2 / 3;
|
||||
if (channelmask & 8)
|
||||
sndbuffer[3] = limit(((sndbuffer[3] + s) * 2) / 3);
|
||||
else
|
||||
sndbuffer[3] = sndbuffer[3] * 2 / 3;
|
||||
if (channelmask & 16)
|
||||
sndbuffer[4] = limit(((sndbuffer[4] + s) * 2) / 3);
|
||||
else
|
||||
sndbuffer[4] = sndbuffer[4] * 2 / 3;
|
||||
if (channelmask & 32)
|
||||
sndbuffer[5] = limit(((sndbuffer[5] + s) * 2) / 3);
|
||||
else
|
||||
sndbuffer[5] = sndbuffer[5] * 2 / 3;
|
||||
sndbuffer += 6;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
for (int i = 0; i < size / 4; i++) {
|
||||
uae_s16 s = clickbuffer[i];
|
||||
if (channelmask & 1)
|
||||
sndbuffer[0] = limit(((sndbuffer[0] + s) * 2) / 3);
|
||||
else
|
||||
sndbuffer[0] = sndbuffer[0] * 2 / 3;
|
||||
if (channelmask & 2)
|
||||
sndbuffer[1] = limit(((sndbuffer[1] + s) * 2) / 3);
|
||||
else
|
||||
sndbuffer[1] = sndbuffer[1] * 2 / 3;
|
||||
if (channelmask & 4)
|
||||
sndbuffer[2] = limit(((sndbuffer[2] + s) * 2) / 3);
|
||||
else
|
||||
sndbuffer[2] = sndbuffer[2] * 2 / 3;
|
||||
if (channelmask & 8)
|
||||
sndbuffer[3] = limit(((sndbuffer[3] + s) * 2) / 3);
|
||||
else
|
||||
sndbuffer[3] = sndbuffer[3] * 2 / 3;
|
||||
sndbuffer += 4;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
for (int i = 0; i < size / 2; i++) {
|
||||
uae_s16 s = clickbuffer[i];
|
||||
if (channelmask & 1)
|
||||
sndbuffer[0] = limit(((sndbuffer[0] + s) * 2) / 3);
|
||||
else
|
||||
sndbuffer[0] = sndbuffer[0] * 2 / 3;
|
||||
if (channelmask & 2)
|
||||
sndbuffer[1] = limit(((sndbuffer[1] + s) * 2) / 3);
|
||||
else
|
||||
sndbuffer[1] = sndbuffer[1] * 2 / 3;
|
||||
sndbuffer += 2;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
for (int i = 0; i < size; i++) {
|
||||
uae_s16 s = clickbuffer[i];
|
||||
if (channelmask & 1)
|
||||
sndbuffer[0] = limit(((sndbuffer[0] + s) * 2) / 3);
|
||||
else
|
||||
sndbuffer[0] = sndbuffer[0] * 2 / 3;
|
||||
sndbuffer++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void dr_audio_activate(void)
|
||||
{
|
||||
if (audio_activate())
|
||||
clickcnt = 0;
|
||||
}
|
||||
|
||||
void driveclick_click(int drive, int cyl)
|
||||
{
|
||||
static int prevcyl[4];
|
||||
|
||||
if (!click_initialized)
|
||||
return;
|
||||
if (!currprefs.floppyslots[drive].dfxclick)
|
||||
return;
|
||||
if (prevcyl[drive] == 0 && cyl == 0) // "noclick" check
|
||||
return;
|
||||
dr_audio_activate();
|
||||
prevcyl[drive] = cyl;
|
||||
if (!wave_initialized) {
|
||||
driveclick_fdrawcmd_seek(currprefs.floppyslots[drive].dfxclick - 2, cyl);
|
||||
return;
|
||||
}
|
||||
mix();
|
||||
drvs[drive][DS_CLICK].pos = drvs[drive][DS_CLICK].indexes[cyl] << DS_SHIFT;
|
||||
drvs[drive][DS_CLICK].len = (drvs[drive][DS_CLICK].indexes[cyl] + (drvs[drive][DS_CLICK].lengths[cyl] / 2)) << DS_SHIFT;
|
||||
}
|
||||
|
||||
void driveclick_motor(int drive, int running)
|
||||
{
|
||||
if (!click_initialized)
|
||||
return;
|
||||
if (!currprefs.floppyslots[drive].dfxclick)
|
||||
return;
|
||||
if (!wave_initialized) {
|
||||
driveclick_fdrawcmd_motor(currprefs.floppyslots[drive].dfxclick - 2, running);
|
||||
return;
|
||||
}
|
||||
mix();
|
||||
if (running == 0) {
|
||||
drv_starting[drive] = 0;
|
||||
drv_spinning[drive] = 0;
|
||||
} else {
|
||||
if (drv_spinning[drive] == 0) {
|
||||
dr_audio_activate();
|
||||
drv_starting[drive] = 1;
|
||||
drv_spinning[drive] = 1;
|
||||
if (drv_has_disk[drive] && drv_has_spun[drive] == 0 && drvs[drive][DS_SNATCH].pos >= drvs[drive][DS_SNATCH].len)
|
||||
drvs[drive][DS_SNATCH].pos = 0;
|
||||
if (running == 2)
|
||||
drvs[drive][DS_START].pos = 0;
|
||||
drvs[drive][DS_SPIN].pos = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void driveclick_insert(int drive, int eject)
|
||||
{
|
||||
if (!click_initialized)
|
||||
return;
|
||||
if (!wave_initialized)
|
||||
return;
|
||||
if (!currprefs.floppyslots[drive].dfxclick)
|
||||
return;
|
||||
if (eject)
|
||||
drv_has_spun[drive] = 0;
|
||||
if (drv_has_disk[drive] == 0 && !eject)
|
||||
dr_audio_activate ();
|
||||
drv_has_disk[drive] = !eject;
|
||||
}
|
||||
|
||||
void driveclick_check_prefs(void)
|
||||
{
|
||||
if (!config_changed)
|
||||
return;
|
||||
driveclick_fdrawcmd_vsync();
|
||||
if (driveclick_active())
|
||||
dr_audio_activate();
|
||||
if (
|
||||
currprefs.dfxclickvolume_disk[0] != changed_prefs.dfxclickvolume_disk[0] ||
|
||||
currprefs.dfxclickvolume_disk[1] != changed_prefs.dfxclickvolume_disk[1] ||
|
||||
currprefs.dfxclickvolume_disk[2] != changed_prefs.dfxclickvolume_disk[2] ||
|
||||
currprefs.dfxclickvolume_disk[3] != changed_prefs.dfxclickvolume_disk[3] ||
|
||||
currprefs.dfxclickvolume_empty[0] != changed_prefs.dfxclickvolume_empty[0] ||
|
||||
currprefs.dfxclickvolume_empty[1] != changed_prefs.dfxclickvolume_empty[1] ||
|
||||
currprefs.dfxclickvolume_empty[2] != changed_prefs.dfxclickvolume_empty[2] ||
|
||||
currprefs.dfxclickvolume_empty[3] != changed_prefs.dfxclickvolume_empty[3] ||
|
||||
currprefs.floppyslots[0].dfxclick != changed_prefs.floppyslots[0].dfxclick ||
|
||||
currprefs.floppyslots[1].dfxclick != changed_prefs.floppyslots[1].dfxclick ||
|
||||
currprefs.floppyslots[2].dfxclick != changed_prefs.floppyslots[2].dfxclick ||
|
||||
currprefs.floppyslots[3].dfxclick != changed_prefs.floppyslots[3].dfxclick ||
|
||||
_tcscmp(currprefs.floppyslots[0].dfxclickexternal, changed_prefs.floppyslots[0].dfxclickexternal) ||
|
||||
_tcscmp(currprefs.floppyslots[1].dfxclickexternal, changed_prefs.floppyslots[1].dfxclickexternal) ||
|
||||
_tcscmp(currprefs.floppyslots[2].dfxclickexternal, changed_prefs.floppyslots[2].dfxclickexternal) ||
|
||||
_tcscmp(currprefs.floppyslots[3].dfxclickexternal, changed_prefs.floppyslots[3].dfxclickexternal))
|
||||
{
|
||||
for (int i = 0; i < 4; i++) {
|
||||
currprefs.floppyslots[i].dfxclick = changed_prefs.floppyslots[i].dfxclick;
|
||||
_tcscpy(currprefs.floppyslots[i].dfxclickexternal, changed_prefs.floppyslots[i].dfxclickexternal);
|
||||
currprefs.dfxclickvolume_empty[i] = changed_prefs.dfxclickvolume_empty[i];
|
||||
currprefs.dfxclickvolume_disk[i] = changed_prefs.dfxclickvolume_disk[i];
|
||||
}
|
||||
driveclick_init();
|
||||
}
|
||||
}
|
||||
|
||||
int driveclick_loadresource(struct drvsample* sp, int drivetype)
|
||||
{
|
||||
auto ok = 1;
|
||||
for (auto type = 0; type < DS_END; type++) {
|
||||
auto* s = sp + type;
|
||||
switch (type) {
|
||||
case 0:
|
||||
ok = loadsample("data/floppy_sounds/drive_click.wav", s);
|
||||
break;
|
||||
case 1:
|
||||
ok = loadsample("data/floppy_sounds/drive_spin.wav", s);
|
||||
break;
|
||||
case 2:
|
||||
ok = loadsample("data/floppy_sounds/drive_spinnd.wav", s);
|
||||
break;
|
||||
case 3:
|
||||
ok = loadsample("data/floppy_sounds/drive_startup.wav", s);
|
||||
break;
|
||||
case 4:
|
||||
ok = loadsample("data/floppy_sounds/drive_snatch.wav", s);
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
void driveclick_fdrawcmd_close(int drive)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int driveclick_fdrawcmd_open(int drive)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void driveclick_fdrawcmd_detect(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void driveclick_fdrawcmd_seek(int drive, int cyl)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void driveclick_fdrawcmd_motor(int drive, int running)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void driveclick_fdrawcmd_vsync(void)
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
|
@ -75,9 +75,9 @@ static bool event_check_vsync(void)
|
|||
if (v < 0)
|
||||
{
|
||||
if (currprefs.cachesize)
|
||||
regs.pissoff = pissoff_value;
|
||||
pissoff = pissoff_value;
|
||||
else
|
||||
regs.pissoff = pissoff_nojit_value;
|
||||
pissoff = pissoff_nojit_value;
|
||||
return true;
|
||||
}
|
||||
//}
|
||||
|
@ -95,9 +95,9 @@ static bool event_check_vsync(void)
|
|||
}
|
||||
if (v < 0 && v2 < 0) {
|
||||
if (currprefs.cachesize)
|
||||
regs.pissoff = pissoff_value;
|
||||
pissoff = pissoff_value;
|
||||
else
|
||||
regs.pissoff = pissoff_nojit_value;
|
||||
pissoff = pissoff_nojit_value;
|
||||
return true;
|
||||
}
|
||||
//}
|
||||
|
@ -108,11 +108,11 @@ static bool event_check_vsync(void)
|
|||
|
||||
void do_cycles_cpu_fastest(uae_u32 cycles_to_add)
|
||||
{
|
||||
if ((regs.pissoff -= cycles_to_add) > 0)
|
||||
if ((pissoff -= cycles_to_add) > 0)
|
||||
return;
|
||||
|
||||
cycles_to_add = -regs.pissoff;
|
||||
regs.pissoff = 0;
|
||||
cycles_to_add = -pissoff;
|
||||
pissoff = 0;
|
||||
|
||||
if (is_syncline)
|
||||
{
|
||||
|
|
57
src/include/driveclick.h
Normal file
57
src/include/driveclick.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* UAE - The Un*x Amiga Emulator
|
||||
*
|
||||
* Drive Click emulation stuff
|
||||
*
|
||||
* Copyright 2004 James Bagg, Toni Wilen
|
||||
*/
|
||||
|
||||
#ifndef UAE_DRIVECLICK_H
|
||||
#define UAE_DRIVECLICK_H
|
||||
|
||||
#include "uae/types.h"
|
||||
|
||||
#define CLICK_TRACKS 84
|
||||
|
||||
struct drvsample {
|
||||
int len;
|
||||
int pos;
|
||||
uae_s16* p;
|
||||
int indexes[CLICK_TRACKS];
|
||||
int lengths[CLICK_TRACKS];
|
||||
};
|
||||
|
||||
#define DS_CLICK 0
|
||||
#define DS_SPIN 1
|
||||
#define DS_SPINND 2
|
||||
#define DS_START 3
|
||||
#define DS_SNATCH 4
|
||||
#define DS_END 5
|
||||
|
||||
extern void driveclick_click(int drive, int startOffset);
|
||||
extern void driveclick_motor(int drive, int running);
|
||||
extern void driveclick_insert(int drive, int eject);
|
||||
extern void driveclick_init(void);
|
||||
extern void driveclick_free(void);
|
||||
extern void driveclick_reset(void);
|
||||
extern void driveclick_mix(uae_s16*, int, int);
|
||||
extern int driveclick_loadresource(struct drvsample*, int);
|
||||
extern void driveclick_check_prefs(void);
|
||||
extern uae_s16* decodewav(uae_u8* s, int* len);
|
||||
|
||||
#define DS_BUILD_IN_SOUNDS 1
|
||||
#define DS_NAME_CLICK _T("drive_click_")
|
||||
#define DS_NAME_SPIN _T("drive_spin_")
|
||||
#define DS_NAME_SPIN_ND _T("drive_spinnd_")
|
||||
#define DS_NAME_START _T("drive_start_")
|
||||
#define DS_NAME_SNATCH _T("drive_snatch_")
|
||||
|
||||
extern int driveclick_fdrawcmd_open(int);
|
||||
extern void driveclick_fdrawcmd_close(int);
|
||||
extern void driveclick_fdrawcmd_detect(void);
|
||||
extern void driveclick_fdrawcmd_seek(int, int);
|
||||
extern void driveclick_fdrawcmd_motor(int, int);
|
||||
extern void driveclick_fdrawcmd_vsync(void);
|
||||
extern int driveclick_pcdrivemask, driveclick_pcdrivenum;
|
||||
|
||||
#endif /* UAE_DRIVECLICK_H */
|
|
@ -69,8 +69,9 @@ enum {
|
|||
};
|
||||
|
||||
extern int pissoff_value;
|
||||
extern uae_s32 pissoff;
|
||||
|
||||
#define countdown (regs.pissoff)
|
||||
#define countdown (pissoff)
|
||||
|
||||
extern struct ev eventtab[ev_max];
|
||||
extern struct ev2 eventtab2[ev2_max];
|
||||
|
@ -82,19 +83,19 @@ STATIC_INLINE void cycles_do_special(void)
|
|||
{
|
||||
#ifdef JIT
|
||||
if (currprefs.cachesize) {
|
||||
if (regs.pissoff >= 0)
|
||||
regs.pissoff = -1;
|
||||
if (pissoff >= 0)
|
||||
pissoff = -1;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
regs.pissoff = 0;
|
||||
pissoff = 0;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC_INLINE void do_extra_cycles (unsigned long cycles_to_add)
|
||||
{
|
||||
regs.pissoff -= cycles_to_add;
|
||||
pissoff -= cycles_to_add;
|
||||
}
|
||||
|
||||
STATIC_INLINE unsigned long int get_cycles (void)
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "uae/types.h"
|
||||
#include "readcpu.h"
|
||||
#include "machdep/m68k.h"
|
||||
#include "events.h"
|
||||
|
||||
extern const int areg_byteinc[];
|
||||
extern const int imm8_table[];
|
||||
|
@ -172,7 +173,6 @@ struct regstruct
|
|||
uae_u32 pcr;
|
||||
uae_u32 address_space_mask;
|
||||
|
||||
uae_s32 pissoff;
|
||||
uae_u8* natmem_offset;
|
||||
|
||||
#ifdef JIT
|
||||
|
|
|
@ -10,4 +10,7 @@ void uae_clipboard_put_text(const char* text);
|
|||
typedef const char * (*amiga_plugin_lookup_function)(const char *name);
|
||||
void amiga_set_plugin_lookup_function(amiga_plugin_lookup_function function);
|
||||
|
||||
typedef int (*audio_callback)(int type, int16_t* buffer, int size);
|
||||
int amiga_set_cd_audio_callback(audio_callback func);
|
||||
|
||||
#endif // LIBAMIGA_LIBAMIGA_H_
|
|
@ -31,6 +31,8 @@
|
|||
/* Need to have these somewhere */
|
||||
bool check_prefs_changed_comp (bool checkonly) { return false; }
|
||||
#endif
|
||||
/* For faster JIT cycles handling */
|
||||
uae_s32 pissoff = 0;
|
||||
|
||||
/* Opcode of faulting instruction */
|
||||
static uae_u32 last_op_for_exception_3;
|
||||
|
@ -1158,7 +1160,7 @@ static void m68k_reset(bool hardreset)
|
|||
{
|
||||
uae_u32 v;
|
||||
|
||||
regs.pissoff = 0;
|
||||
pissoff = 0;
|
||||
cpu_cycles = 0;
|
||||
|
||||
regs.halted = 0;
|
||||
|
|
|
@ -134,6 +134,7 @@ static char rp9_path[MAX_DPATH];
|
|||
static char controllers_path[MAX_DPATH];
|
||||
static char retroarch_file[MAX_DPATH];
|
||||
static char logfile_path[MAX_DPATH];
|
||||
static char floppy_sounds_dir[MAX_DPATH];
|
||||
|
||||
char last_loaded_config[MAX_DPATH] = {'\0'};
|
||||
|
||||
|
@ -529,6 +530,11 @@ void target_default_options(struct uae_prefs* p, int type)
|
|||
p->cr[0].locked = true;
|
||||
p->cr[0].rtg = true;
|
||||
_tcscpy(p->cr[0].label, _T("RTG"));
|
||||
|
||||
for (auto& floppyslot : p->floppyslots)
|
||||
{
|
||||
floppyslot.dfxclick = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void target_save_options(struct zfile* f, struct uae_prefs* p)
|
||||
|
@ -1209,6 +1215,7 @@ void load_amiberry_settings(void)
|
|||
#endif
|
||||
snprintf(rp9_path, MAX_DPATH, "%s/rp9/", start_path_data);
|
||||
snprintf(path, MAX_DPATH, "%s/conf/amiberry.conf", start_path_data);
|
||||
snprintf(floppy_sounds_dir, MAX_DPATH, "%s/data/floppy_sounds/", start_path_data);
|
||||
|
||||
auto* const fh = zfile_fopen(path, _T("r"), ZFD_NORMAL);
|
||||
if (fh)
|
||||
|
@ -2067,3 +2074,22 @@ bool handle_events()
|
|||
return pause_emulation != 0;
|
||||
}
|
||||
|
||||
bool get_plugin_path(TCHAR* out, int len, const TCHAR* path)
|
||||
{
|
||||
if (strcmp(path, "floppysounds") == 0) {
|
||||
if (floppy_sounds_dir) {
|
||||
strncpy(out, floppy_sounds_dir, len);
|
||||
}
|
||||
else {
|
||||
strncpy(out, "floppy_sounds", len);
|
||||
}
|
||||
// make sure out is null-terminated in any case
|
||||
out[len - 1] = '\0';
|
||||
}
|
||||
else {
|
||||
write_log("\n-----------------> STUB: get_plugin_path, "
|
||||
"size: %d, path: %s\n", len, path);
|
||||
out[0] = '\0';
|
||||
}
|
||||
return TRUE;
|
||||
}
|
|
@ -31,6 +31,7 @@
|
|||
#include "statusline.h"
|
||||
#include "sounddep/sound.h"
|
||||
#include "threaddep/thread.h"
|
||||
|
||||
static uae_thread_id display_tid = nullptr;
|
||||
static smp_comm_pipe *volatile display_pipe = nullptr;
|
||||
static uae_sem_t display_sem = nullptr;
|
||||
|
|
|
@ -424,7 +424,7 @@ int gui_init()
|
|||
void gui_exit()
|
||||
{
|
||||
sync();
|
||||
stop_sound();
|
||||
close_sound();
|
||||
save_amiberry_settings();
|
||||
ClearConfigFileList();
|
||||
ClearAvailableROMList();
|
||||
|
|
|
@ -1,78 +1,120 @@
|
|||
#include "sysconfig.h"
|
||||
#include "sysdeps.h"
|
||||
|
||||
#include "audio.h"
|
||||
|
||||
#include "cda_play.h"
|
||||
#include "audio.h"
|
||||
#include "options.h"
|
||||
|
||||
#include "sounddep/sound.h"
|
||||
#include "uae/uae.h"
|
||||
|
||||
cda_audio::~cda_audio()
|
||||
{
|
||||
cdaudio_active = false;
|
||||
if (active) {
|
||||
wait(0);
|
||||
wait(1);
|
||||
}
|
||||
for (int i = 0; i < 2; i++) {
|
||||
xfree (buffers[i]);
|
||||
buffers[i] = NULL;
|
||||
}
|
||||
static int (*g_audio_callback)(int type, int16_t* buffer, int size) = NULL;
|
||||
|
||||
int amiga_set_cd_audio_callback(audio_callback func) {
|
||||
g_audio_callback = func;
|
||||
return 1;
|
||||
}
|
||||
|
||||
cda_audio::cda_audio(int num_sectors, int sectorsize, int samplerate)
|
||||
cda_audio::~cda_audio()
|
||||
{
|
||||
active = false;
|
||||
playing = false;
|
||||
volume[0] = volume[1] = 0;
|
||||
currBuf = 1;
|
||||
wait(0);
|
||||
wait(1);
|
||||
|
||||
for (auto& buffer : buffers)
|
||||
{
|
||||
xfree(buffer);
|
||||
buffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bufsize = num_sectors * sectorsize;
|
||||
cda_audio::cda_audio(int num_sectors, int sectorsize, int samplerate, bool internalmode)
|
||||
{
|
||||
active = false;
|
||||
playing = false;
|
||||
volume[0] = volume[1] = 0;
|
||||
|
||||
bufsize = num_sectors * sectorsize;
|
||||
this->sectorsize = sectorsize;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
buffers[i] = xcalloc (uae_u8, num_sectors * ((bufsize + 4095) & ~4095));
|
||||
}
|
||||
this->num_sectors = num_sectors;
|
||||
active = true;
|
||||
playing = true;
|
||||
cdaudio_active = true;
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
buffer_ids[i] = 0;
|
||||
buffers[i] = xcalloc(uae_u8, num_sectors * ((bufsize + 4095) & ~4095));
|
||||
}
|
||||
this->num_sectors = num_sectors;
|
||||
|
||||
if (internalmode)
|
||||
return;
|
||||
|
||||
active = true;
|
||||
playing = true;
|
||||
}
|
||||
|
||||
void cda_audio::setvolume(int left, int right)
|
||||
void cda_audio::setvolume(int left, int right)
|
||||
{
|
||||
for (int j = 0; j < 2; j++) {
|
||||
volume[j] = j == 0 ? left : right;
|
||||
for (int j = 0; j < 2; j++)
|
||||
{
|
||||
volume[j] = j == 0 ? left : right;
|
||||
volume[j] = sound_cd_volume[j] * volume[j] / 32768;
|
||||
if (volume[j])
|
||||
volume[j]++;
|
||||
if (volume[j] >= 32768)
|
||||
volume[j] = 32768;
|
||||
}
|
||||
if (volume[j])
|
||||
volume[j]++;
|
||||
volume[j] = volume[j] * (100 - currprefs.sound_volume_master) / 100;
|
||||
if (volume[j] >= 32768)
|
||||
volume[j] = 32768;
|
||||
}
|
||||
}
|
||||
|
||||
bool cda_audio::play(int bufnum)
|
||||
bool cda_audio::play(int bufnum)
|
||||
{
|
||||
if (!active) {
|
||||
return false;
|
||||
}
|
||||
if (!active)
|
||||
return false;
|
||||
|
||||
currBuf = bufnum;
|
||||
uae_s16 *p = (uae_s16*)(buffers[bufnum]);
|
||||
for (int i = 0; i < num_sectors * sectorsize / 4; i++) {
|
||||
PUT_CDAUDIO_WORD_STEREO(p[i * 2 + 0] * volume[0] / 32768, p[i * 2 + 1] * volume[1] / 32768);
|
||||
check_cdaudio_buffers();
|
||||
}
|
||||
uae_s16* p = (uae_s16*)(buffers[bufnum]);
|
||||
for (int i = 0; i < num_sectors * sectorsize / 4; i++) {
|
||||
p[i * 2 + 0] = p[i * 2 + 0] * volume[0] / 32768;
|
||||
p[i * 2 + 1] = p[i * 2 + 1] * volume[1] / 32768;
|
||||
}
|
||||
|
||||
return cdaudio_catchup();
|
||||
if (g_audio_callback) {
|
||||
int len = num_sectors * sectorsize;
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
int8_t* d = (int8_t*)p;
|
||||
int8_t temp = 0;
|
||||
for (int i = 0; i < len; i += 2) {
|
||||
temp = d[i + 1];
|
||||
d[i + 1] = d[i];
|
||||
d[i] = temp;
|
||||
}
|
||||
#endif
|
||||
buffer_ids[bufnum] = g_audio_callback(3, p, len);
|
||||
}
|
||||
else {
|
||||
buffer_ids[bufnum] = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void cda_audio::wait(int bufnum)
|
||||
void cda_audio::wait(int bufnum)
|
||||
{
|
||||
if (!active || !playing)
|
||||
return;
|
||||
if (!active || !playing)
|
||||
return;
|
||||
|
||||
if (buffer_ids[bufnum] == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// calling g_audio_callback with NULL parameter to check status
|
||||
while (!g_audio_callback(3, NULL, buffer_ids[bufnum])) {
|
||||
Sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
bool cda_audio::isplaying(int bufnum)
|
||||
{
|
||||
if (!active || !playing)
|
||||
return false;
|
||||
return bufnum != currBuf;
|
||||
if (buffer_ids[bufnum] == 0) {
|
||||
return false;
|
||||
}
|
||||
return g_audio_callback(3, NULL, buffer_ids[bufnum]);
|
||||
}
|
||||
|
|
|
@ -1,26 +1,28 @@
|
|||
|
||||
#pragma once
|
||||
#include "audio.h"
|
||||
|
||||
extern volatile bool cd_audio_mode_changed;
|
||||
|
||||
class cda_audio
|
||||
class cda_audio
|
||||
{
|
||||
private:
|
||||
int bufsize;
|
||||
int sectorsize;
|
||||
int volume[2];
|
||||
bool playing;
|
||||
bool active;
|
||||
int currBuf;
|
||||
int num_sectors;
|
||||
int bufsize;
|
||||
int volume[2];
|
||||
bool playing;
|
||||
bool active;
|
||||
int buffer_ids[2];
|
||||
|
||||
public:
|
||||
uae_u8 *buffers[2];
|
||||
|
||||
cda_audio(int num_sectors, int sectorsize, int samplerate);
|
||||
~cda_audio();
|
||||
void setvolume(int left, int right);
|
||||
bool play(int bufnum);
|
||||
void wait(void);
|
||||
void wait(int bufnum);
|
||||
uae_u8 *buffers[2];
|
||||
int num_sectors;
|
||||
int sectorsize;
|
||||
|
||||
cda_audio(int num_sectors, int sectorsize, int samplerate, bool internalmode);
|
||||
~cda_audio();
|
||||
void setvolume(int left, int right);
|
||||
bool play(int bufnum);
|
||||
void wait(void);
|
||||
void wait(int bufnum);
|
||||
bool isplaying(int bufnum);
|
||||
};
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#define MAX_DPATH 4096
|
||||
#endif
|
||||
|
||||
/* #define DRIVESOUND */
|
||||
#define DRIVESOUND
|
||||
/* #define GFXFILTER */
|
||||
//#define USE_SOFT_LONG_DOUBLE
|
||||
#define PACKAGE_STRING "AMIBERRY"
|
||||
|
|
|
@ -57,8 +57,6 @@ void update_display(struct uae_prefs*);
|
|||
void black_screen_now(void);
|
||||
void graphics_subshutdown(void);
|
||||
|
||||
void stop_sound();
|
||||
|
||||
void keyboard_settrans();
|
||||
void set_mouse_grab(bool grab);
|
||||
|
||||
|
@ -221,3 +219,12 @@ void restore_host_fp_regs(void* buf);
|
|||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define MAX_SOUND_DEVICES 100
|
||||
#define SOUND_DEVICE_DS 1
|
||||
#define SOUND_DEVICE_AL 2
|
||||
#define SOUND_DEVICE_PA 3
|
||||
#define SOUND_DEVICE_WASAPI 4
|
||||
#define SOUND_DEVICE_WASAPI_EXCLUSIVE 5
|
||||
#define SOUND_DEVICE_XAUDIO2 6
|
||||
#define SOUND_DEVICE_SDL2 7
|
||||
|
|
|
@ -2,245 +2,385 @@
|
|||
* Sdl sound.c implementation
|
||||
* (c) 2015
|
||||
*/
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include "sysconfig.h"
|
||||
#include "sysdeps.h"
|
||||
#include "uae.h"
|
||||
|
||||
#include "options.h"
|
||||
#include "audio.h"
|
||||
#include "gensound.h"
|
||||
#include "sounddep/sound.h"
|
||||
#include "events.h"
|
||||
#include "custom.h"
|
||||
#include "threaddep/thread.h"
|
||||
#include "gui.h"
|
||||
#include "savestate.h"
|
||||
#ifdef DRIVESOUND
|
||||
#include "driveclick.h"
|
||||
#endif
|
||||
#include "gensound.h"
|
||||
#include "xwin.h"
|
||||
#include "sounddep/sound.h"
|
||||
|
||||
#ifdef ANDROID
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
|
||||
// "consumer" means the actual SDL sound output, as opposed to
|
||||
#define SOUND_CONSUMER_BUFFER_LENGTH (SNDBUFFER_LEN * SOUND_BUFFERS_COUNT / 4)
|
||||
struct sound_dp
|
||||
{
|
||||
int sndbufsize;
|
||||
int framesperbuffer;
|
||||
int sndbuf;
|
||||
int pullmode;
|
||||
uae_u8* pullbuffer;
|
||||
int pullbufferlen;
|
||||
int pullbuffermaxlen;
|
||||
double avg_correct;
|
||||
double cnt_correct;
|
||||
};
|
||||
|
||||
uae_u16 sndbuffer[SOUND_BUFFERS_COUNT][(SNDBUFFER_LEN + 32) * DEFAULT_SOUND_CHANNELS];
|
||||
uae_u16* sndbufpt = sndbuffer[0];
|
||||
uae_u16* render_sndbuff = sndbuffer[0];
|
||||
uae_u16* finish_sndbuff = sndbuffer[0] + SNDBUFFER_LEN * DEFAULT_SOUND_CHANNELS;
|
||||
#define SND_STATUSCNT 10
|
||||
|
||||
uae_u16 cdaudio_buffer[CDAUDIO_BUFFERS][(CDAUDIO_BUFFER_LEN + 32) * DEFAULT_SOUND_CHANNELS];
|
||||
uae_u16* cdbufpt = cdaudio_buffer[0];
|
||||
uae_u16* render_cdbuff = cdaudio_buffer[0];
|
||||
uae_u16* finish_cdbuff = cdaudio_buffer[0] + CDAUDIO_BUFFER_LEN * DEFAULT_SOUND_CHANNELS;
|
||||
bool cdaudio_active = false;
|
||||
static int cdwrcnt = 0;
|
||||
static int cdrdcnt = 0;
|
||||
#define ADJUST_SIZE 20
|
||||
#define EXP 1.9
|
||||
|
||||
#define ADJUST_VSSIZE 12
|
||||
#define EXPVS 1.6
|
||||
|
||||
static int have_sound = 0;
|
||||
static int statuscnt;
|
||||
|
||||
void update_sound(double clk)
|
||||
#define SND_MAX_BUFFER2 524288
|
||||
#define SND_MAX_BUFFER 65536
|
||||
|
||||
//uae_u16 paula_sndbuffer[SND_MAX_BUFFER];
|
||||
uae_u16 paula_sndbuffer[SND_MAX_BUFFER];
|
||||
uae_u16* paula_sndbufpt;
|
||||
int paula_sndbufsize;
|
||||
|
||||
SDL_AudioSpec want, have;
|
||||
SDL_AudioDeviceID dev;
|
||||
|
||||
void sdl2_audio_callback(void* userdata, Uint8* stream, int len);
|
||||
|
||||
struct sound_device* sound_devices[MAX_SOUND_DEVICES];
|
||||
struct sound_device* record_devices[MAX_SOUND_DEVICES];
|
||||
|
||||
static struct sound_data sdpaula;
|
||||
static struct sound_data* sdp = &sdpaula;
|
||||
|
||||
static uae_u8* extrasndbuf;
|
||||
static int extrasndbufsize;
|
||||
static int extrasndbuffered;
|
||||
|
||||
|
||||
int setup_sound(void)
|
||||
{
|
||||
const auto evtime = clk * CYCLE_UNIT / double(currprefs.sound_freq);
|
||||
scaled_sample_evtime = evtime;
|
||||
}
|
||||
|
||||
|
||||
static int s_oldrate = 0, s_oldbits = 0, s_oldstereo = 0;
|
||||
static int sound_thread_active = 0, sound_thread_exit = 0;
|
||||
static int rdcnt = 0;
|
||||
static int wrcnt = 0;
|
||||
|
||||
|
||||
static void sound_copy_produced_block(void* ud, Uint8* stream, int len)
|
||||
{
|
||||
if (currprefs.sound_stereo)
|
||||
{
|
||||
if (cdaudio_active && currprefs.sound_freq == 44100 && cdrdcnt < cdwrcnt)
|
||||
{
|
||||
for (auto i = 0; i < SNDBUFFER_LEN * 2; ++i)
|
||||
sndbuffer[rdcnt & SOUND_BUFFERS_COUNT - 1][i] += cdaudio_buffer[cdrdcnt & CDAUDIO_BUFFERS - 1][i];
|
||||
cdrdcnt++;
|
||||
}
|
||||
|
||||
memcpy(stream, sndbuffer[rdcnt & SOUND_BUFFERS_COUNT - 1], len);
|
||||
}
|
||||
else
|
||||
memcpy(stream, sndbuffer[rdcnt & SOUND_BUFFERS_COUNT - 1], len);
|
||||
|
||||
if (wrcnt - rdcnt >= SOUND_BUFFERS_COUNT / 2)
|
||||
{
|
||||
rdcnt++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void sound_thread_mixer(void* ud, Uint8* stream, int len)
|
||||
{
|
||||
if (sound_thread_exit)
|
||||
return;
|
||||
sound_thread_active = 1;
|
||||
|
||||
const auto sample_size = currprefs.sound_stereo ? 4 : 2;
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
int l = len < SNDBUFFER_LEN * sample_size ? len : SNDBUFFER_LEN * sample_size;
|
||||
sound_copy_produced_block(ud, stream, l);
|
||||
stream += l;
|
||||
len -= l;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void init_soundbuffer_usage()
|
||||
{
|
||||
sndbufpt = sndbuffer[0];
|
||||
render_sndbuff = sndbuffer[0];
|
||||
finish_sndbuff = sndbuffer[0] + SNDBUFFER_LEN * 2;
|
||||
rdcnt = 0;
|
||||
wrcnt = 0;
|
||||
|
||||
cdbufpt = cdaudio_buffer[0];
|
||||
render_cdbuff = cdaudio_buffer[0];
|
||||
finish_cdbuff = cdaudio_buffer[0] + CDAUDIO_BUFFER_LEN * 2;
|
||||
cdrdcnt = 0;
|
||||
cdwrcnt = 0;
|
||||
}
|
||||
|
||||
|
||||
static int start_sound(int rate, int bits, int stereo)
|
||||
{
|
||||
int frag = 0, buffers, ret;
|
||||
unsigned int bsize;
|
||||
|
||||
if (SDL_GetAudioStatus() == SDL_AUDIO_STOPPED)
|
||||
{
|
||||
init_soundbuffer_usage();
|
||||
|
||||
s_oldrate = 0;
|
||||
s_oldbits = 0;
|
||||
s_oldstereo = 0;
|
||||
|
||||
sound_thread_exit = 0;
|
||||
}
|
||||
|
||||
// if no settings change, we don't need to do anything
|
||||
if (rate == s_oldrate && s_oldbits == bits && s_oldstereo == stereo)
|
||||
return 0;
|
||||
|
||||
|
||||
SDL_AudioSpec as;
|
||||
memset(&as, 0, sizeof(as));
|
||||
|
||||
as.freq = rate;
|
||||
as.format = (bits == 8 ? AUDIO_S8 : AUDIO_S16);
|
||||
as.channels = (stereo ? 2 : 1);
|
||||
as.samples = SOUND_CONSUMER_BUFFER_LENGTH;
|
||||
as.callback = sound_thread_mixer;
|
||||
|
||||
if (SDL_OpenAudio(&as, nullptr))
|
||||
write_log("Error when opening SDL audio !\n");
|
||||
|
||||
s_oldrate = rate;
|
||||
s_oldbits = bits;
|
||||
s_oldstereo = stereo;
|
||||
|
||||
clear_sound_buffers();
|
||||
clear_cdaudio_buffers();
|
||||
|
||||
SDL_PauseAudio(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void stop_sound()
|
||||
{
|
||||
if (sound_thread_exit == 0)
|
||||
{
|
||||
SDL_PauseAudio(1);
|
||||
sound_thread_exit = 1;
|
||||
SDL_CloseAudio();
|
||||
}
|
||||
}
|
||||
|
||||
void finish_sound_buffer()
|
||||
{
|
||||
wrcnt++;
|
||||
sndbufpt = render_sndbuff = sndbuffer[wrcnt & SOUND_BUFFERS_COUNT - 1];
|
||||
|
||||
if (currprefs.sound_stereo)
|
||||
finish_sndbuff = sndbufpt + SNDBUFFER_LEN * 2;
|
||||
else
|
||||
finish_sndbuff = sndbufpt + SNDBUFFER_LEN;
|
||||
|
||||
while ((wrcnt & SOUND_BUFFERS_COUNT - 1) == (rdcnt & SOUND_BUFFERS_COUNT - 1))
|
||||
{
|
||||
usleep(500);
|
||||
}
|
||||
}
|
||||
|
||||
void pause_sound_buffer()
|
||||
{
|
||||
reset_sound();
|
||||
}
|
||||
|
||||
void restart_sound_buffer()
|
||||
{
|
||||
sndbufpt = render_sndbuff = sndbuffer[wrcnt & (SOUND_BUFFERS_COUNT - 1)];
|
||||
if (currprefs.sound_stereo)
|
||||
finish_sndbuff = sndbufpt + SNDBUFFER_LEN * 2;
|
||||
else
|
||||
finish_sndbuff = sndbufpt + SNDBUFFER_LEN;
|
||||
|
||||
cdbufpt = render_cdbuff = cdaudio_buffer[cdwrcnt & (CDAUDIO_BUFFERS - 1)];
|
||||
finish_cdbuff = cdbufpt + CDAUDIO_BUFFER_LEN * 2;
|
||||
}
|
||||
|
||||
void finish_cdaudio_buffer()
|
||||
{
|
||||
cdwrcnt++;
|
||||
cdbufpt = render_cdbuff = cdaudio_buffer[cdwrcnt & (CDAUDIO_BUFFERS - 1)];
|
||||
finish_cdbuff = cdbufpt + CDAUDIO_BUFFER_LEN * 2;
|
||||
audio_activate();
|
||||
}
|
||||
|
||||
|
||||
bool cdaudio_catchup()
|
||||
{
|
||||
while (cdwrcnt > cdrdcnt + CDAUDIO_BUFFERS - 10 && sound_thread_active != 0 && quit_program == 0)
|
||||
{
|
||||
sleep_millis(10);
|
||||
}
|
||||
return sound_thread_active != 0;
|
||||
}
|
||||
|
||||
/* Try to determine whether sound is available. This is only for GUI purposes. */
|
||||
int setup_sound()
|
||||
{
|
||||
if (start_sound(currprefs.sound_freq, 16, currprefs.sound_stereo) != 0)
|
||||
return 0;
|
||||
|
||||
sound_available = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
float sound_sync_multiplier = 1.0;
|
||||
float scaled_sample_evtime_orig;
|
||||
// Originally from sampler.cpp
|
||||
float sampler_evtime;
|
||||
|
||||
void update_sound(double clk)
|
||||
{
|
||||
if (!have_sound)
|
||||
return;
|
||||
scaled_sample_evtime_orig = clk * CYCLE_UNIT * sound_sync_multiplier / sdp->obtainedfreq;
|
||||
scaled_sample_evtime = scaled_sample_evtime_orig;
|
||||
sampler_evtime = clk * CYCLE_UNIT * sound_sync_multiplier;
|
||||
}
|
||||
|
||||
extern int vsynctimebase_orig;
|
||||
|
||||
#define ADJUST_LIMIT 6
|
||||
#define ADJUST_LIMIT2 1
|
||||
|
||||
void sound_setadjust(double v)
|
||||
{
|
||||
float mult;
|
||||
|
||||
if (v < -ADJUST_LIMIT)
|
||||
v = -ADJUST_LIMIT;
|
||||
if (v > ADJUST_LIMIT)
|
||||
v = ADJUST_LIMIT;
|
||||
|
||||
mult = 1000.0 + v;
|
||||
if (isvsync_chipset()) {
|
||||
vsynctimebase = vsynctimebase_orig;
|
||||
scaled_sample_evtime = scaled_sample_evtime_orig * mult / 1000.0;
|
||||
}
|
||||
else if (currprefs.cachesize || currprefs.m68k_speed != 0) {
|
||||
vsynctimebase = (int)(((double)vsynctimebase_orig) * mult / 1000.0);
|
||||
scaled_sample_evtime = scaled_sample_evtime_orig;
|
||||
}
|
||||
else {
|
||||
vsynctimebase = (int)(((double)vsynctimebase_orig) * mult / 1000.0);
|
||||
scaled_sample_evtime = scaled_sample_evtime_orig;
|
||||
}
|
||||
}
|
||||
|
||||
static void docorrection(struct sound_dp* s, int sndbuf, double sync, int granulaty)
|
||||
{
|
||||
static int tfprev;
|
||||
|
||||
s->avg_correct += sync;
|
||||
s->cnt_correct++;
|
||||
|
||||
if (granulaty < 10)
|
||||
granulaty = 10;
|
||||
|
||||
if (tfprev != timeframes) {
|
||||
double skipmode, avgskipmode;
|
||||
double avg = s->avg_correct / s->cnt_correct;
|
||||
|
||||
skipmode = sync / 100.0;
|
||||
avgskipmode = avg / (10000.0 / granulaty);
|
||||
|
||||
gui_data.sndbuf = sndbuf;
|
||||
|
||||
if (skipmode > ADJUST_LIMIT2)
|
||||
skipmode = ADJUST_LIMIT2;
|
||||
if (skipmode < -ADJUST_LIMIT2)
|
||||
skipmode = -ADJUST_LIMIT2;
|
||||
|
||||
sound_setadjust(skipmode + avgskipmode);
|
||||
tfprev = timeframes;
|
||||
}
|
||||
}
|
||||
|
||||
static double sync_sound(double m)
|
||||
{
|
||||
double skipmode;
|
||||
if (isvsync()) {
|
||||
|
||||
skipmode = pow(m < 0 ? -m : m, EXPVS) / 2;
|
||||
if (m < 0)
|
||||
skipmode = -skipmode;
|
||||
if (skipmode < -ADJUST_VSSIZE)
|
||||
skipmode = -ADJUST_VSSIZE;
|
||||
if (skipmode > ADJUST_VSSIZE)
|
||||
skipmode = ADJUST_VSSIZE;
|
||||
|
||||
}
|
||||
else if (1) {
|
||||
|
||||
skipmode = pow(m < 0 ? -m : m, EXP) / 2;
|
||||
if (m < 0)
|
||||
skipmode = -skipmode;
|
||||
if (skipmode < -ADJUST_SIZE)
|
||||
skipmode = -ADJUST_SIZE;
|
||||
if (skipmode > ADJUST_SIZE)
|
||||
skipmode = ADJUST_SIZE;
|
||||
}
|
||||
|
||||
return skipmode;
|
||||
}
|
||||
|
||||
static void clearbuffer_sdl2(struct sound_data *sd)
|
||||
{
|
||||
SDL_LockAudioDevice(dev);
|
||||
SDL_memset(paula_sndbuffer, 0, sizeof paula_sndbuffer);
|
||||
SDL_UnlockAudioDevice(dev);
|
||||
}
|
||||
|
||||
static void clearbuffer(struct sound_data* sd)
|
||||
{
|
||||
struct sound_dp* s = sd->data;
|
||||
clearbuffer_sdl2(sd);
|
||||
if (s->pullbuffer) {
|
||||
memset(s->pullbuffer, 0, s->pullbuffermaxlen);
|
||||
}
|
||||
}
|
||||
|
||||
static void set_reset(struct sound_data* sd)
|
||||
{
|
||||
sd->reset = true;
|
||||
sd->resetcnt = 10;
|
||||
sd->resetframecnt = 0;
|
||||
}
|
||||
|
||||
static void pause_audio_sdl2(struct sound_data* sd)
|
||||
{
|
||||
sd->waiting_for_buffer = 0;
|
||||
SDL_PauseAudioDevice(dev, 1);
|
||||
clearbuffer(sd);
|
||||
}
|
||||
|
||||
static void resume_audio_sdl2(struct sound_data* sd)
|
||||
{
|
||||
struct sound_dp* s = sd->data;
|
||||
sd->paused = 0;
|
||||
clearbuffer(sd);
|
||||
sd->waiting_for_buffer = 1;
|
||||
s->avg_correct = 0;
|
||||
s->cnt_correct = 0;
|
||||
SDL_PauseAudioDevice(dev, 0);
|
||||
}
|
||||
|
||||
static void close_audio_sdl2(struct sound_data* sd)
|
||||
{
|
||||
struct sound_dp* s = sd->data;
|
||||
SDL_PauseAudioDevice(dev, 1);
|
||||
// shut everything down
|
||||
SDL_CloseAudioDevice(dev);
|
||||
xfree(s->pullbuffer);
|
||||
s->pullbuffer = NULL;
|
||||
s->pullbufferlen = 0;
|
||||
}
|
||||
|
||||
void set_volume_sound_device(struct sound_data* sd, int volume, int mute)
|
||||
{
|
||||
//todo
|
||||
}
|
||||
|
||||
void set_volume(int volume, int mute)
|
||||
{
|
||||
set_volume_sound_device(sdp, volume, mute);
|
||||
//setvolume_ahi(volume);
|
||||
config_changed = 1;
|
||||
}
|
||||
|
||||
static void finish_sound_buffer_pull(struct sound_data* sd, uae_u16* sndbuffer)
|
||||
{
|
||||
struct sound_dp* s = sd->data;
|
||||
|
||||
if (s->pullbufferlen + sd->sndbufsize > s->pullbuffermaxlen) {
|
||||
write_log(_T("pull overflow! %d %d %d\n"), s->pullbufferlen, sd->sndbufsize, s->pullbuffermaxlen);
|
||||
s->pullbufferlen = 0;
|
||||
}
|
||||
memcpy(s->pullbuffer + s->pullbufferlen, sndbuffer, sd->sndbufsize);
|
||||
s->pullbufferlen += sd->sndbufsize;
|
||||
}
|
||||
|
||||
static int open_audio_sdl2(struct sound_data* sd, int index)
|
||||
{
|
||||
struct sound_dp* s = sd->data;
|
||||
int freq = sd->freq;
|
||||
int ch = sd->channels;
|
||||
int size;
|
||||
|
||||
sd->devicetype = SOUND_DEVICE_SDL2;
|
||||
if (sd->sndbufsize < 0x80)
|
||||
sd->sndbufsize = 0x80;
|
||||
s->framesperbuffer = sd->sndbufsize;
|
||||
s->sndbufsize = s->framesperbuffer;
|
||||
sd->sndbufsize = s->sndbufsize * ch * 2;
|
||||
if (sd->sndbufsize > SND_MAX_BUFFER)
|
||||
sd->sndbufsize = SND_MAX_BUFFER;
|
||||
|
||||
SDL_memset(&want, 0, sizeof want);
|
||||
want.freq = freq;
|
||||
want.format = AUDIO_S16;
|
||||
want.channels = ch;
|
||||
want.samples = s->framesperbuffer;
|
||||
want.callback = sdl2_audio_callback;
|
||||
want.userdata = sd;
|
||||
|
||||
sd->samplesize = ch * 16 / 8;
|
||||
s->pullmode = 1;
|
||||
|
||||
dev = SDL_OpenAudioDevice(nullptr, 0, &want, &have, 0);
|
||||
if (dev == 0)
|
||||
SDL_Log("Failed to open audio: %s", SDL_GetError());
|
||||
|
||||
s->pullbuffermaxlen = sd->sndbufsize * 2;
|
||||
s->pullbuffer = xcalloc(uae_u8, s->pullbuffermaxlen);
|
||||
s->pullbufferlen = 0;
|
||||
|
||||
clear_sound_buffers();
|
||||
SDL_PauseAudioDevice(dev, 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int open_sound_device(struct sound_data* sd, int index, int bufsize, int freq, int channels)
|
||||
{
|
||||
int ret = 0;
|
||||
struct sound_dp* sdp = xcalloc(struct sound_dp, 1);
|
||||
|
||||
sd->data = sdp;
|
||||
sd->sndbufsize = bufsize;
|
||||
sd->freq = freq;
|
||||
sd->channels = channels;
|
||||
sd->paused = 1;
|
||||
sd->index = index;
|
||||
ret = open_audio_sdl2(sd, index);
|
||||
sd->samplesize = sd->channels * 2;
|
||||
sd->sndbufframes = sd->sndbufsize / sd->samplesize;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void close_sound_device(struct sound_data* sd)
|
||||
{
|
||||
pause_sound_device(sd);
|
||||
close_audio_sdl2(sd);
|
||||
xfree(sd->data);
|
||||
sd->data = NULL;
|
||||
sd->index = -1;
|
||||
}
|
||||
|
||||
void pause_sound_device(struct sound_data* sd)
|
||||
{
|
||||
struct sound_dp* s = sd->data;
|
||||
sd->paused = 1;
|
||||
gui_data.sndbuf_status = 0;
|
||||
gui_data.sndbuf = 0;
|
||||
pause_audio_sdl2(sd);
|
||||
}
|
||||
void resume_sound_device(struct sound_data* sd)
|
||||
{
|
||||
struct sound_dp* s = sd->data;
|
||||
resume_audio_sdl2(sd);
|
||||
sd->paused = 0;
|
||||
}
|
||||
|
||||
static int open_sound()
|
||||
{
|
||||
config_changed = 1;
|
||||
if (start_sound(currprefs.sound_freq, 16, currprefs.sound_stereo) != 0)
|
||||
int ret = 0, ch;
|
||||
int size = currprefs.sound_maxbsiz;
|
||||
|
||||
if (!currprefs.produce_sound) {
|
||||
return 0;
|
||||
}
|
||||
config_changed = 1;
|
||||
/* Always interpret buffer size as number of samples, not as actual
|
||||
buffer size. Of course, since 8192 is the default, we'll have to
|
||||
scale that to a sane value (assuming that otherwise 16 bits and
|
||||
stereo would have been enabled and we'd have done the shift by
|
||||
two anyway). */
|
||||
size >>= 2;
|
||||
size &= ~63;
|
||||
|
||||
sdp->softvolume = -1;
|
||||
ch = get_audio_nativechannels(currprefs.sound_stereo);
|
||||
ret = open_sound_device(sdp, 0, size, currprefs.sound_freq, ch);
|
||||
if (!ret)
|
||||
return 0;
|
||||
currprefs.sound_freq = changed_prefs.sound_freq = sdp->freq;
|
||||
if (ch != sdp->channels)
|
||||
currprefs.sound_stereo = changed_prefs.sound_stereo = get_audio_stereomode(sdp->channels);
|
||||
|
||||
set_volume(currprefs.sound_volume_master, sdp->mute);
|
||||
if (get_audio_amigachannels(currprefs.sound_stereo) == 4)
|
||||
sample_handler = sample16ss_handler;
|
||||
else
|
||||
sample_handler = get_audio_ismono(currprefs.sound_stereo) ? sample16_handler : sample16s_handler;
|
||||
|
||||
sdp->obtainedfreq = currprefs.sound_freq;
|
||||
|
||||
have_sound = 1;
|
||||
sound_available = 1;
|
||||
|
||||
gui_data.sndbuf_avail = true;
|
||||
|
||||
if (currprefs.sound_stereo)
|
||||
sample_handler = sample16s_handler;
|
||||
else
|
||||
sample_handler = sample16_handler;
|
||||
|
||||
gui_data.sndbuf_avail = audio_is_pull() == 0;
|
||||
|
||||
paula_sndbufsize = sdp->sndbufsize;
|
||||
paula_sndbufpt = paula_sndbuffer;
|
||||
#ifdef DRIVESOUND
|
||||
driveclick_init();
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -253,9 +393,42 @@ void close_sound()
|
|||
if (!have_sound)
|
||||
return;
|
||||
|
||||
stop_sound();
|
||||
|
||||
close_sound_device(sdp);
|
||||
have_sound = 0;
|
||||
extrasndbufsize = 0;
|
||||
extrasndbuffered = 0;
|
||||
xfree(extrasndbuf);
|
||||
extrasndbuf = NULL;
|
||||
}
|
||||
|
||||
bool sound_paused(void)
|
||||
{
|
||||
return sdp->paused != 0;
|
||||
}
|
||||
|
||||
void pause_sound()
|
||||
{
|
||||
if (sdp->paused)
|
||||
return;
|
||||
if (!have_sound)
|
||||
return;
|
||||
pause_sound_device(sdp);
|
||||
}
|
||||
|
||||
void resume_sound()
|
||||
{
|
||||
if (!sdp->paused)
|
||||
return;
|
||||
if (!have_sound)
|
||||
return;
|
||||
resume_sound_device(sdp);
|
||||
}
|
||||
|
||||
void reset_sound()
|
||||
{
|
||||
if (!have_sound)
|
||||
return;
|
||||
clearbuffer(sdp);
|
||||
}
|
||||
|
||||
int init_sound()
|
||||
|
@ -263,33 +436,304 @@ int init_sound()
|
|||
gui_data.sndbuf_status = 3;
|
||||
gui_data.sndbuf = 0;
|
||||
gui_data.sndbuf_avail = false;
|
||||
have_sound = open_sound();
|
||||
return have_sound;
|
||||
if (!sound_available)
|
||||
return 0;
|
||||
if (currprefs.produce_sound <= 1)
|
||||
return 0;
|
||||
if (have_sound)
|
||||
return 1;
|
||||
if (!open_sound())
|
||||
return 0;
|
||||
sdp->paused = 1;
|
||||
#ifdef DRIVESOUND
|
||||
driveclick_reset();
|
||||
#endif
|
||||
reset_sound();
|
||||
resume_sound();
|
||||
return 1;
|
||||
}
|
||||
|
||||
void pause_sound()
|
||||
static void disable_sound(void)
|
||||
{
|
||||
SDL_PauseAudio(1);
|
||||
close_sound();
|
||||
currprefs.produce_sound = changed_prefs.produce_sound = 1;
|
||||
}
|
||||
|
||||
void resume_sound()
|
||||
static int reopen_sound(void)
|
||||
{
|
||||
SDL_PauseAudio(0);
|
||||
bool paused = sdp->paused != 0;
|
||||
close_sound();
|
||||
int v = open_sound();
|
||||
if (v && !paused)
|
||||
resume_sound_device(sdp);
|
||||
return v;
|
||||
}
|
||||
|
||||
void reset_sound()
|
||||
void pause_sound_buffer(void)
|
||||
{
|
||||
sdp->deactive = true;
|
||||
reset_sound();
|
||||
}
|
||||
|
||||
void restart_sound_buffer(void)
|
||||
{
|
||||
sdp->deactive = false;
|
||||
//restart_sound_buffer2(sdp);
|
||||
}
|
||||
|
||||
static void channelswap(uae_s16* sndbuffer, int len)
|
||||
{
|
||||
for (int i = 0; i < len; i += 2) {
|
||||
uae_s16 t;
|
||||
t = sndbuffer[i];
|
||||
sndbuffer[i] = sndbuffer[i + 1];
|
||||
sndbuffer[i + 1] = t;
|
||||
}
|
||||
}
|
||||
static void channelswap6(uae_s16* sndbuffer, int len)
|
||||
{
|
||||
for (int i = 0; i < len; i += 6) {
|
||||
uae_s16 t;
|
||||
t = sndbuffer[i + 0];
|
||||
sndbuffer[i + 0] = sndbuffer[i + 1];
|
||||
sndbuffer[i + 1] = t;
|
||||
t = sndbuffer[i + 4];
|
||||
sndbuffer[i + 4] = sndbuffer[i + 5];
|
||||
sndbuffer[i + 5] = t;
|
||||
}
|
||||
}
|
||||
|
||||
static void send_sound(struct sound_data* sd, uae_u16* sndbuffer)
|
||||
{
|
||||
if (savestate_state)
|
||||
return;
|
||||
if (sd->paused)
|
||||
return;
|
||||
if (sd->softvolume >= 0) {
|
||||
uae_s16* p = (uae_s16*)sndbuffer;
|
||||
for (int i = 0; i < sd->sndbufsize / 2; i++) {
|
||||
p[i] = p[i] * sd->softvolume / 32768;
|
||||
}
|
||||
}
|
||||
|
||||
finish_sound_buffer_pull(sd, sndbuffer);
|
||||
}
|
||||
|
||||
bool audio_is_event_frame_possible(int)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int audio_is_pull(void)
|
||||
{
|
||||
if (sdp->reset)
|
||||
return 0;
|
||||
struct sound_dp* s = sdp->data;
|
||||
if (s && s->pullmode) {
|
||||
return sdp->paused || sdp->deactive ? -1 : 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int audio_pull_buffer(void)
|
||||
{
|
||||
int cnt = 0;
|
||||
if (sdp->paused || sdp->deactive || sdp->reset)
|
||||
return 0;
|
||||
struct sound_dp* s = sdp->data;
|
||||
if (s->pullbufferlen > 0) {
|
||||
cnt++;
|
||||
int size = (uae_u8*)paula_sndbufpt - (uae_u8*)paula_sndbuffer;
|
||||
if (size > sdp->sndbufsize * 2 / 3)
|
||||
cnt++;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
bool audio_is_pull_event(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool audio_finish_pull(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static void handle_reset(void)
|
||||
{
|
||||
if (sdp->resetframe == timeframes)
|
||||
return;
|
||||
sdp->resetframe = timeframes;
|
||||
sdp->resetframecnt--;
|
||||
if (sdp->resetframecnt > 0)
|
||||
return;
|
||||
sdp->resetframecnt = 20;
|
||||
|
||||
sdp->reset = false;
|
||||
if (!reopen_sound() || sdp->reset) {
|
||||
if (sdp->resetcnt <= 0) {
|
||||
write_log(_T("Reopen sound failed. Retrying with default device.\n"));
|
||||
close_sound();
|
||||
//int type = sound_devices[currprefs.win32_soundcard]->type;
|
||||
//int max = enumerate_sound_devices();
|
||||
//for (int i = 0; i < max; i++) {
|
||||
// if (sound_devices[i]->alname == NULL && sound_devices[i]->type == type) {
|
||||
// currprefs.win32_soundcard = changed_prefs.win32_soundcard = i;
|
||||
// if (open_sound())
|
||||
// return;
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
currprefs.produce_sound = changed_prefs.produce_sound = 1;
|
||||
}
|
||||
else {
|
||||
write_log(_T("Retrying sound.. %d..\n"), sdp->resetcnt);
|
||||
sdp->resetcnt--;
|
||||
sdp->reset = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
resume_sound_device(sdp);
|
||||
}
|
||||
}
|
||||
|
||||
void finish_sound_buffer()
|
||||
{
|
||||
static unsigned long tframe;
|
||||
int bufsize = (uae_u8*)paula_sndbufpt - (uae_u8*)paula_sndbuffer;
|
||||
|
||||
if (sdp->reset) {
|
||||
handle_reset();
|
||||
paula_sndbufpt = paula_sndbuffer;
|
||||
return;
|
||||
}
|
||||
|
||||
if (currprefs.turbo_emulation) {
|
||||
paula_sndbufpt = paula_sndbuffer;
|
||||
return;
|
||||
}
|
||||
if (currprefs.sound_stereo_swap_paula) {
|
||||
if (get_audio_nativechannels(currprefs.sound_stereo) == 2 || get_audio_nativechannels(currprefs.sound_stereo) == 4)
|
||||
channelswap((uae_s16*)paula_sndbuffer, bufsize / 2);
|
||||
else if (get_audio_nativechannels(currprefs.sound_stereo) == 6)
|
||||
channelswap6((uae_s16*)paula_sndbuffer, bufsize / 2);
|
||||
}
|
||||
#ifdef DRIVESOUND
|
||||
driveclick_mix((uae_s16*)paula_sndbuffer, bufsize / 2, currprefs.dfxclickchannelmask);
|
||||
#endif
|
||||
// must be after driveclick_mix
|
||||
paula_sndbufpt = paula_sndbuffer;
|
||||
|
||||
if (!have_sound)
|
||||
return;
|
||||
|
||||
init_soundbuffer_usage();
|
||||
// we got buffer that was not full (recording active). Need special handling.
|
||||
if (bufsize < sdp->sndbufsize && !extrasndbuf) {
|
||||
extrasndbufsize = sdp->sndbufsize;
|
||||
extrasndbuf = xcalloc(uae_u8, sdp->sndbufsize);
|
||||
extrasndbuffered = 0;
|
||||
}
|
||||
|
||||
clear_sound_buffers();
|
||||
clear_cdaudio_buffers();
|
||||
if (statuscnt > 0 && tframe != timeframes) {
|
||||
tframe = timeframes;
|
||||
statuscnt--;
|
||||
if (statuscnt == 0)
|
||||
gui_data.sndbuf_status = 0;
|
||||
}
|
||||
if (gui_data.sndbuf_status == 3)
|
||||
gui_data.sndbuf_status = 0;
|
||||
|
||||
if (extrasndbuf) {
|
||||
int size = extrasndbuffered + bufsize;
|
||||
int copied = 0;
|
||||
if (size > extrasndbufsize) {
|
||||
copied = extrasndbufsize - extrasndbuffered;
|
||||
memcpy(extrasndbuf + extrasndbuffered, paula_sndbuffer, copied);
|
||||
send_sound(sdp, (uae_u16*)extrasndbuf);
|
||||
extrasndbuffered = 0;
|
||||
}
|
||||
memcpy(extrasndbuf + extrasndbuffered, (uae_u8*)paula_sndbuffer + copied, bufsize - copied);
|
||||
extrasndbuffered += bufsize - copied;
|
||||
}
|
||||
else {
|
||||
send_sound(sdp, paula_sndbuffer);
|
||||
}
|
||||
}
|
||||
|
||||
static int set_master_volume(int volume, int mute)
|
||||
{
|
||||
//todo set volume using SDL2
|
||||
}
|
||||
|
||||
static int get_master_volume(int* volume, int* mute)
|
||||
{
|
||||
//todo get volume using SDL2
|
||||
}
|
||||
|
||||
void sound_mute(int newmute)
|
||||
{
|
||||
if (newmute < 0)
|
||||
sdp->mute = sdp->mute ? 0 : 1;
|
||||
else
|
||||
sdp->mute = newmute;
|
||||
set_volume(currprefs.sound_volume_master, sdp->mute);
|
||||
config_changed = 1;
|
||||
}
|
||||
|
||||
void sound_volume(int dir)
|
||||
{
|
||||
currprefs.sound_volume_master -= dir * 10;
|
||||
currprefs.sound_volume_cd -= dir * 10;
|
||||
if (currprefs.sound_volume_master < 0)
|
||||
currprefs.sound_volume_master = 0;
|
||||
if (currprefs.sound_volume_master > 100)
|
||||
currprefs.sound_volume_master = 100;
|
||||
changed_prefs.sound_volume_master = currprefs.sound_volume_master;
|
||||
if (currprefs.sound_volume_cd < 0)
|
||||
currprefs.sound_volume_cd = 0;
|
||||
if (currprefs.sound_volume_cd > 100)
|
||||
currprefs.sound_volume_cd = 100;
|
||||
changed_prefs.sound_volume_cd = currprefs.sound_volume_cd;
|
||||
set_volume(currprefs.sound_volume_master, sdp->mute);
|
||||
config_changed = 1;
|
||||
}
|
||||
|
||||
void master_sound_volume(int dir)
|
||||
{
|
||||
int vol, mute, r;
|
||||
|
||||
r = get_master_volume(&vol, &mute);
|
||||
if (!r)
|
||||
return;
|
||||
if (dir == 0)
|
||||
mute = mute ? 0 : 1;
|
||||
vol += dir * (65536 / 10);
|
||||
if (vol < 0)
|
||||
vol = 0;
|
||||
if (vol > 65535)
|
||||
vol = 65535;
|
||||
set_master_volume(vol, mute);
|
||||
config_changed = 1;
|
||||
}
|
||||
|
||||
// Audio callback function
|
||||
void sdl2_audio_callback(void* userdata, Uint8* stream, int len)
|
||||
{
|
||||
struct sound_data* sd = (struct sound_data*)userdata;
|
||||
struct sound_dp* s = sd->data;
|
||||
int bytestocopy;
|
||||
|
||||
if (s->pullbufferlen <= 0)
|
||||
return;
|
||||
|
||||
bytestocopy = s->framesperbuffer * sd->samplesize;
|
||||
if (bytestocopy > 0) {
|
||||
memcpy(stream, s->pullbuffer, bytestocopy);
|
||||
}
|
||||
|
||||
if (bytestocopy < s->pullbufferlen) {
|
||||
memmove(s->pullbuffer, s->pullbuffer + bytestocopy, s->pullbufferlen - bytestocopy);
|
||||
}
|
||||
s->pullbufferlen -= bytestocopy;
|
||||
}
|
||||
|
|
|
@ -7,43 +7,136 @@
|
|||
*/
|
||||
|
||||
#pragma once
|
||||
#define DEFAULT_SOUND_CHANNELS 2
|
||||
#include "audio.h"
|
||||
|
||||
#define SOUNDSTUFF 1
|
||||
|
||||
#define SOUND_BUFFERS_COUNT 4
|
||||
#define SNDBUFFER_LEN 1024
|
||||
|
||||
extern uae_u16 sndbuffer[SOUND_BUFFERS_COUNT][(SNDBUFFER_LEN + 32) * DEFAULT_SOUND_CHANNELS];
|
||||
extern uae_u16* sndbufpt;
|
||||
extern uae_u16* render_sndbuff;
|
||||
extern uae_u16* finish_sndbuff;
|
||||
extern int sndbufsize;
|
||||
extern uae_u16 paula_sndbuffer[];
|
||||
extern uae_u16* paula_sndbufpt;
|
||||
extern int paula_sndbufsize;
|
||||
extern void finish_sound_buffer(void);
|
||||
extern void restart_sound_buffer(void);
|
||||
extern void pause_sound_buffer(void);
|
||||
extern void finish_cdaudio_buffer(void);
|
||||
extern bool cdaudio_catchup(void);
|
||||
extern int init_sound(void);
|
||||
extern void close_sound(void);
|
||||
extern int setup_sound(void);
|
||||
extern void resume_sound(void);
|
||||
extern void pause_sound(void);
|
||||
extern void reset_sound(void);
|
||||
extern void sound_volume(int);
|
||||
extern void stop_sound(void);
|
||||
extern bool sound_paused(void);
|
||||
extern void sound_setadjust(double);
|
||||
|
||||
#define check_sound_buffers() { if (sndbufpt >= finish_sndbuff) finish_sound_buffer (); }
|
||||
extern int drivesound_init(void);
|
||||
extern void drivesound_free(void);
|
||||
extern void sound_mute(int);
|
||||
extern void sound_volume(int);
|
||||
extern void set_volume(int, int);
|
||||
extern void master_sound_volume(int);
|
||||
|
||||
struct sound_dp;
|
||||
|
||||
struct sound_data
|
||||
{
|
||||
int waiting_for_buffer;
|
||||
int deactive;
|
||||
int devicetype;
|
||||
int obtainedfreq;
|
||||
int paused;
|
||||
int mute;
|
||||
int channels;
|
||||
int freq;
|
||||
int samplesize;
|
||||
int sndbufsize;
|
||||
int sndbufframes;
|
||||
int softvolume;
|
||||
struct sound_dp* data;
|
||||
int index;
|
||||
bool reset;
|
||||
int resetcnt;
|
||||
int resetframe;
|
||||
int resetframecnt;
|
||||
};
|
||||
|
||||
int open_sound_device(struct sound_data* sd, int index, int exclusive, int bufsize, int freq, int channels);
|
||||
void close_sound_device(struct sound_data* sd);
|
||||
void pause_sound_device(struct sound_data* sd);
|
||||
void resume_sound_device(struct sound_data* sd);
|
||||
void set_volume_sound_device(struct sound_data* sd, int volume, int mute);
|
||||
|
||||
static uae_u16* paula_sndbufpt_prev, * paula_sndbufpt_start;
|
||||
|
||||
STATIC_INLINE void set_sound_buffers(void)
|
||||
{
|
||||
#if SOUNDSTUFF > 1
|
||||
paula_sndbufpt_prev = paula_sndbufpt_start;
|
||||
paula_sndbufpt_start = paula_sndbufpt;
|
||||
#endif
|
||||
}
|
||||
|
||||
STATIC_INLINE void check_sound_buffers()
|
||||
{
|
||||
#if SOUNDSTUFF > 1
|
||||
int len;
|
||||
#endif
|
||||
|
||||
if (currprefs.sound_stereo == SND_4CH_CLONEDSTEREO) {
|
||||
((uae_u16*)paula_sndbufpt)[0] = ((uae_u16*)paula_sndbufpt)[-2];
|
||||
((uae_u16*)paula_sndbufpt)[1] = ((uae_u16*)paula_sndbufpt)[-1];
|
||||
paula_sndbufpt = (uae_u16*)(((uae_u8*)paula_sndbufpt) + 2 * 2);
|
||||
}
|
||||
else if (currprefs.sound_stereo == SND_6CH_CLONEDSTEREO) {
|
||||
uae_s16* p = ((uae_s16*)paula_sndbufpt);
|
||||
uae_s32 sum;
|
||||
p[2] = p[-2];
|
||||
p[3] = p[-1];
|
||||
sum = (uae_s32)(p[-2]) + (uae_s32)(p[-1]) + (uae_s32)(p[2]) + (uae_s32)(p[3]);
|
||||
p[0] = sum / 8;
|
||||
p[1] = sum / 8;
|
||||
paula_sndbufpt = (uae_u16*)(((uae_u8*)paula_sndbufpt) + 4 * 2);
|
||||
}
|
||||
#if SOUNDSTUFF > 1
|
||||
if (outputsample == 0)
|
||||
return;
|
||||
len = paula_sndbufpt - paula_sndbufpt_start;
|
||||
if (outputsample < 0) {
|
||||
int i;
|
||||
uae_s16* p1 = (uae_s16*)paula_sndbufpt_prev;
|
||||
uae_s16* p2 = (uae_s16*)paula_sndbufpt_start;
|
||||
for (i = 0; i < len; i++) {
|
||||
*p1 = (*p1 + *p2) / 2;
|
||||
}
|
||||
paula_sndbufpt = paula_sndbufpt_start;
|
||||
}
|
||||
#endif
|
||||
if ((uae_u8*)paula_sndbufpt - (uae_u8*)paula_sndbuffer >= paula_sndbufsize) {
|
||||
finish_sound_buffer();
|
||||
paula_sndbufpt = paula_sndbuffer;
|
||||
}
|
||||
#if SOUNDSTUFF > 1
|
||||
while (doublesample-- > 0) {
|
||||
memcpy(paula_sndbufpt, paula_sndbufpt_start, len * 2);
|
||||
paula_sndbufpt += len;
|
||||
if ((uae_u8*)paula_sndbufpt - (uae_u8*)paula_sndbuffer >= paula_sndbufsize) {
|
||||
finish_sound_buffer();
|
||||
paula_sndbufpt = paula_sndbuffer;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
STATIC_INLINE void clear_sound_buffers(void)
|
||||
{
|
||||
memset(sndbuffer, 0, sizeof(sndbuffer));
|
||||
memset(paula_sndbuffer, 0, paula_sndbufsize);
|
||||
paula_sndbufpt = paula_sndbuffer;
|
||||
}
|
||||
|
||||
#define PUT_SOUND_WORD(b) do { *sndbufpt = b; sndbufpt = sndbufpt + 1; } while (0)
|
||||
#define PUT_SOUND_WORD_STEREO(l,r) do { *((uae_u32 *)sndbufpt) = (r << 16) | (l & 0xffff); sndbufpt = sndbufpt + 2; } while (0)
|
||||
|
||||
#define DEFAULT_SOUND_BITS 16
|
||||
#define DEFAULT_SOUND_FREQ 44100
|
||||
#define HAVE_STEREO_SUPPORT
|
||||
#define PUT_SOUND_WORD(b) do { *(uae_u16 *)paula_sndbufpt = b; paula_sndbufpt = (uae_u16 *)(((uae_u8 *)paula_sndbufpt) + 2); } while (0)
|
||||
#define PUT_SOUND_WORD_MONO(b) PUT_SOUND_WORD(b)
|
||||
#define SOUND16_BASE_VAL 0
|
||||
#define SOUND8_BASE_VAL 128
|
||||
|
||||
#define DEFAULT_SOUND_MAXB 16384
|
||||
#define DEFAULT_SOUND_MINB 16384
|
||||
|
@ -56,22 +149,4 @@ STATIC_INLINE void clear_sound_buffers(void)
|
|||
#define FILTER_SOUND_ON 2
|
||||
|
||||
#define FILTER_SOUND_TYPE_A500 0
|
||||
#define FILTER_SOUND_TYPE_A1200 1
|
||||
|
||||
|
||||
#define CDAUDIO_BUFFERS 16
|
||||
#define CDAUDIO_BUFFER_LEN 1024
|
||||
extern uae_u16 cdaudio_buffer[CDAUDIO_BUFFERS][(CDAUDIO_BUFFER_LEN + 32) * DEFAULT_SOUND_CHANNELS];
|
||||
extern uae_u16* cdbufpt;
|
||||
extern uae_u16* render_cdbuff;
|
||||
extern uae_u16* finish_cdbuff;
|
||||
extern bool cdaudio_active;
|
||||
|
||||
#define check_cdaudio_buffers() { if (cdbufpt >= finish_cdbuff) finish_cdaudio_buffer (); }
|
||||
|
||||
STATIC_INLINE void clear_cdaudio_buffers(void)
|
||||
{
|
||||
memset(cdaudio_buffer, 0, sizeof(cdaudio_buffer));
|
||||
}
|
||||
|
||||
#define PUT_CDAUDIO_WORD_STEREO(l,r) do { *((uae_u32 *)cdbufpt) = (r << 16) | (l & 0xffff); cdbufpt = cdbufpt + 2; } while (0)
|
||||
#define FILTER_SOUND_TYPE_A1200 1
|
Loading…
Add table
Add a link
Reference in a new issue