WIP: cd audio support

Using QueueAudio works, but there are still gaps in playback
This commit is contained in:
Dimitris Panokostas 2020-08-21 00:30:36 +02:00
parent c241d790ed
commit 4044dc208a
5 changed files with 68 additions and 179 deletions

View file

@ -150,9 +150,7 @@ static int audio_extra_streams[AUDIO_CHANNEL_STREAMS];
static int audio_total_extra_streams;
static int samplecnt;
#if SOUNDSTUFF > 0
static int extrasamples, outputsample, doublesample;
#endif
int sampleripper_enabled;
struct ripped_sample
@ -745,7 +743,6 @@ static void sample16i_sinc_handler (void)
get_extra_channels_sample2(&data1, NULL, 2);
set_sound_buffers ();
PUT_SOUND_WORD_MONO (data1);
check_sound_buffers ();
}
@ -776,7 +773,6 @@ void sample16_handler (void)
get_extra_channels_sample2(&data, NULL, 0);
set_sound_buffers ();
PUT_SOUND_WORD_MONO (data);
check_sound_buffers ();
}
@ -795,7 +791,6 @@ static void sample16i_anti_handler (void)
get_extra_channels_sample2(&data1, NULL, 1);
set_sound_buffers ();
PUT_SOUND_WORD_MONO (data1);
check_sound_buffers ();
}
@ -852,7 +847,6 @@ static void sample16i_rh_handler (void)
get_extra_channels_sample2(&data, NULL, 0);
set_sound_buffers ();
PUT_SOUND_WORD_MONO (data);
check_sound_buffers ();
}
@ -929,7 +923,6 @@ static void sample16i_crux_handler (void)
get_extra_channels_sample2(&data, NULL, 0);
set_sound_buffers ();
PUT_SOUND_WORD_MONO (data);
check_sound_buffers ();
}
@ -976,7 +969,6 @@ void sample16ss_handler (void)
get_extra_channels_sample6(&data0, &data1, &data3, &data2, &data4, &data5, 0);
set_sound_buffers ();
put_sound_word_right(data0);
put_sound_word_left (data1);
if (currprefs.sound_stereo == SND_6CH) {
@ -1012,7 +1004,6 @@ static void sample16ss_anti_handler (void)
get_extra_channels_sample6(&data0, &data1, &data3, &data2, &data4, &data5, 0);
set_sound_buffers ();
put_sound_word_right(data0);
put_sound_word_left (data1);
if (currprefs.sound_stereo == SND_6CH) {
@ -1039,7 +1030,6 @@ static void sample16si_anti_handler (void)
get_extra_channels_sample2(&data1, &data2, 1);
set_sound_buffers ();
put_sound_word_right(data1);
put_sound_word_left (data2);
check_sound_buffers ();
@ -1066,7 +1056,6 @@ static void sample16ss_sinc_handler (void)
get_extra_channels_sample6(&data0, &data1, &data3, &data2, &data4, &data5, 0);
set_sound_buffers ();
put_sound_word_right(data0);
put_sound_word_left (data1);
if (currprefs.sound_stereo == SND_6CH) {
@ -1093,7 +1082,6 @@ static void sample16si_sinc_handler (void)
get_extra_channels_sample2(&data1, &data2, 2);
set_sound_buffers ();
put_sound_word_right(data1);
put_sound_word_left(data2);
check_sound_buffers ();
@ -1127,7 +1115,6 @@ void sample16s_handler (void)
get_extra_channels_sample2(&data2, &data3, 0);
set_sound_buffers ();
put_sound_word_right(data2);
put_sound_word_left(data3);
check_sound_buffers ();
@ -1206,7 +1193,6 @@ static void sample16si_crux_handler (void)
get_extra_channels_sample2(&data2, &data3, 0);
set_sound_buffers ();
put_sound_word_right(data2);
put_sound_word_left (data3);
check_sound_buffers ();
@ -1266,7 +1252,6 @@ static void sample16si_rh_handler (void)
get_extra_channels_sample2(&data2, &data3, 0);
set_sound_buffers ();
put_sound_word_right(data2);
put_sound_word_left (data3);
check_sound_buffers ();
@ -2136,9 +2121,7 @@ static void update_audio_volcnt(int cycles, float evtime, bool nextsmp)
void update_audio (void)
{
unsigned long int n_cycles = 0;
#if SOUNDSTUFF > 1
static int samplecounter;
#endif
if (!isaudio ())
goto end;
@ -2208,29 +2191,7 @@ void update_audio (void)
if (rounded == best_evtime) {
/* Before the following addition, next_sample_evtime is in range [-0.5, 0.5) */
next_sample_evtime += scaled_sample_evtime;
#if SOUNDSTUFF > 1
next_sample_evtime -= extrasamples * 15;
doublesample = 0;
if (--samplecounter <= 0) {
samplecounter = currprefs.sound_freq / 1000;
if (extrasamples > 0) {
outputsample = 1;
doublesample = 1;
extrasamples--;
} else if (extrasamples < 0) {
outputsample = 0;
doublesample = 0;
extrasamples++;
}
}
#endif
(*sample_handler) ();
#if SOUNDSTUFF > 1
if (outputsample == 0)
outputsample = -1;
else if (outputsample < 0)
outputsample = 1;
#endif
}
}
@ -2507,39 +2468,7 @@ void led_filter_audio (void)
void audio_vsync (void)
{
#if 0
#if SOUNDSTUFF > 0
int max, min;
int vsync = isvsync ();
static int lastdir;
if (1 || !vsync) {
extrasamples = 0;
return;
}
min = -10 * 10;
max = vsync ? 10 * 10 : 20 * 10;
extrasamples = 0;
if (gui_data.sndbuf < min) { // +1
extrasamples = (min - gui_data.sndbuf) / 10;
lastdir = 1;
} else if (gui_data.sndbuf > max) { // -1
extrasamples = (max - gui_data.sndbuf) / 10;
} else if (gui_data.sndbuf > 1 * 50 && lastdir < 0) {
extrasamples--;
} else if (gui_data.sndbuf < -1 * 50 && lastdir > 0) {
extrasamples++;
} else {
lastdir = 0;
}
if (extrasamples > 99)
extrasamples = 99;
if (extrasamples < -99)
extrasamples = -99;
#endif
#endif
}
void restore_audio_finish (void)

View file

@ -8,13 +8,16 @@
#include "sounddep/sound.h"
#include "uae/uae.h"
SDL_AudioDeviceID cdda_dev;
cda_audio::~cda_audio()
{
wait(0);
wait(1);
cdaudio_active = false;
if (SDL_GetAudioDeviceStatus(cdda_dev) != SDL_AUDIO_STOPPED)
SDL_CloseAudioDevice(cdda_dev);
for (auto& buffer : buffers)
{
xfree(buffer);
@ -30,19 +33,30 @@ cda_audio::cda_audio(int num_sectors, int sectorsize, int samplerate, bool inter
bufsize = num_sectors * sectorsize;
this->sectorsize = sectorsize;
for (auto& buffer : buffers)
{
buffer = xcalloc(uae_u8, num_sectors * ( bufsize + 4095 & ~4095));
for (auto i = 0; i < 2; i++) {
buffers[i] = xcalloc(uae_u8, num_sectors * ((bufsize + 4095) & ~4095));
}
this->num_sectors = num_sectors;
if (internalmode)
return;
cdaudio_active = true;
active = true;
playing = true;
SDL_AudioSpec cdda_want, cdda_have;
memset(&cdda_want, 0, sizeof cdda_want);
cdda_want.freq = samplerate;
cdda_want.format = AUDIO_S16;
cdda_want.channels = 2;
cdda_want.samples = num_sectors * sectorsize;
cdda_dev = SDL_OpenAudioDevice(nullptr, 0, &cdda_want, &cdda_have, 0);
if (cdda_dev == 0)
write_log("Failed to open SDL2 device for CD-Audio: %s", SDL_GetError());
else
{
SDL_PauseAudioDevice(cdda_dev, 0);
active = true;
playing = true;
}
}
void cda_audio::setvolume(int left, int right)
@ -64,16 +78,17 @@ bool cda_audio::play(int bufnum)
if (!active)
return false;
auto* const p = reinterpret_cast<uae_s16*>(buffers[bufnum]);
for (auto 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;
//PUT_CDAUDIO_WORD_STEREO(p[i * 2 + 0] * volume[0] / 32768, p[i * 2 + 1] * volume[1] / 32768);
//check_cdaudio_buffers();
auto* p = reinterpret_cast<uae_s16*>(buffers[bufnum]);
if (volume[0] != 32768 || volume[1] != 32768) {
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;
}
}
SDL_QueueAudio(cdda_dev, p, num_sectors * sectorsize);
return true;
//return cdaudio_catchup();
}
void cda_audio::wait(int bufnum)
@ -81,7 +96,7 @@ void cda_audio::wait(int bufnum)
if (!active || !playing)
return;
while (SDL_GetAudioDeviceStatus(dev) != SDL_AUDIO_PLAYING) {
while (SDL_GetQueuedAudioSize(cdda_dev) > 0) {
Sleep(10);
}
}
@ -90,6 +105,6 @@ bool cda_audio::isplaying(int bufnum)
{
if (!active || !playing)
return false;
return SDL_GetAudioDeviceStatus(dev) == SDL_AUDIO_PLAYING;
return SDL_GetQueuedAudioSize(cdda_dev) > 0;
}

View file

@ -2,6 +2,7 @@
#include "audio.h"
extern volatile bool cd_audio_mode_changed;
extern SDL_AudioDeviceID cdda_dev;
class cda_audio
{

View file

@ -63,11 +63,6 @@ int paula_sndbufsize;
#ifdef AMIBERRY
SDL_AudioDeviceID dev;
void sdl2_audio_callback(void* userdata, Uint8* stream, int len);
uae_u16 cdaudio_buffer[SND_MAX_BUFFER];
uae_u16* cdbufpt;
int cdaudio_bufsize;
bool cdaudio_active = false;
#endif
struct sound_device* sound_devices[MAX_SOUND_DEVICES];
@ -80,6 +75,7 @@ static uae_u8* extrasndbuf;
static int extrasndbufsize;
static int extrasndbuffered;
static int sound_pull = 1;
int setup_sound(void)
{
@ -128,6 +124,7 @@ void sound_setadjust(double v)
}
}
#if 0
static void docorrection(struct sound_dp* s, int sndbuf, double sync, int granulaty)
{
static int tfprev;
@ -155,7 +152,9 @@ static void docorrection(struct sound_dp* s, int sndbuf, double sync, int granul
tfprev = timeframes;
}
}
#endif
#if 0
static double sync_sound(double m)
{
double skipmode;
@ -183,14 +182,12 @@ static double sync_sound(double m)
return skipmode;
}
#endif
static void clearbuffer_sdl2(struct sound_data *sd)
{
SDL_LockAudioDevice(dev);
memset(paula_sndbuffer, 0, sizeof paula_sndbuffer);
#ifdef AMIBERRY
clear_cdaudio_buffers();
#endif
SDL_UnlockAudioDevice(dev);
}
@ -262,12 +259,6 @@ static void finish_sound_buffer_pull(struct sound_data* sd, uae_u16* sndbuffer)
s->pullbufferlen += sd->sndbufsize;
}
void finish_cdaudio_buffer()
{
}
static int open_audio_sdl2(struct sound_data* sd, int index)
{
auto* const s = sd->data;
@ -282,6 +273,7 @@ static int open_audio_sdl2(struct sound_data* sd, int index)
sd->sndbufsize = s->sndbufsize * ch * 2;
if (sd->sndbufsize > SND_MAX_BUFFER)
sd->sndbufsize = SND_MAX_BUFFER;
s->pullmode = sound_pull;
SDL_AudioSpec want, have;
memset(&want, 0, sizeof want);
@ -289,11 +281,14 @@ static int open_audio_sdl2(struct sound_data* sd, int index)
want.format = AUDIO_S16;
want.channels = ch;
want.samples = s->framesperbuffer;
want.callback = sdl2_audio_callback;
want.userdata = sd;
if (s->pullmode)
{
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)
@ -307,7 +302,6 @@ static int open_audio_sdl2(struct sound_data* sd, int index)
s->pullbufferlen = 0;
clear_sound_buffers();
clear_cdaudio_buffers();
SDL_PauseAudioDevice(dev, 0);
return 1;
@ -391,10 +385,6 @@ static int open_sound()
paula_sndbufpt = paula_sndbuffer;
#ifdef DRIVESOUND
driveclick_init();
#endif
#if 0
cdaudio_bufsize = SND_MAX_BUFFER;
cdbufpt = cdaudio_buffer;
#endif
return 1;
}
@ -495,6 +485,21 @@ void restart_sound_buffer()
//restart_sound_buffer2(sdp);
}
static void finish_sound_buffer_sdl2_push(struct sound_data* sd, uae_u16* sndbuffer)
{
struct sound_dp* s = sd->data;
SDL_QueueAudio(dev, sndbuffer, sd->sndbufsize);
}
static void finish_sound_buffer_sdl2(struct sound_data *sd, uae_u16 *sndbuffer)
{
auto* s = sd->data;
if (s->pullmode)
finish_sound_buffer_pull(sd, sndbuffer);
else
finish_sound_buffer_sdl2_push(sd, sndbuffer);
}
static void channelswap(uae_s16* sndbuffer, int len)
{
for (auto i = 0; i < len; i += 2) {
@ -538,7 +543,7 @@ static void send_sound(struct sound_data* sd, uae_u16* sndbuffer)
}
}
finish_sound_buffer_pull(sd, sndbuffer);
finish_sound_buffer_sdl2(sd, sndbuffer);
}
bool audio_is_event_frame_possible(int)
@ -582,7 +587,7 @@ bool audio_finish_pull()
int type = sdp->devicetype;
if (sdp->paused || sdp->deactive || sdp->reset)
return false;
if (type != SOUND_DEVICE_SDL2 && type != SOUND_DEVICE_WASAPI && type != SOUND_DEVICE_WASAPI_EXCLUSIVE && type != SOUND_DEVICE_PA)
if (type != SOUND_DEVICE_SDL2)
return false;
if (audio_pull_buffer() && audio_is_pull_event()) {
return send_sound_do(sdp);
@ -682,11 +687,13 @@ void finish_sound_buffer()
static int set_master_volume(int volume, int mute)
{
//todo set volume using SDL2
return 1;
}
static int get_master_volume(int* volume, int* mute)
{
//todo get volume using SDL2
return 1;
}
void sound_mute(int newmute)
@ -744,7 +751,7 @@ void sdl2_audio_callback(void* userdata, Uint8* stream, int len)
if (s->pullbufferlen <= 0)
return;
const auto bytes_to_copy = s->framesperbuffer * sd->samplesize;
const unsigned int bytes_to_copy = s->framesperbuffer * sd->samplesize;
if (bytes_to_copy > 0) {
memcpy(stream, s->pullbuffer, bytes_to_copy);
}

View file

@ -9,20 +9,10 @@
#pragma once
#include "audio.h"
#define SOUNDSTUFF 1
extern uae_u16 paula_sndbuffer[];
extern uae_u16* paula_sndbufpt;
extern int paula_sndbufsize;
#ifdef AMIBERRY
extern uae_u16 cdaudio_buffer[];
extern uae_u16* cdbufpt;
extern int cdaudio_bufsize;
extern bool cdaudio_active;
extern void finish_cdaudio_buffer();
extern bool cdaudio_catchup();
#define PUT_CDAUDIO_WORD_STEREO(l,r) do { *((uae_u32 *)cdbufpt) = ((r) << 16) | ((l) & 0xffff); cdbufpt = cdbufpt + 2; } while (0)
extern SDL_AudioDeviceID dev;
#endif
@ -77,20 +67,8 @@ 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];
@ -106,34 +84,11 @@ STATIC_INLINE void check_sound_buffers()
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()
@ -142,24 +97,6 @@ STATIC_INLINE void clear_sound_buffers()
paula_sndbufpt = paula_sndbuffer;
}
#ifdef AMIBERRY
STATIC_INLINE void check_cdaudio_buffers()
{
if ((uae_u8*)cdbufpt - (uae_u8*)cdaudio_buffer >= cdaudio_bufsize)
{
finish_cdaudio_buffer();
cdbufpt = cdaudio_buffer;
}
}
STATIC_INLINE void clear_cdaudio_buffers()
{
memset(cdaudio_buffer, 0, cdaudio_bufsize);
cdbufpt = cdaudio_buffer;
}
#endif
#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