frodo-wii/Src/SID_hp.h
2009-01-13 18:46:42 +00:00

192 lines
4.5 KiB
C

/*
* SID_hp.h - 6581 emulation, HP-UX specific stuff
*
* Frodo (C) 1994-1997,2002-2005 Christian Bauer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
extern "C" {
#include <sys/audio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
}
#define TXBUFSIZE 16384 // bytes, not samples
#define TXFRAGSIZE 1024 // samples, not bytes
#define TXLOWWATER (TXBUFSIZE-(TXFRAGSIZE*2)) // bytes, not samples
/*
* Initialization
*/
void DigitalRenderer::init_sound(void)
{
ready = false;
if ((fd = open("/dev/audio", O_WRONLY | O_NDELAY, 0)) < 0) {
fprintf(stderr, "unable to open /dev/audio -> no sound\n");
return;
}
int flags;
if ((flags = fcntl (fd, F_GETFL, 0)) < 0) {
fprintf(stderr, "unable to set non-blocking mode for /dev/audio -> no sound\n");
return;
}
flags |= O_NDELAY;
if (fcntl (fd, F_SETFL, flags) < 0) {
fprintf(stderr, "unable to set non-blocking mode for /dev/audio -> no sound\n");
return;
}
if (ioctl(fd, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_LINEAR16BIT)) {
fprintf(stderr, "unable to select 16bit-linear sample format -> no sound\n");
return;
}
if (ioctl(fd, AUDIO_SET_SAMPLE_RATE, 44100)) {
fprintf(stderr, "unable to select 44.1kHz sample-rate -> no sound\n");
return;
}
if (ioctl(fd, AUDIO_SET_CHANNELS, 1)) {
fprintf(stderr, "unable to select 1-channel playback -> no sound\n");
return;
}
// choose between:
// AUDIO_OUT_SPEAKER
// AUDIO_OUT_HEADPHONE
// AUDIO_OUT_LINE
if (ioctl(fd, AUDIO_SET_OUTPUT, AUDIO_OUT_SPEAKER)) {
fprintf(stderr, "unable to select audio output -> no sound\n");
return;
}
{
// set volume:
audio_describe description;
audio_gains gains;
if (ioctl(fd, AUDIO_DESCRIBE, &description)) {
fprintf(stderr, "unable to get audio description -> no sound\n");
return;
}
if (ioctl (fd, AUDIO_GET_GAINS, &gains)) {
fprintf(stderr, "unable to get gain values -> no sound\n");
return;
}
float volume = 1.0;
gains.transmit_gain = (int)((float)description.min_transmit_gain +
(float)(description.max_transmit_gain
- description.min_transmit_gain)
* volume);
if (ioctl (fd, AUDIO_SET_GAINS, &gains)) {
fprintf(stderr, "unable to set gain values -> no sound\n");
return;
}
}
if (ioctl(fd, AUDIO_SET_TXBUFSIZE, TXBUFSIZE)) {
fprintf(stderr, "unable to set transmission buffer size -> no sound\n");
return;
}
sound_calc_buf = new int16[TXFRAGSIZE];
linecnt = 0;
ready = true;
return;
}
/*
* Destructor
*/
DigitalRenderer::~DigitalRenderer()
{
if (fd > 0) {
if (ready) {
ioctl(fd, AUDIO_DRAIN);
}
ioctl(fd, AUDIO_RESET);
close(fd);
}
}
/*
* Pause sound output
*/
void DigitalRenderer::Pause(void)
{
}
/*
* Resume sound output
*/
void DigitalRenderer::Resume(void)
{
}
/*
* Fill buffer, sample volume (for sampled voice)
*/
void DigitalRenderer::EmulateLine(void)
{
sample_buf[sample_in_ptr] = volume;
sample_in_ptr = (sample_in_ptr + 1) % SAMPLE_BUF_SIZE;
// testing the audio status at each raster-line is
// really not necessary. Let's do it every 50th one..
// ought to be enough by far.
linecnt--;
if (linecnt < 0 && ready) {
linecnt = 50;
// check whether we should add some more data to the
// transmission buffer.
if (ioctl(fd, AUDIO_GET_STATUS, &status)) {
fprintf(stderr,"fatal: unable to get audio status\n");
exit(20);
}
if (status.transmit_buffer_count < TXLOWWATER) {
// add one sound fragment..
calc_buffer(sound_calc_buf, TXFRAGSIZE*2);
// since we've checked for enough space in the transmission buffer,
// it is an error if the non-blocking write returns anything but
// TXFRAGSIZE*2
if (TXFRAGSIZE*2 != write (fd, sound_calc_buf, TXFRAGSIZE*2)) {
fprintf(stderr,"fatal: write to audio-device failed\n");
exit(20);
}
}
}
}