2017-05-30 03:38:38 +02:00
|
|
|
/*
|
|
|
|
|
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
|
|
|
|
* running old operating systems and software designed for IBM
|
|
|
|
|
* PC systems and compatibles from 1981 through fairly recent
|
|
|
|
|
* system designs based on the PCI bus.
|
|
|
|
|
*
|
|
|
|
|
* This file is part of the 86Box distribution.
|
|
|
|
|
*
|
|
|
|
|
* Sound emulation core.
|
|
|
|
|
*
|
2018-05-21 19:04:05 +02:00
|
|
|
* Version: @(#)sound.c 1.0.17 2018/04/29
|
2017-05-30 03:38:38 +02:00
|
|
|
*
|
2017-06-05 01:20:51 -04:00
|
|
|
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
2017-05-30 03:38:38 +02:00
|
|
|
* Miran Grca, <mgrca8@gmail.com>
|
2017-10-11 05:40:44 -04:00
|
|
|
*
|
2018-02-11 20:51:42 +01:00
|
|
|
* Copyright 2008-2018 Sarah Walker.
|
|
|
|
|
* Copyright 2016-2018 Miran Grca.
|
2017-05-30 03:38:38 +02:00
|
|
|
*/
|
2018-05-21 19:04:05 +02:00
|
|
|
#include <stdarg.h>
|
2017-09-25 04:31:20 -04:00
|
|
|
#include <stdint.h>
|
2018-05-21 19:04:05 +02:00
|
|
|
#include <stdio.h>
|
2017-09-25 04:31:20 -04:00
|
|
|
#include <string.h>
|
2016-06-26 00:34:39 +02:00
|
|
|
#include <stdlib.h>
|
2017-09-25 04:31:20 -04:00
|
|
|
#include <wchar.h>
|
2018-05-21 19:04:05 +02:00
|
|
|
#define HAVE_STDARG_H
|
2017-10-17 01:59:09 -04:00
|
|
|
#include "../86box.h"
|
2017-05-06 17:48:33 +02:00
|
|
|
#include "../device.h"
|
|
|
|
|
#include "../timer.h"
|
2018-04-25 23:51:13 +02:00
|
|
|
#include "../scsi/scsi.h"
|
2017-09-04 01:52:29 -04:00
|
|
|
#include "../cdrom/cdrom.h"
|
2017-10-11 05:40:44 -04:00
|
|
|
#include "../plat.h"
|
2016-06-26 00:34:39 +02:00
|
|
|
#include "sound.h"
|
2017-09-25 04:31:20 -04:00
|
|
|
#include "midi.h"
|
2017-05-06 17:48:33 +02:00
|
|
|
#include "snd_opl.h"
|
2018-04-25 23:51:13 +02:00
|
|
|
#include "snd_cms.h"
|
2017-05-06 17:48:33 +02:00
|
|
|
#include "snd_adlib.h"
|
|
|
|
|
#include "snd_adlibgold.h"
|
2017-10-14 07:03:19 +02:00
|
|
|
#include "snd_audiopci.h"
|
2018-04-25 23:51:13 +02:00
|
|
|
#include "snd_gus.h"
|
2017-10-16 06:19:18 +02:00
|
|
|
#include "snd_mpu401.h"
|
2017-10-11 05:40:44 -04:00
|
|
|
#if defined(DEV_BRANCH) && defined(USE_PAS16)
|
|
|
|
|
# include "snd_pas16.h"
|
2017-08-27 00:58:44 +02:00
|
|
|
#endif
|
2017-05-06 17:48:33 +02:00
|
|
|
#include "snd_sb.h"
|
|
|
|
|
#include "snd_sb_dsp.h"
|
2018-04-25 23:51:13 +02:00
|
|
|
#include "snd_ssi2001.h"
|
2017-05-06 17:48:33 +02:00
|
|
|
#include "snd_wss.h"
|
|
|
|
|
#include "filters.h"
|
2016-06-26 00:34:39 +02:00
|
|
|
|
|
|
|
|
|
2017-11-05 01:57:04 -05:00
|
|
|
typedef struct {
|
2018-02-18 10:32:51 +01:00
|
|
|
const char *name;
|
|
|
|
|
const char *internal_name;
|
2018-03-19 01:02:04 +01:00
|
|
|
const device_t *device;
|
2016-06-26 00:34:39 +02:00
|
|
|
} SOUND_CARD;
|
|
|
|
|
|
2018-02-15 23:14:44 +01:00
|
|
|
typedef struct {
|
|
|
|
|
void (*get_buffer)(int32_t *buffer, int len, void *p);
|
|
|
|
|
void *priv;
|
|
|
|
|
} sound_handler_t;
|
|
|
|
|
|
2017-11-05 01:57:04 -05:00
|
|
|
|
|
|
|
|
int sound_card_current = 0;
|
|
|
|
|
int sound_pos_global = 0;
|
2018-02-15 23:14:44 +01:00
|
|
|
volatile int soundon = 1;
|
2018-02-11 20:51:42 +01:00
|
|
|
int sound_gain = 0;
|
2017-11-05 01:57:04 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
static int sound_card_last = 0;
|
2018-02-15 23:14:44 +01:00
|
|
|
static sound_handler_t sound_handlers[8];
|
|
|
|
|
static sound_handler_t sound_process_handlers[8];
|
2017-11-05 01:57:04 -05:00
|
|
|
static int sound_handlers_num;
|
2018-02-15 23:14:44 +01:00
|
|
|
static int sound_process_handlers_num;
|
2017-11-05 01:57:04 -05:00
|
|
|
static int64_t sound_poll_time = 0LL, sound_poll_latch;
|
|
|
|
|
static int16_t cd_buffer[CDROM_NUM][CD_BUFLEN * 2];
|
|
|
|
|
static float cd_out_buffer[CD_BUFLEN * 2];
|
|
|
|
|
static int16_t cd_out_buffer_int16[CD_BUFLEN * 2];
|
|
|
|
|
static thread_t *sound_cd_thread_h;
|
|
|
|
|
static event_t *sound_cd_event;
|
2017-12-05 20:19:19 +01:00
|
|
|
static event_t *sound_cd_start_event;
|
2017-11-05 01:57:04 -05:00
|
|
|
static unsigned int cd_vol_l, cd_vol_r;
|
|
|
|
|
static int cd_buf_update = CD_BUFLEN / SOUNDBUFLEN;
|
2017-12-05 20:19:19 +01:00
|
|
|
static volatile int cdaudioon = 0;
|
2017-11-05 01:57:04 -05:00
|
|
|
|
|
|
|
|
|
2018-03-19 01:02:04 +01:00
|
|
|
static const SOUND_CARD sound_cards[] =
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2017-10-10 00:14:15 +02:00
|
|
|
{ "None", "none", NULL },
|
|
|
|
|
{ "[ISA] Adlib", "adlib", &adlib_device },
|
|
|
|
|
{ "[ISA] Adlib Gold", "adlibgold",&adgold_device },
|
|
|
|
|
{ "[ISA] Sound Blaster 1.0", "sb", &sb_1_device },
|
|
|
|
|
{ "[ISA] Sound Blaster 1.5", "sb1.5", &sb_15_device },
|
|
|
|
|
{ "[ISA] Sound Blaster 2.0", "sb2.0", &sb_2_device },
|
|
|
|
|
{ "[ISA] Sound Blaster Pro v1", "sbprov1", &sb_pro_v1_device },
|
|
|
|
|
{ "[ISA] Sound Blaster Pro v2", "sbprov2", &sb_pro_v2_device },
|
|
|
|
|
{ "[ISA] Sound Blaster 16", "sb16", &sb_16_device },
|
|
|
|
|
{ "[ISA] Sound Blaster AWE32", "sbawe32", &sb_awe32_device },
|
2017-10-11 05:40:44 -04:00
|
|
|
#if defined(DEV_BRANCH) && defined(USE_PAS16)
|
2017-10-10 00:14:15 +02:00
|
|
|
{ "[ISA] Pro Audio Spectrum 16","pas16", &pas16_device },
|
2017-06-04 02:14:27 +02:00
|
|
|
#endif
|
2017-10-10 00:14:15 +02:00
|
|
|
{ "[ISA] Windows Sound System", "wss", &wss_device },
|
2017-10-14 07:03:19 +02:00
|
|
|
{ "[MCA] Adlib", "adlib_mca", &adlib_mca_device },
|
|
|
|
|
{ "[MCA] Sound Blaster MCV", "sbmcv", &sb_mcv_device },
|
2017-10-10 00:14:15 +02:00
|
|
|
{ "[MCA] Sound Blaster Pro MCV","sbpromcv", &sb_pro_mcv_device },
|
2017-10-14 07:03:19 +02:00
|
|
|
{ "[PCI] Ensoniq AudioPCI (ES1371)","es1371", &es1371_device},
|
|
|
|
|
{ "[PCI] Sound Blaster PCI 128", "sbpci128", &es1371_device},
|
2017-06-05 01:20:51 -04:00
|
|
|
{ "", "", NULL }
|
2016-06-26 00:34:39 +02:00
|
|
|
};
|
|
|
|
|
|
2017-06-05 01:20:51 -04:00
|
|
|
|
2018-05-21 19:04:05 +02:00
|
|
|
#ifdef ENABLE_SOUND_LOG
|
|
|
|
|
int sound_do_log = ENABLE_SOUND_LOG;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
sound_log(const char *fmt, ...)
|
|
|
|
|
{
|
|
|
|
|
#ifdef ENABLE_SOUND_LOG
|
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
|
|
if (sound_do_log) {
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
|
pclog_ex(fmt, ap);
|
|
|
|
|
va_end(ap);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2016-06-26 00:34:39 +02:00
|
|
|
int sound_card_available(int card)
|
|
|
|
|
{
|
|
|
|
|
if (sound_cards[card].device)
|
|
|
|
|
return device_available(sound_cards[card].device);
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *sound_card_getname(int card)
|
|
|
|
|
{
|
2018-02-18 10:32:51 +01:00
|
|
|
return (char *) sound_cards[card].name;
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2018-03-19 01:02:04 +01:00
|
|
|
const device_t *sound_card_getdevice(int card)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
|
|
|
|
return sound_cards[card].device;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int sound_card_has_config(int card)
|
|
|
|
|
{
|
|
|
|
|
if (!sound_cards[card].device)
|
|
|
|
|
return 0;
|
|
|
|
|
return sound_cards[card].device->config ? 1 : 0;
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-14 00:38:25 +01:00
|
|
|
char *sound_card_get_internal_name(int card)
|
|
|
|
|
{
|
2018-02-18 10:32:51 +01:00
|
|
|
return (char *) sound_cards[card].internal_name;
|
2017-03-14 00:38:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int sound_card_get_from_internal_name(char *s)
|
|
|
|
|
{
|
|
|
|
|
int c = 0;
|
|
|
|
|
|
2018-02-18 10:32:51 +01:00
|
|
|
while (strlen((char *) sound_cards[c].internal_name))
|
2017-03-14 00:38:25 +01:00
|
|
|
{
|
2018-02-18 10:32:51 +01:00
|
|
|
if (!strcmp((char *) sound_cards[c].internal_name, s))
|
2017-03-14 00:38:25 +01:00
|
|
|
return c;
|
|
|
|
|
c++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-05 01:20:51 -04:00
|
|
|
void sound_card_init(void)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
|
|
|
|
if (sound_cards[sound_card_current].device)
|
|
|
|
|
device_add(sound_cards[sound_card_current].device);
|
|
|
|
|
sound_card_last = sound_card_current;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void sound_set_cd_volume(unsigned int vol_l, unsigned int vol_r)
|
|
|
|
|
{
|
|
|
|
|
cd_vol_l = vol_l;
|
|
|
|
|
cd_vol_r = vol_r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void sound_cd_thread(void *param)
|
|
|
|
|
{
|
2017-01-16 01:49:19 +01:00
|
|
|
int i = 0;
|
|
|
|
|
|
2017-06-14 07:21:01 +02:00
|
|
|
float cd_buffer_temp[2] = {0.0, 0.0};
|
|
|
|
|
float cd_buffer_temp2[2] = {0.0, 0.0};
|
|
|
|
|
|
2018-02-15 23:14:44 +01:00
|
|
|
int32_t cd_buffer_temp4[2] = {0, 0};
|
|
|
|
|
|
2017-06-14 07:21:01 +02:00
|
|
|
int c, has_audio;
|
2018-04-25 23:51:13 +02:00
|
|
|
int d, r;
|
2017-06-14 07:21:01 +02:00
|
|
|
|
2017-12-05 20:19:19 +01:00
|
|
|
thread_set_event(sound_cd_start_event);
|
|
|
|
|
|
|
|
|
|
while (cdaudioon)
|
2017-01-27 23:03:20 +01:00
|
|
|
{
|
|
|
|
|
thread_wait_event(sound_cd_event, -1);
|
2018-02-15 23:14:44 +01:00
|
|
|
thread_reset_event(sound_cd_event);
|
2017-12-05 20:19:19 +01:00
|
|
|
if (!soundon || !cdaudioon)
|
2017-02-02 02:55:08 +01:00
|
|
|
return;
|
2017-01-16 01:49:19 +01:00
|
|
|
for (c = 0; c < CD_BUFLEN*2; c += 2)
|
|
|
|
|
{
|
2017-06-14 07:21:01 +02:00
|
|
|
if (sound_is_float)
|
|
|
|
|
{
|
|
|
|
|
cd_out_buffer[c] = 0.0;
|
|
|
|
|
cd_out_buffer[c+1] = 0.0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
cd_out_buffer_int16[c] = 0;
|
|
|
|
|
cd_out_buffer_int16[c+1] = 0;
|
|
|
|
|
}
|
2017-01-16 01:49:19 +01:00
|
|
|
}
|
|
|
|
|
for (i = 0; i < CDROM_NUM; i++)
|
|
|
|
|
{
|
|
|
|
|
has_audio = 0;
|
2018-04-25 23:51:13 +02:00
|
|
|
if ((cdrom_drives[i].bus_type == CDROM_BUS_DISABLED) || !cdrom[i] || !cdrom[i]->handler)
|
2018-02-15 23:14:44 +01:00
|
|
|
continue;
|
2018-04-25 23:51:13 +02:00
|
|
|
if (cdrom[i]->handler->audio_callback)
|
2017-01-16 01:49:19 +01:00
|
|
|
{
|
2018-04-25 23:51:13 +02:00
|
|
|
r = cdrom[i]->handler->audio_callback(i, cd_buffer[i], CD_BUFLEN*2);
|
|
|
|
|
has_audio = (cdrom_drives[i].bus_type && cdrom_drives[i].sound_on/* && r*/);
|
2018-02-15 23:14:44 +01:00
|
|
|
} else
|
|
|
|
|
continue;
|
2017-01-27 23:03:20 +01:00
|
|
|
if (soundon && has_audio)
|
|
|
|
|
{
|
2018-04-25 23:51:13 +02:00
|
|
|
int32_t audio_vol_l = cdrom_mode_sense_get_volume(cdrom[i], 0);
|
|
|
|
|
int32_t audio_vol_r = cdrom_mode_sense_get_volume(cdrom[i], 1);
|
2017-01-27 23:03:20 +01:00
|
|
|
int channel_select[2];
|
|
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
channel_select[0] = cdrom_mode_sense_get_channel(cdrom[i], 0);
|
|
|
|
|
channel_select[1] = cdrom_mode_sense_get_channel(cdrom[i], 1);
|
|
|
|
|
|
|
|
|
|
if (!r)
|
|
|
|
|
{
|
|
|
|
|
for (c = 0; c < CD_BUFLEN*2; c += 2)
|
|
|
|
|
{
|
|
|
|
|
if (sound_is_float)
|
|
|
|
|
{
|
|
|
|
|
cd_out_buffer[c] += 0.0;
|
|
|
|
|
cd_out_buffer[c+1] += 0.0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
cd_out_buffer_int16[c] += 0;
|
|
|
|
|
cd_out_buffer_int16[c+1] += 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2017-01-27 23:03:20 +01:00
|
|
|
|
|
|
|
|
for (c = 0; c < CD_BUFLEN*2; c += 2)
|
|
|
|
|
{
|
|
|
|
|
/* First, transfer the CD audio data to the temporary buffer. */
|
|
|
|
|
cd_buffer_temp[0] = (float) cd_buffer[i][c];
|
|
|
|
|
cd_buffer_temp[1] = (float) cd_buffer[i][c+1];
|
|
|
|
|
|
|
|
|
|
/* Then, adjust input from drive according to ATAPI/SCSI volume. */
|
|
|
|
|
cd_buffer_temp[0] *= (float) audio_vol_l;
|
2017-02-04 06:53:46 +01:00
|
|
|
cd_buffer_temp[0] /= 511.0;
|
2017-01-27 23:03:20 +01:00
|
|
|
cd_buffer_temp[1] *= (float) audio_vol_r;
|
2017-02-04 06:53:46 +01:00
|
|
|
cd_buffer_temp[1] /= 511.0;
|
2017-01-27 23:03:20 +01:00
|
|
|
|
|
|
|
|
/*Apply ATAPI channel select*/
|
|
|
|
|
cd_buffer_temp2[0] = cd_buffer_temp2[1] = 0.0;
|
|
|
|
|
if (channel_select[0] & 1)
|
|
|
|
|
{
|
|
|
|
|
cd_buffer_temp2[0] += cd_buffer_temp[0];
|
|
|
|
|
}
|
|
|
|
|
if (channel_select[0] & 2)
|
|
|
|
|
{
|
|
|
|
|
cd_buffer_temp2[1] += cd_buffer_temp[0];
|
|
|
|
|
}
|
|
|
|
|
if (channel_select[1] & 1)
|
|
|
|
|
{
|
|
|
|
|
cd_buffer_temp2[0] += cd_buffer_temp[1];
|
|
|
|
|
}
|
|
|
|
|
if (channel_select[1] & 2)
|
|
|
|
|
{
|
|
|
|
|
cd_buffer_temp2[1] += cd_buffer_temp[1];
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-15 23:14:44 +01:00
|
|
|
if (sound_process_handlers_num)
|
|
|
|
|
{
|
|
|
|
|
cd_buffer_temp4[0] = (int32_t) cd_buffer_temp2[0];
|
|
|
|
|
cd_buffer_temp4[1] = (int32_t) cd_buffer_temp2[1];
|
|
|
|
|
|
|
|
|
|
for (d = 0; d < sound_process_handlers_num; d++)
|
|
|
|
|
sound_process_handlers[d].get_buffer(cd_buffer_temp4, 1, sound_process_handlers[d].priv);
|
|
|
|
|
|
|
|
|
|
cd_buffer_temp2[0] = (float) cd_buffer_temp4[0];
|
|
|
|
|
cd_buffer_temp2[1] = (float) cd_buffer_temp4[1];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/*Apply sound card CD volume*/
|
|
|
|
|
cd_buffer_temp2[0] *= (float) cd_vol_l;
|
|
|
|
|
cd_buffer_temp2[0] /= 65535.0;
|
2017-01-27 23:03:20 +01:00
|
|
|
|
2018-02-15 23:14:44 +01:00
|
|
|
cd_buffer_temp2[1] *= (float) cd_vol_r;
|
|
|
|
|
cd_buffer_temp2[1] /= 65535.0;
|
|
|
|
|
}
|
2017-01-27 23:03:20 +01:00
|
|
|
|
2017-06-14 07:21:01 +02:00
|
|
|
if (sound_is_float)
|
|
|
|
|
{
|
|
|
|
|
cd_out_buffer[c] += (cd_buffer_temp2[0] / 32768.0);
|
|
|
|
|
cd_out_buffer[c+1] += (cd_buffer_temp2[1] / 32768.0);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (cd_buffer_temp2[0] > 32767)
|
|
|
|
|
cd_buffer_temp2[0] = 32767;
|
|
|
|
|
if (cd_buffer_temp2[0] < -32768)
|
|
|
|
|
cd_buffer_temp2[0] = -32768;
|
|
|
|
|
if (cd_buffer_temp2[1] > 32767)
|
|
|
|
|
cd_buffer_temp2[1] = 32767;
|
|
|
|
|
if (cd_buffer_temp2[1] < -32768)
|
|
|
|
|
cd_buffer_temp2[1] = -32768;
|
|
|
|
|
|
|
|
|
|
cd_out_buffer_int16[c] += cd_buffer_temp2[0];
|
|
|
|
|
cd_out_buffer_int16[c+1] += cd_buffer_temp2[1];
|
|
|
|
|
}
|
2017-01-27 23:03:20 +01:00
|
|
|
}
|
|
|
|
|
}
|
2017-01-16 01:49:19 +01:00
|
|
|
}
|
2017-06-14 07:21:01 +02:00
|
|
|
if (sound_is_float)
|
|
|
|
|
givealbuffer_cd(cd_out_buffer);
|
|
|
|
|
else
|
2017-06-19 06:46:08 +02:00
|
|
|
givealbuffer_cd(cd_out_buffer_int16);
|
2017-01-27 23:03:20 +01:00
|
|
|
}
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int32_t *outbuffer;
|
2017-01-16 01:49:19 +01:00
|
|
|
static float *outbuffer_ex;
|
2017-06-14 07:21:01 +02:00
|
|
|
static int16_t *outbuffer_ex_int16;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-02-02 02:55:08 +01:00
|
|
|
static int cd_thread_enable = 0;
|
|
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
static void sound_realloc_buffers(void)
|
2017-06-14 07:21:01 +02:00
|
|
|
{
|
|
|
|
|
if (outbuffer_ex != NULL)
|
|
|
|
|
{
|
|
|
|
|
free(outbuffer_ex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (outbuffer_ex_int16 != NULL)
|
|
|
|
|
{
|
|
|
|
|
free(outbuffer_ex_int16);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sound_is_float)
|
|
|
|
|
{
|
|
|
|
|
outbuffer_ex = malloc(SOUNDBUFLEN * 2 * sizeof(float));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
outbuffer_ex_int16 = malloc(SOUNDBUFLEN * 2 * sizeof(int16_t));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-05 01:20:51 -04:00
|
|
|
void sound_init(void)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2017-02-02 02:55:08 +01:00
|
|
|
int i = 0;
|
|
|
|
|
int available_cdrom_drives = 0;
|
|
|
|
|
|
2017-06-14 07:21:01 +02:00
|
|
|
outbuffer_ex = NULL;
|
|
|
|
|
outbuffer_ex_int16 = NULL;
|
|
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
outbuffer = malloc(SOUNDBUFLEN * 2 * sizeof(int32_t));
|
2017-02-02 02:55:08 +01:00
|
|
|
|
|
|
|
|
for (i = 0; i < CDROM_NUM; i++)
|
|
|
|
|
{
|
2017-06-01 01:47:54 +02:00
|
|
|
if (cdrom_drives[i].bus_type != CDROM_BUS_DISABLED)
|
2017-02-02 02:55:08 +01:00
|
|
|
{
|
|
|
|
|
available_cdrom_drives++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (available_cdrom_drives)
|
|
|
|
|
{
|
2018-02-15 23:14:44 +01:00
|
|
|
cdaudioon = 1;
|
|
|
|
|
|
2017-12-05 20:19:19 +01:00
|
|
|
sound_cd_start_event = thread_create_event();
|
|
|
|
|
|
2017-02-02 02:55:08 +01:00
|
|
|
sound_cd_event = thread_create_event();
|
|
|
|
|
sound_cd_thread_h = thread_create(sound_cd_thread, NULL);
|
2017-12-05 20:19:19 +01:00
|
|
|
|
2018-05-21 19:04:05 +02:00
|
|
|
sound_log("Waiting for CD start event...\n");
|
2017-12-05 20:19:19 +01:00
|
|
|
thread_wait_event(sound_cd_start_event, -1);
|
2018-02-15 23:14:44 +01:00
|
|
|
thread_reset_event(sound_cd_start_event);
|
2018-05-21 19:04:05 +02:00
|
|
|
sound_log("Done!\n");
|
2017-02-02 02:55:08 +01:00
|
|
|
}
|
2017-12-05 20:19:19 +01:00
|
|
|
else
|
|
|
|
|
cdaudioon = 0;
|
2017-02-02 02:55:08 +01:00
|
|
|
|
|
|
|
|
cd_thread_enable = available_cdrom_drives ? 1 : 0;
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void sound_add_handler(void (*get_buffer)(int32_t *buffer, int len, void *p), void *p)
|
|
|
|
|
{
|
|
|
|
|
sound_handlers[sound_handlers_num].get_buffer = get_buffer;
|
|
|
|
|
sound_handlers[sound_handlers_num].priv = p;
|
|
|
|
|
sound_handlers_num++;
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-15 23:14:44 +01:00
|
|
|
void sound_add_process_handler(void (*get_buffer)(int32_t *buffer, int len, void *p), void *p)
|
|
|
|
|
{
|
|
|
|
|
sound_process_handlers[sound_process_handlers_num].get_buffer = get_buffer;
|
|
|
|
|
sound_process_handlers[sound_process_handlers_num].priv = p;
|
|
|
|
|
sound_process_handlers_num++;
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-26 00:34:39 +02:00
|
|
|
void sound_poll(void *priv)
|
|
|
|
|
{
|
|
|
|
|
sound_poll_time += sound_poll_latch;
|
2017-06-19 06:46:08 +02:00
|
|
|
|
|
|
|
|
midi_poll();
|
|
|
|
|
|
2016-06-26 00:34:39 +02:00
|
|
|
sound_pos_global++;
|
|
|
|
|
if (sound_pos_global == SOUNDBUFLEN)
|
|
|
|
|
{
|
|
|
|
|
int c;
|
|
|
|
|
|
|
|
|
|
memset(outbuffer, 0, SOUNDBUFLEN * 2 * sizeof(int32_t));
|
|
|
|
|
|
|
|
|
|
for (c = 0; c < sound_handlers_num; c++)
|
|
|
|
|
sound_handlers[c].get_buffer(outbuffer, SOUNDBUFLEN, sound_handlers[c].priv);
|
|
|
|
|
|
|
|
|
|
|
2017-01-16 01:49:19 +01:00
|
|
|
for (c = 0; c < SOUNDBUFLEN * 2; c++)
|
|
|
|
|
{
|
2017-06-14 07:21:01 +02:00
|
|
|
if (sound_is_float)
|
|
|
|
|
{
|
|
|
|
|
outbuffer_ex[c] = ((float) outbuffer[c]) / 32768.0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (outbuffer[c] > 32767)
|
|
|
|
|
outbuffer[c] = 32767;
|
|
|
|
|
if (outbuffer[c] < -32768)
|
|
|
|
|
outbuffer[c] = -32768;
|
|
|
|
|
|
|
|
|
|
outbuffer_ex_int16[c] = outbuffer[c];
|
|
|
|
|
}
|
2017-01-16 01:49:19 +01:00
|
|
|
}
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-06-14 07:21:01 +02:00
|
|
|
if (soundon)
|
|
|
|
|
{
|
|
|
|
|
if (sound_is_float)
|
|
|
|
|
{
|
|
|
|
|
givealbuffer(outbuffer_ex);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2017-06-19 06:46:08 +02:00
|
|
|
givealbuffer(outbuffer_ex_int16);
|
2017-06-14 07:21:01 +02:00
|
|
|
}
|
|
|
|
|
}
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-02-02 02:55:08 +01:00
|
|
|
if (cd_thread_enable)
|
|
|
|
|
{
|
|
|
|
|
cd_buf_update--;
|
|
|
|
|
if (!cd_buf_update)
|
|
|
|
|
{
|
|
|
|
|
cd_buf_update = (48000 / SOUNDBUFLEN) / (CD_FREQ / CD_BUFLEN);
|
|
|
|
|
thread_set_event(sound_cd_event);
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-06-26 00:34:39 +02:00
|
|
|
|
|
|
|
|
sound_pos_global = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-05 01:20:51 -04:00
|
|
|
void sound_speed_changed(void)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2017-10-09 01:48:36 +02:00
|
|
|
sound_poll_latch = (int64_t)((double)TIMER_USEC * (1000000.0 / 48000.0));
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2017-06-05 01:20:51 -04:00
|
|
|
void sound_reset(void)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2018-04-25 23:51:13 +02:00
|
|
|
sound_realloc_buffers();
|
|
|
|
|
|
|
|
|
|
midi_device_init();
|
|
|
|
|
inital();
|
2017-01-16 01:49:19 +01:00
|
|
|
|
2016-06-26 00:34:39 +02:00
|
|
|
timer_add(sound_poll, &sound_poll_time, TIMER_ALWAYS_ENABLED, NULL);
|
|
|
|
|
|
|
|
|
|
sound_handlers_num = 0;
|
2018-02-15 23:14:44 +01:00
|
|
|
sound_process_handlers_num = 0;
|
|
|
|
|
|
2016-06-26 00:34:39 +02:00
|
|
|
sound_set_cd_volume(65535, 65535);
|
2018-04-25 23:51:13 +02:00
|
|
|
}
|
2017-01-16 01:49:19 +01:00
|
|
|
|
2018-04-25 23:51:13 +02:00
|
|
|
void sound_card_reset(void)
|
|
|
|
|
{
|
|
|
|
|
sound_card_init();
|
|
|
|
|
if (mpu401_standalone_enable)
|
|
|
|
|
mpu401_device_add();
|
|
|
|
|
if (GUS)
|
|
|
|
|
device_add(&gus_device);
|
|
|
|
|
if (GAMEBLASTER)
|
|
|
|
|
device_add(&cms_device);
|
|
|
|
|
if (SSI2001)
|
|
|
|
|
device_add(&ssi2001_device);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
2017-02-02 02:55:08 +01:00
|
|
|
|
2017-10-19 23:55:51 +02:00
|
|
|
void sound_cd_thread_end(void)
|
|
|
|
|
{
|
2017-12-05 20:19:19 +01:00
|
|
|
if (cdaudioon) {
|
|
|
|
|
cdaudioon = 0;
|
|
|
|
|
|
2018-05-21 19:04:05 +02:00
|
|
|
sound_log("Waiting for CD Audio thread to terminate...\n");
|
2017-12-05 20:19:19 +01:00
|
|
|
thread_set_event(sound_cd_event);
|
2017-10-19 23:55:51 +02:00
|
|
|
thread_wait(sound_cd_thread_h, -1);
|
2018-05-21 19:04:05 +02:00
|
|
|
sound_log("CD Audio thread terminated...\n");
|
2017-10-19 23:55:51 +02:00
|
|
|
|
|
|
|
|
if (sound_cd_event) {
|
|
|
|
|
thread_destroy_event(sound_cd_event);
|
|
|
|
|
sound_cd_event = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sound_cd_thread_h = NULL;
|
2017-12-05 20:19:19 +01:00
|
|
|
|
|
|
|
|
if (sound_cd_start_event) {
|
|
|
|
|
thread_destroy_event(sound_cd_start_event);
|
|
|
|
|
sound_cd_event = NULL;
|
|
|
|
|
}
|
2017-10-19 23:55:51 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-05 01:20:51 -04:00
|
|
|
void sound_cd_thread_reset(void)
|
2017-02-02 02:55:08 +01:00
|
|
|
{
|
|
|
|
|
int i = 0;
|
|
|
|
|
int available_cdrom_drives = 0;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < CDROM_NUM; i++)
|
|
|
|
|
{
|
2018-04-25 23:51:13 +02:00
|
|
|
if (cdrom[i] && cdrom[i]->handler && cdrom[i]->handler->audio_stop)
|
|
|
|
|
{
|
|
|
|
|
cdrom[i]->handler->audio_stop(i);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((cdrom_drives[i].bus_type != CDROM_BUS_DISABLED) && cdrom[i])
|
2017-02-02 02:55:08 +01:00
|
|
|
{
|
|
|
|
|
available_cdrom_drives++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (available_cdrom_drives && !cd_thread_enable)
|
|
|
|
|
{
|
2018-02-15 23:14:44 +01:00
|
|
|
cdaudioon = 1;
|
|
|
|
|
|
2017-12-05 20:19:19 +01:00
|
|
|
sound_cd_start_event = thread_create_event();
|
|
|
|
|
|
2017-02-03 23:24:56 +01:00
|
|
|
sound_cd_event = thread_create_event();
|
|
|
|
|
sound_cd_thread_h = thread_create(sound_cd_thread, NULL);
|
2017-12-05 20:19:19 +01:00
|
|
|
|
|
|
|
|
thread_wait_event(sound_cd_start_event, -1);
|
2018-02-15 23:14:44 +01:00
|
|
|
thread_reset_event(sound_cd_start_event);
|
2017-02-02 02:55:08 +01:00
|
|
|
}
|
|
|
|
|
else if (!available_cdrom_drives && cd_thread_enable)
|
|
|
|
|
{
|
2017-10-19 23:55:51 +02:00
|
|
|
sound_cd_thread_end();
|
2017-02-02 02:55:08 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cd_thread_enable = available_cdrom_drives ? 1 : 0;
|
|
|
|
|
}
|