mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-07-05 09:28:57 +00:00
- supported audio formats are now kept in STL vectors
- added run-time audio parameter switching for OSS/ESD audio output - setting ESPEAKER env variable causes B2 to try ESD before OSS
This commit is contained in:
parent
abd6539568
commit
7eb6ed2b86
@ -9,6 +9,8 @@ V1.0 (snapshot) - <date>
|
||||
depth, which can be switched on-the-fly
|
||||
- Unix: Ctrl-F5 grabs mouse in windowed mode (enhanced compatibility
|
||||
with games like flight simulators)
|
||||
- Unix: audio sample rate, bit depth and channel count are adjustable
|
||||
in the MacOS "Sound" control panel
|
||||
|
||||
V0.9 (release 0.9-1) - 31.May 2001
|
||||
- final adjustments for 0.9 release
|
||||
|
@ -10,7 +10,6 @@ General:
|
||||
- Disk: rdVerify
|
||||
- CD-ROM: track lists, positioning type 3, TOC type 4/5, ReadHeader/ReadMCN/
|
||||
ReadISRC/ReadAudio/ReadAllSubcodes
|
||||
- Sound output rate/bits/channels switching
|
||||
- Sound in
|
||||
- Video: multiple monitor support
|
||||
- More accurate Time Manager
|
||||
@ -31,10 +30,12 @@ AmigaOS:
|
||||
- Patch 512K ROM for 68040/060 caches
|
||||
- Input handler instead of IDCMP?
|
||||
- Last sound buffer is not played
|
||||
- Sound output rate/bits/channels switching
|
||||
|
||||
BeOS:
|
||||
- clip_beos.cpp: clip BeOS->Basilisk
|
||||
- Last sound buffer is not played
|
||||
- Sound output rate/bits/channels switching
|
||||
|
||||
Unix:
|
||||
- clip_unix.cpp: clip Unix->Basilisk
|
||||
@ -42,7 +43,6 @@ Unix:
|
||||
- sys_unix.cpp: SysFormat(), SysIsFixedDisk(), SysIsDiskInserted(), prevent/allow
|
||||
for non-floppy/CDROM devices
|
||||
- scsi_linux.cpp: adapt to SCSI Generic driver V2.0
|
||||
- ESD vs. /dev/dsp should be a prefs item
|
||||
- ESD is also available on Solaris
|
||||
- maybe use SDL for sound?
|
||||
- serial_unix.cpp: provide a way to pipe input/output to programs
|
||||
|
@ -37,15 +37,6 @@
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
// Supported sample rates, sizes and channels
|
||||
int audio_num_sample_rates = 1;
|
||||
uint32 audio_sample_rates[] = {22050 << 16};
|
||||
int audio_num_sample_sizes = 1;
|
||||
uint16 audio_sample_sizes[] = {16};
|
||||
int audio_num_channel_counts = 1;
|
||||
uint16 audio_channel_counts[] = {2};
|
||||
|
||||
|
||||
// Global variables
|
||||
static ULONG ahi_id = AHI_DEFAULT_ID; // AHI audio ID
|
||||
static struct AHIAudioCtrl *ahi_ctrl = NULL;
|
||||
@ -64,14 +55,23 @@ static __saveds __attribute__((regparm(3))) ULONG audio_callback(struct Hook *ho
|
||||
* Initialization
|
||||
*/
|
||||
|
||||
// Set AudioStatus to reflect current audio stream format
|
||||
static void set_audio_status_format(void)
|
||||
{
|
||||
AudioStatus.sample_rate = audio_sample_rates[0];
|
||||
AudioStatus.sample_size = audio_sample_sizes[0];
|
||||
AudioStatus.channels = audio_channel_counts[0];
|
||||
}
|
||||
|
||||
void AudioInit(void)
|
||||
{
|
||||
sample[0].ahisi_Address = sample[1].ahisi_Address = NULL;
|
||||
|
||||
// Init audio status and feature flags
|
||||
AudioStatus.sample_rate = audio_sample_rates[0];
|
||||
AudioStatus.sample_size = audio_sample_sizes[0];
|
||||
AudioStatus.channels = audio_channel_counts[0];
|
||||
audio_sample_rates.push_back(22050 << 16);
|
||||
audio_sample_sizes.push_back(16);
|
||||
audio_channel_counts.push_back(2);
|
||||
set_audio_status_format();
|
||||
AudioStatus.mixer = 0;
|
||||
AudioStatus.num_sources = 0;
|
||||
audio_component_flags = cmpWantsRegisterMessage | kStereoOut | k16BitOut;
|
||||
@ -250,16 +250,19 @@ void AudioInterrupt(void)
|
||||
* It is guaranteed that AudioStatus.num_sources == 0
|
||||
*/
|
||||
|
||||
void audio_set_sample_rate(int index)
|
||||
bool audio_set_sample_rate(int index)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void audio_set_sample_size(int index)
|
||||
bool audio_set_sample_size(int index)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void audio_set_channels(int index)
|
||||
bool audio_set_channels(int index)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -35,14 +35,6 @@
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
// Supported sample rates, sizes and channels
|
||||
int audio_num_sample_rates = 1;
|
||||
uint32 audio_sample_rates[] = {44100 << 16};
|
||||
int audio_num_sample_sizes = 1;
|
||||
uint16 audio_sample_sizes[] = {16};
|
||||
int audio_num_channel_counts = 1;
|
||||
uint16 audio_channel_counts[] = {2};
|
||||
|
||||
// Global variables
|
||||
static int audio_irq_done_sem = -1; // Signal from interrupt to streaming thread: data block read
|
||||
static BSoundPlayer *the_player;
|
||||
@ -107,12 +99,21 @@ static status_t audio_manager(void *arg)
|
||||
* Initialization
|
||||
*/
|
||||
|
||||
void AudioInit(void)
|
||||
// Set AudioStatus to reflect current audio stream format
|
||||
static void set_audio_status_format(void)
|
||||
{
|
||||
// Init audio status and feature flags
|
||||
AudioStatus.sample_rate = audio_sample_rates[0];
|
||||
AudioStatus.sample_size = audio_sample_sizes[0];
|
||||
AudioStatus.channels = audio_channel_counts[0];
|
||||
}
|
||||
|
||||
void AudioInit(void)
|
||||
{
|
||||
// Init audio status and feature flags
|
||||
audio_sample_rates.push_back(44100 << 16);
|
||||
audio_sample_sizes.push_back(16);
|
||||
audio_channel_counts.push_back(2);
|
||||
set_audio_status_format();
|
||||
AudioStatus.mixer = 0;
|
||||
AudioStatus.num_sources = 0;
|
||||
audio_component_flags = cmpWantsRegisterMessage | kStereoOut | k16BitOut;
|
||||
@ -274,16 +275,19 @@ void AudioInterrupt(void)
|
||||
* It is guaranteed that AudioStatus.num_sources == 0
|
||||
*/
|
||||
|
||||
void audio_set_sample_rate(int index)
|
||||
bool audio_set_sample_rate(int index)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void audio_set_sample_size(int index)
|
||||
bool audio_set_sample_size(int index)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void audio_set_channels(int index)
|
||||
bool audio_set_channels(int index)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -40,14 +40,6 @@
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
// Supported sample rates, sizes and channels (defaults)
|
||||
int audio_num_sample_rates = 1;
|
||||
uint32 audio_sample_rates[] = {44100 << 16};
|
||||
int audio_num_sample_sizes = 1;
|
||||
uint16 audio_sample_sizes[] = {16};
|
||||
int audio_num_channel_counts = 1;
|
||||
uint16 audio_channel_counts[] = {2};
|
||||
|
||||
// Global variables
|
||||
static int audio_fd = -1; // fd from audio library
|
||||
static sem_t audio_irq_done_sem; // Signal from interrupt to streaming thread: data block read
|
||||
@ -168,6 +160,9 @@ bool audio_init_al(void)
|
||||
void AudioInit(void)
|
||||
{
|
||||
// Init audio status (defaults) and feature flags
|
||||
audio_sample_rates.push_back(44100 << 16);
|
||||
audio_sample_sizes.push_back(16);
|
||||
audio_channel_counts.push_back(2);
|
||||
set_audio_status_format();
|
||||
AudioStatus.mixer = 0;
|
||||
AudioStatus.num_sources = 0;
|
||||
|
@ -40,14 +40,6 @@
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
// Supported sample rates, sizes and channels
|
||||
int audio_num_sample_rates = 1;
|
||||
uint32 audio_sample_rates[] = {44100 << 16};
|
||||
int audio_num_sample_sizes = 1;
|
||||
uint16 audio_sample_sizes[] = {16};
|
||||
int audio_num_channel_counts = 1;
|
||||
uint16 audio_channel_counts[] = {2};
|
||||
|
||||
// Global variables
|
||||
static int fd = -1; // fd of /dev/audio
|
||||
static sem_t audio_irq_done_sem; // Signal from interrupt to streaming thread: data block read
|
||||
@ -64,14 +56,23 @@ static void *stream_func(void *arg);
|
||||
* Initialization
|
||||
*/
|
||||
|
||||
// Set AudioStatus to reflect current audio stream format
|
||||
static void set_audio_status_format(void)
|
||||
{
|
||||
AudioStatus.sample_rate = audio_sample_rates[0];
|
||||
AudioStatus.sample_size = audio_sample_sizes[0];
|
||||
AudioStatus.channels = audio_channel_counts[0];
|
||||
}
|
||||
|
||||
void AudioInit(void)
|
||||
{
|
||||
char str[256];
|
||||
|
||||
// Init audio status and feature flags
|
||||
AudioStatus.sample_rate = audio_sample_rates[0];
|
||||
AudioStatus.sample_size = audio_sample_sizes[0];
|
||||
AudioStatus.channels = audio_channel_counts[0];
|
||||
audio_sample_rates.push_back(44100 << 16);
|
||||
audio_sample_sizes.push_back(16);
|
||||
audio_channel_counts.push_back(2);
|
||||
set_audio_status_format();
|
||||
AudioStatus.mixer = 0;
|
||||
AudioStatus.num_sources = 0;
|
||||
audio_component_flags = cmpWantsRegisterMessage | kStereoOut | k16BitOut;
|
||||
|
@ -49,13 +49,10 @@
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
// Supported sample rates, sizes and channels (defaults)
|
||||
int audio_num_sample_rates = 1;
|
||||
uint32 audio_sample_rates[] = {44100 << 16};
|
||||
int audio_num_sample_sizes = 1;
|
||||
uint16 audio_sample_sizes[] = {16};
|
||||
int audio_num_channel_counts = 1;
|
||||
uint16 audio_channel_counts[] = {2};
|
||||
// The currently selected audio parameters (indices in audio_sample_rates[] etc. vectors)
|
||||
static int audio_sample_rate_index = 0;
|
||||
static int audio_sample_size_index = 0;
|
||||
static int audio_channel_count_index = 0;
|
||||
|
||||
// Constants
|
||||
#define DSP_NAME "/dev/dsp"
|
||||
@ -63,6 +60,7 @@ uint16 audio_channel_counts[] = {2};
|
||||
// Global variables
|
||||
static int audio_fd = -1; // fd of /dev/dsp or ESD
|
||||
static int mixer_fd = -1; // fd of /dev/mixer
|
||||
static bool formats_known = false; // Flag: available audio formats have been probed
|
||||
static sem_t audio_irq_done_sem; // Signal from interrupt to streaming thread: data block read
|
||||
static bool sem_inited = false; // Flag: audio_irq_done_sem initialized
|
||||
static int sound_buffer_size; // Size of sound buffer in bytes
|
||||
@ -84,70 +82,120 @@ static void *stream_func(void *arg);
|
||||
// Set AudioStatus to reflect current audio stream format
|
||||
static void set_audio_status_format(void)
|
||||
{
|
||||
AudioStatus.sample_rate = audio_sample_rates[0];
|
||||
AudioStatus.sample_size = audio_sample_sizes[0];
|
||||
AudioStatus.channels = audio_channel_counts[0];
|
||||
AudioStatus.sample_rate = audio_sample_rates[audio_sample_rate_index];
|
||||
AudioStatus.sample_size = audio_sample_sizes[audio_sample_size_index];
|
||||
AudioStatus.channels = audio_channel_counts[audio_channel_count_index];
|
||||
}
|
||||
|
||||
// Init using /dev/dsp, returns false on error
|
||||
bool audio_init_dsp(void)
|
||||
static bool open_dsp(void)
|
||||
{
|
||||
// Open /dev/dsp
|
||||
audio_fd = open(DSP_NAME, O_WRONLY);
|
||||
if (audio_fd < 0) {
|
||||
fprintf(stderr, "WARNING: Cannot open %s (%s)\n", DSP_NAME, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
printf("Using " DSP_NAME " audio output\n");
|
||||
|
||||
// Get supported sample formats
|
||||
unsigned long format;
|
||||
ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &format);
|
||||
if ((format & (AFMT_U8 | AFMT_S16_BE | AFMT_S16_LE)) == 0) {
|
||||
WarningAlert(GetString(STR_AUDIO_FORMAT_WARN));
|
||||
close(audio_fd);
|
||||
audio_fd = -1;
|
||||
return false;
|
||||
if (!formats_known) {
|
||||
unsigned long format;
|
||||
ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &format);
|
||||
if (format & AFMT_U8)
|
||||
audio_sample_sizes.push_back(8);
|
||||
if (format & (AFMT_S16_BE | AFMT_S16_LE))
|
||||
audio_sample_sizes.push_back(16);
|
||||
|
||||
int stereo = 0;
|
||||
if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo) == 0 && stereo == 0)
|
||||
audio_channel_counts.push_back(1);
|
||||
stereo = 1;
|
||||
if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo) == 0 && stereo == 1)
|
||||
audio_channel_counts.push_back(2);
|
||||
|
||||
if (audio_sample_sizes.empty() || audio_channel_counts.empty()) {
|
||||
WarningAlert(GetString(STR_AUDIO_FORMAT_WARN));
|
||||
close(audio_fd);
|
||||
audio_fd = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
audio_sample_rates.push_back(11025 << 16);
|
||||
audio_sample_rates.push_back(22050 << 16);
|
||||
int rate = 44100;
|
||||
ioctl(audio_fd, SNDCTL_DSP_SPEED, &rate);
|
||||
if (rate > 22050)
|
||||
audio_sample_rates.push_back(rate << 16);
|
||||
|
||||
// Default to highest supported values
|
||||
audio_sample_rate_index = audio_sample_rates.size() - 1;
|
||||
audio_sample_size_index = audio_sample_sizes.size() - 1;
|
||||
audio_channel_count_index = audio_channel_counts.size() - 1;
|
||||
formats_known = true;
|
||||
}
|
||||
if (format & (AFMT_S16_BE | AFMT_S16_LE)) {
|
||||
audio_sample_sizes[0] = 16;
|
||||
silence_byte = 0;
|
||||
} else {
|
||||
audio_sample_sizes[0] = 8;
|
||||
silence_byte = 0x80;
|
||||
}
|
||||
if (!(format & AFMT_S16_BE))
|
||||
little_endian = true;
|
||||
|
||||
// Set DSP parameters
|
||||
format = audio_sample_sizes[0] == 8 ? AFMT_U8 : (little_endian ? AFMT_S16_LE : AFMT_S16_BE);
|
||||
unsigned long format;
|
||||
if (audio_sample_sizes[audio_sample_size_index] == 8) {
|
||||
format = AFMT_U8;
|
||||
little_endian = false;
|
||||
silence_byte = 0x80;
|
||||
} else {
|
||||
unsigned long sup_format;
|
||||
ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &format);
|
||||
if (sup_format & AFMT_S16_BE) {
|
||||
little_endian = false;
|
||||
format = AFMT_S16_BE;
|
||||
} else {
|
||||
little_endian = true;
|
||||
format = AFMT_S16_LE;
|
||||
}
|
||||
silence_byte = 0;
|
||||
}
|
||||
ioctl(audio_fd, SNDCTL_DSP_SETFMT, &format);
|
||||
int frag = 0x0004000c; // Block size: 4096 frames
|
||||
ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag);
|
||||
int stereo = (audio_channel_counts[0] == 2);
|
||||
int stereo = (audio_channel_counts[audio_channel_count_index] == 2);
|
||||
ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo);
|
||||
int rate = audio_sample_rates[0] >> 16;
|
||||
int rate = audio_sample_rates[audio_sample_rate_index] >> 16;
|
||||
ioctl(audio_fd, SNDCTL_DSP_SPEED, &rate);
|
||||
audio_sample_rates[0] = rate << 16;
|
||||
|
||||
// Set AudioStatus again because we now know more about the sound
|
||||
// system's capabilities
|
||||
set_audio_status_format();
|
||||
|
||||
// Get sound buffer size
|
||||
ioctl(audio_fd, SNDCTL_DSP_GETBLKSIZE, &audio_frames_per_block);
|
||||
D(bug("DSP_GETBLKSIZE %d\n", audio_frames_per_block));
|
||||
sound_buffer_size = (AudioStatus.sample_size >> 3) * AudioStatus.channels * audio_frames_per_block;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Init using ESD, returns false on error
|
||||
bool audio_init_esd(void)
|
||||
static bool open_esd(void)
|
||||
{
|
||||
#ifdef ENABLE_ESD
|
||||
printf("Using ESD audio output\n");
|
||||
// ESD supports a variety of audio formats
|
||||
if (!formats_known) {
|
||||
audio_sample_rates.push_back(11025 << 16);
|
||||
audio_sample_rates.push_back(22050 << 16);
|
||||
audio_sample_rates.push_back(44100 << 16);
|
||||
audio_sample_sizes.push_back(8);
|
||||
audio_sample_sizes.push_back(16);
|
||||
audio_channel_counts.push_back(1);
|
||||
audio_channel_counts.push_back(2);
|
||||
|
||||
// Default to 44.1kHz, 16-bit, stereo
|
||||
audio_sample_rate_index = 2;
|
||||
audio_sample_size_index = 1;
|
||||
audio_channel_count_index = 1;
|
||||
formats_known = true;
|
||||
}
|
||||
|
||||
// ESD audio format
|
||||
esd_format_t format = ESD_STREAM | ESD_PLAY;
|
||||
if (AudioStatus.sample_size == 8)
|
||||
if (audio_sample_sizes[audio_sample_size_index] == 8)
|
||||
format |= ESD_BITS8;
|
||||
else
|
||||
format |= ESD_BITS16;
|
||||
if (AudioStatus.channels == 1)
|
||||
if (audio_channel_counts[audio_channel_count_index] == 1)
|
||||
format |= ESD_MONO;
|
||||
else
|
||||
format |= ESD_STEREO;
|
||||
@ -160,62 +208,49 @@ bool audio_init_esd(void)
|
||||
silence_byte = 0; // Is this correct for 8-bit mode?
|
||||
|
||||
// Open connection to ESD server
|
||||
audio_fd = esd_play_stream(format, AudioStatus.sample_rate >> 16, NULL, NULL);
|
||||
audio_fd = esd_play_stream(format, audio_sample_rates[audio_sample_rate_index] >> 16, NULL, NULL);
|
||||
if (audio_fd < 0) {
|
||||
char str[256];
|
||||
sprintf(str, GetString(STR_NO_ESD_WARN), strerror(errno));
|
||||
WarningAlert(str);
|
||||
fprintf(stderr, "WARNING: Cannot open ESD connection\n");
|
||||
formats_known = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
printf("Using ESD audio output\n");
|
||||
|
||||
// Sound buffer size = 4096 frames
|
||||
audio_frames_per_block = 4096;
|
||||
sound_buffer_size = (AudioStatus.sample_size >> 3) * AudioStatus.channels * audio_frames_per_block;
|
||||
return true;
|
||||
#else
|
||||
ErrorAlert("Basilisk II has been compiled with ESD support disabled.");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void AudioInit(void)
|
||||
static bool open_audio(void)
|
||||
{
|
||||
char str[256];
|
||||
|
||||
// Init audio status (defaults) and feature flags
|
||||
set_audio_status_format();
|
||||
AudioStatus.mixer = 0;
|
||||
AudioStatus.num_sources = 0;
|
||||
audio_component_flags = cmpWantsRegisterMessage | kStereoOut | k16BitOut;
|
||||
|
||||
// Sound disabled in prefs? Then do nothing
|
||||
if (PrefsFindBool("nosound"))
|
||||
return;
|
||||
#ifdef ENABLE_ESD
|
||||
// If ESPEAKER is set, the user probably wants to use ESD, so try that first
|
||||
if (getenv("ESPEAKER"))
|
||||
if (open_esd())
|
||||
goto dev_opened;
|
||||
#endif
|
||||
|
||||
// Try to open /dev/dsp
|
||||
audio_fd = open(DSP_NAME, O_WRONLY);
|
||||
if (audio_fd < 0) {
|
||||
if (open_dsp())
|
||||
goto dev_opened;
|
||||
|
||||
#ifdef ENABLE_ESD
|
||||
if (!audio_init_esd())
|
||||
return;
|
||||
#else
|
||||
sprintf(str, GetString(STR_NO_AUDIO_DEV_WARN), DSP_NAME, strerror(errno));
|
||||
WarningAlert(str);
|
||||
return;
|
||||
// Hm, /dev/dsp failed so we try ESD again if ESPEAKER wasn't set
|
||||
if (!getenv("ESPEAKER"))
|
||||
if (open_esd())
|
||||
goto dev_opened;
|
||||
#endif
|
||||
} else
|
||||
if (!audio_init_dsp())
|
||||
return;
|
||||
|
||||
// Try to open /dev/mixer
|
||||
mixer_fd = open("/dev/mixer", O_RDWR);
|
||||
if (mixer_fd < 0)
|
||||
printf("WARNING: Cannot open /dev/mixer (%s)", strerror(errno));
|
||||
// No audio device succeeded
|
||||
WarningAlert(GetString(STR_NO_AUDIO_WARN));
|
||||
return false;
|
||||
|
||||
// Init semaphore
|
||||
if (sem_init(&audio_irq_done_sem, 0, 0) < 0)
|
||||
return;
|
||||
sem_inited = true;
|
||||
// Device opened, set AudioStatus
|
||||
dev_opened:
|
||||
sound_buffer_size = (audio_sample_sizes[audio_sample_size_index] >> 3) * audio_channel_counts[audio_channel_count_index] * audio_frames_per_block;
|
||||
set_audio_status_format();
|
||||
|
||||
// Start streaming thread
|
||||
pthread_attr_init(&stream_thread_attr);
|
||||
@ -228,10 +263,42 @@ void AudioInit(void)
|
||||
pthread_attr_setschedparam(&stream_thread_attr, &fifo_param);
|
||||
}
|
||||
#endif
|
||||
stream_thread_cancel = false;
|
||||
stream_thread_active = (pthread_create(&stream_thread, &stream_thread_attr, stream_func, NULL) == 0);
|
||||
|
||||
// Everything OK
|
||||
// Everything went fine
|
||||
audio_open = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void AudioInit(void)
|
||||
{
|
||||
char str[256];
|
||||
|
||||
// Init audio status (reasonable defaults) and feature flags
|
||||
AudioStatus.sample_rate = 44100 << 16;
|
||||
AudioStatus.sample_size = 16;
|
||||
AudioStatus.channels = 2;
|
||||
AudioStatus.mixer = 0;
|
||||
AudioStatus.num_sources = 0;
|
||||
audio_component_flags = cmpWantsRegisterMessage | kStereoOut | k16BitOut;
|
||||
|
||||
// Sound disabled in prefs? Then do nothing
|
||||
if (PrefsFindBool("nosound"))
|
||||
return;
|
||||
|
||||
// Init semaphore
|
||||
if (sem_init(&audio_irq_done_sem, 0, 0) < 0)
|
||||
return;
|
||||
sem_inited = true;
|
||||
|
||||
// Try to open /dev/mixer
|
||||
mixer_fd = open("/dev/mixer", O_RDWR);
|
||||
if (mixer_fd < 0)
|
||||
printf("WARNING: Cannot open /dev/mixer (%s)", strerror(errno));
|
||||
|
||||
// Open and initialize audio device
|
||||
open_audio();
|
||||
}
|
||||
|
||||
|
||||
@ -239,7 +306,7 @@ void AudioInit(void)
|
||||
* Deinitialization
|
||||
*/
|
||||
|
||||
void AudioExit(void)
|
||||
static void close_audio(void)
|
||||
{
|
||||
// Stop stream and delete semaphore
|
||||
if (stream_thread_active) {
|
||||
@ -250,16 +317,28 @@ void AudioExit(void)
|
||||
pthread_join(stream_thread, NULL);
|
||||
stream_thread_active = false;
|
||||
}
|
||||
if (sem_inited)
|
||||
sem_destroy(&audio_irq_done_sem);
|
||||
|
||||
// Close /dev/dsp
|
||||
if (audio_fd > 0)
|
||||
// Close /dev/dsp or ESD socket
|
||||
if (audio_fd >= 0) {
|
||||
close(audio_fd);
|
||||
audio_fd = -1;
|
||||
}
|
||||
|
||||
audio_open = false;
|
||||
}
|
||||
|
||||
void AudioExit(void)
|
||||
{
|
||||
if (sem_inited) {
|
||||
sem_destroy(&audio_irq_done_sem);
|
||||
sem_inited = false;
|
||||
}
|
||||
|
||||
// Close /dev/mixer
|
||||
if (mixer_fd > 0)
|
||||
if (mixer_fd >= 0) {
|
||||
close(mixer_fd);
|
||||
mixer_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -372,20 +451,29 @@ void AudioInterrupt(void)
|
||||
|
||||
/*
|
||||
* Set sampling parameters
|
||||
* "index" is an index into the audio_sample_rates[] etc. arrays
|
||||
* "index" is an index into the audio_sample_rates[] etc. vectors
|
||||
* It is guaranteed that AudioStatus.num_sources == 0
|
||||
*/
|
||||
|
||||
void audio_set_sample_rate(int index)
|
||||
bool audio_set_sample_rate(int index)
|
||||
{
|
||||
close_audio();
|
||||
audio_sample_rate_index = index;
|
||||
return open_audio();
|
||||
}
|
||||
|
||||
void audio_set_sample_size(int index)
|
||||
bool audio_set_sample_size(int index)
|
||||
{
|
||||
close_audio();
|
||||
audio_sample_size_index = index;
|
||||
return open_audio();
|
||||
}
|
||||
|
||||
void audio_set_channels(int index)
|
||||
bool audio_set_channels(int index)
|
||||
{
|
||||
close_audio();
|
||||
audio_channel_count_index = index;
|
||||
return open_audio();
|
||||
}
|
||||
|
||||
|
||||
|
@ -51,8 +51,8 @@ user_string_def platform_strings[] = {
|
||||
{STR_SCSI_DEVICE_OPEN_WARN, "Cannot open %s (%s). SCSI Manager access to this device will be disabled."},
|
||||
{STR_SCSI_DEVICE_NOT_SCSI_WARN, "%s doesn't seem to comply to the Generic SCSI API. SCSI Manager access to this device will be disabled."},
|
||||
{STR_NO_AUDIO_DEV_WARN, "Cannot open %s (%s). Audio output will be disabled."},
|
||||
{STR_NO_ESD_WARN, "Cannot open ESD connection. Audio output will be disabled."},
|
||||
{STR_AUDIO_FORMAT_WARN, "Audio hardware doesn't support signed 16 bit format. Audio output will be disabled."},
|
||||
{STR_NO_AUDIO_WARN, "No audio device found, audio output will be disabled."},
|
||||
{STR_AUDIO_FORMAT_WARN, "Audio hardware doesn't seem to support necessary format. Audio output will be disabled."},
|
||||
{STR_KEYCODE_FILE_WARN, "Cannot open keycode translation file %s (%s)."},
|
||||
{STR_KEYCODE_VENDOR_WARN, "Cannot find vendor '%s' in keycode translation file %s."},
|
||||
|
||||
|
@ -42,7 +42,7 @@ enum {
|
||||
STR_SCSI_DEVICE_OPEN_WARN,
|
||||
STR_SCSI_DEVICE_NOT_SCSI_WARN,
|
||||
STR_NO_AUDIO_DEV_WARN,
|
||||
STR_NO_ESD_WARN,
|
||||
STR_NO_AUDIO_WARN,
|
||||
STR_AUDIO_FORMAT_WARN,
|
||||
STR_KEYCODE_FILE_WARN,
|
||||
STR_KEYCODE_VENDOR_WARN,
|
||||
|
@ -36,6 +36,11 @@
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
// Supported sample rates, sizes and channels
|
||||
vector<uint32> audio_sample_rates;
|
||||
vector<uint16> audio_sample_sizes;
|
||||
vector<uint16> audio_channel_counts;
|
||||
|
||||
// Global variables
|
||||
struct audio_status AudioStatus; // Current audio status (sample rate etc.)
|
||||
bool audio_open = false; // Flag: audio is initialized and ready
|
||||
@ -73,15 +78,15 @@ static int32 AudioGetInfo(uint32 infoPtr, uint32 selector, uint32 sourceID)
|
||||
break;
|
||||
|
||||
case siSampleSizeAvailable: {
|
||||
r.d[0] = audio_num_sample_sizes * 2;
|
||||
r.d[0] = audio_sample_sizes.size() * 2;
|
||||
Execute68kTrap(0xa122, &r); // NewHandle()
|
||||
uint32 h = r.a[0];
|
||||
if (h == 0)
|
||||
return memFullErr;
|
||||
WriteMacInt16(infoPtr + sil_count, audio_num_sample_sizes);
|
||||
WriteMacInt16(infoPtr + sil_count, audio_sample_sizes.size());
|
||||
WriteMacInt32(infoPtr + sil_infoHandle, h);
|
||||
uint32 sp = ReadMacInt32(h);
|
||||
for (i=0; i<audio_num_sample_sizes; i++)
|
||||
for (i=0; i<audio_sample_sizes.size(); i++)
|
||||
WriteMacInt16(sp + i*2, audio_sample_sizes[i]);
|
||||
break;
|
||||
}
|
||||
@ -91,15 +96,15 @@ static int32 AudioGetInfo(uint32 infoPtr, uint32 selector, uint32 sourceID)
|
||||
break;
|
||||
|
||||
case siChannelAvailable: {
|
||||
r.d[0] = audio_num_channel_counts * 2;
|
||||
r.d[0] = audio_channel_counts.size() * 2;
|
||||
Execute68kTrap(0xa122, &r); // NewHandle()
|
||||
uint32 h = r.a[0];
|
||||
if (h == 0)
|
||||
return memFullErr;
|
||||
WriteMacInt16(infoPtr + sil_count, audio_num_channel_counts);
|
||||
WriteMacInt16(infoPtr + sil_count, audio_channel_counts.size());
|
||||
WriteMacInt32(infoPtr + sil_infoHandle, h);
|
||||
uint32 sp = ReadMacInt32(h);
|
||||
for (i=0; i<audio_num_channel_counts; i++)
|
||||
for (i=0; i<audio_channel_counts.size(); i++)
|
||||
WriteMacInt16(sp + i*2, audio_channel_counts[i]);
|
||||
break;
|
||||
}
|
||||
@ -109,15 +114,15 @@ static int32 AudioGetInfo(uint32 infoPtr, uint32 selector, uint32 sourceID)
|
||||
break;
|
||||
|
||||
case siSampleRateAvailable: {
|
||||
r.d[0] = audio_num_sample_rates * 4;
|
||||
r.d[0] = audio_sample_rates.size() * 4;
|
||||
Execute68kTrap(0xa122, &r); // NewHandle()
|
||||
uint32 h = r.a[0];
|
||||
if (h == 0)
|
||||
return memFullErr;
|
||||
WriteMacInt16(infoPtr + sil_count, audio_num_sample_rates);
|
||||
WriteMacInt16(infoPtr + sil_count, audio_sample_rates.size());
|
||||
WriteMacInt32(infoPtr + sil_infoHandle, h);
|
||||
uint32 lp = ReadMacInt32(h);
|
||||
for (i=0; i<audio_num_sample_rates; i++)
|
||||
for (i=0; i<audio_sample_rates.size(); i++)
|
||||
WriteMacInt32(lp + i*4, audio_sample_rates[i]);
|
||||
break;
|
||||
}
|
||||
@ -189,10 +194,14 @@ static int32 AudioSetInfo(uint32 infoPtr, uint32 selector, uint32 sourceID)
|
||||
D(bug(" set sample size %08lx\n", infoPtr));
|
||||
if (AudioStatus.num_sources)
|
||||
return siDeviceBusyErr;
|
||||
for (i=0; i<audio_num_sample_sizes; i++)
|
||||
if (infoPtr == AudioStatus.sample_size)
|
||||
return noErr;
|
||||
for (i=0; i<audio_sample_sizes.size(); i++)
|
||||
if (audio_sample_sizes[i] == infoPtr) {
|
||||
audio_set_sample_size(i);
|
||||
return noErr;
|
||||
if (audio_set_sample_size(i))
|
||||
return noErr;
|
||||
else
|
||||
return siInvalidSampleSize;
|
||||
}
|
||||
return siInvalidSampleSize;
|
||||
|
||||
@ -200,10 +209,14 @@ static int32 AudioSetInfo(uint32 infoPtr, uint32 selector, uint32 sourceID)
|
||||
D(bug(" set sample rate %08lx\n", infoPtr));
|
||||
if (AudioStatus.num_sources)
|
||||
return siDeviceBusyErr;
|
||||
for (i=0; i<audio_num_sample_rates; i++)
|
||||
if (infoPtr == AudioStatus.sample_rate)
|
||||
return noErr;
|
||||
for (i=0; i<audio_sample_rates.size(); i++)
|
||||
if (audio_sample_rates[i] == infoPtr) {
|
||||
audio_set_sample_rate(i);
|
||||
return noErr;
|
||||
if (audio_set_sample_rate(i))
|
||||
return noErr;
|
||||
else
|
||||
return siInvalidSampleRate;
|
||||
}
|
||||
return siInvalidSampleRate;
|
||||
|
||||
@ -211,10 +224,14 @@ static int32 AudioSetInfo(uint32 infoPtr, uint32 selector, uint32 sourceID)
|
||||
D(bug(" set number of channels %08lx\n", infoPtr));
|
||||
if (AudioStatus.num_sources)
|
||||
return siDeviceBusyErr;
|
||||
for (i=0; i<audio_num_channel_counts; i++)
|
||||
if (infoPtr == AudioStatus.channels)
|
||||
return noErr;
|
||||
for (i=0; i<audio_channel_counts.size(); i++)
|
||||
if (audio_channel_counts[i] == infoPtr) {
|
||||
audio_set_channels(i);
|
||||
return noErr;
|
||||
if (audio_set_channels(i))
|
||||
return noErr;
|
||||
else
|
||||
return badChannel;
|
||||
}
|
||||
return badChannel;
|
||||
|
||||
|
@ -21,6 +21,12 @@
|
||||
#ifndef AUDIO_H
|
||||
#define AUDIO_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#ifndef NO_STD_NAMESPACE
|
||||
using std::vector;
|
||||
#endif
|
||||
|
||||
extern int32 AudioDispatch(uint32 params, uint32 ti);
|
||||
|
||||
extern bool AudioAvailable; // Flag: audio output available (from the software point of view)
|
||||
@ -41,9 +47,9 @@ extern void AudioInterrupt(void);
|
||||
extern void audio_enter_stream(void);
|
||||
extern void audio_exit_stream(void);
|
||||
|
||||
extern void audio_set_sample_rate(int index);
|
||||
extern void audio_set_sample_size(int index);
|
||||
extern void audio_set_channels(int index);
|
||||
extern bool audio_set_sample_rate(int index);
|
||||
extern bool audio_set_sample_size(int index);
|
||||
extern bool audio_set_channels(int index);
|
||||
|
||||
extern bool audio_get_main_mute(void);
|
||||
extern uint32 audio_get_main_volume(void);
|
||||
@ -68,12 +74,9 @@ extern bool audio_open; // Flag: audio is open and ready
|
||||
extern int audio_frames_per_block; // Number of audio frames per block
|
||||
extern uint32 audio_component_flags; // Component feature flags
|
||||
|
||||
extern int audio_num_sample_rates; // Number of supported sample rates
|
||||
extern uint32 audio_sample_rates[]; // Array of supported sample rates (16.16 fixed point)
|
||||
extern int audio_num_sample_sizes; // Number of supported sample sizes
|
||||
extern uint16 audio_sample_sizes[]; // Array of supported sample sizes
|
||||
extern int audio_num_channel_counts; // Number of supported channel counts
|
||||
extern uint16 audio_channel_counts[]; // Array of supported channels counts
|
||||
extern vector<uint32> audio_sample_rates; // Vector of supported sample rates (16.16 fixed point)
|
||||
extern vector<uint16> audio_sample_sizes; // Vector of supported sample sizes
|
||||
extern vector<uint16> audio_channel_counts; // Array of supported channels counts
|
||||
|
||||
// Audio component global data and 68k routines
|
||||
enum {
|
||||
|
Loading…
Reference in New Issue
Block a user