Source to src/od-dos/sound/sound.c


Enter a symbol's name here to quickly find it.

 /*
  * UAE - The Un*x Amiga Emulator
  *
  * Support for DOS
  *
  * Copyright 1997, 1998 Gustavo Goedert
  */

/****** This file is broken.  The sample handlers have to go.  ******/

#include "sysconfig.h"
#include "sysdeps.h"

#include "config.h"
#include "options.h"
#include "memory.h"
#include "custom.h"
#include "audio.h"
#include "gensound.h"
#include "sounddep/sound.h"
#include "events.h"

#include <go32.h>
#include <sys/farptr.h>
#include <time.h>

#include "sound/sb.h"

typedef uae_s8 sample8_t;
#define DO_CHANNEL_1(v, c) do { (v) *= audio_channel[c].vol; } while (0)
#define SBASEVAL8(logn) ((logn) == 1 ? SOUND8_BASE_VAL << 7 : SOUND8_BASE_VAL << 8)
#define SBASEVAL16(logn) ((logn) == 1 ? SOUND16_BASE_VAL >> 1 : SOUND16_BASE_VAL)
#define FINISH_DATA(b,logn) do { if (14 - (b) + (logn) > 0) data >>= 14 - (b) + (logn); else data <<= (b) - 14 - (logn); } while (0);

uae_u16 sndbuffer[44100];
uae_u16 *sndbufpt;
int sndbufsize;
extern int sound_table[256][64];
int dspbits;

int sound_curfreq;

void (*SND_DirectWrite)(unsigned int size, int freq); // Pointer to function that plays data on card
#define SND_DirectWrite SB_DirectWrite
volatile int IsPlaying = 0;
int CurrentBuffer = 0;
unsigned int direct_buffers[2], direct_sndbufpt;

void direct_mono_sample16_handler(void);
void direct_mono_sample8_handler(void);
void direct_stereo_sample16_handler(void);
void direct_stereo_sample8_handler(void);
void interpol_freq(int new_freq);
void direct_check_sound_buffers(void);

#define INTERPOL_SIZE 8
int freq_buf[INTERPOL_SIZE];
int buf_tot, buf_pos=0;

inline void interpol_freq(int new_freq) {
    buf_tot = buf_tot - freq_buf[buf_pos] + new_freq;
    freq_buf[buf_pos] = new_freq;
    buf_pos++;
    if (buf_pos == INTERPOL_SIZE) buf_pos = 0;
    sound_curfreq = buf_tot/INTERPOL_SIZE;
    if (sound_curfreq<currprefs.sound_freq) {
	sound_curfreq |= 0xff;
	if (sound_curfreq<5512)
	    sound_curfreq = 5512;
    }
    if (sound_curfreq>currprefs.sound_freq)
	sound_curfreq = currprefs.sound_freq;
}

unsigned int sound_bytes = 0, last_clock = 0;

inline void direct_check_sound_buffers(void) {
    int played_size = direct_sndbufpt - direct_buffers[CurrentBuffer];

    sound_bytes++;
    if ((!IsPlaying) && played_size >= currprefs.sound_minbsiz) {
	SND_DirectWrite(played_size, sound_curfreq);
	if (currprefs.sound_adjust) {
	    unsigned int cur_clock, new_freq;

	    if (last_clock == 0)
		last_clock = uclock();
	    else {
		cur_clock = uclock();
		new_freq = (unsigned long long) sound_bytes * UCLOCKS_PER_SEC / (cur_clock-last_clock);
		interpol_freq(new_freq);
		last_clock = cur_clock;
	    }
	    sound_bytes = 0;
	}
	CurrentBuffer = !CurrentBuffer;
	direct_sndbufpt = direct_buffers[CurrentBuffer];
    } else if (played_size >= currprefs.sound_maxbsiz) {
	if (currprefs.sound_adjust)
	    interpol_freq(currprefs.sound_freq);
	while(IsPlaying);
	SND_DirectWrite(currprefs.sound_maxbsiz, sound_curfreq);
	CurrentBuffer = !CurrentBuffer;
	direct_sndbufpt = direct_buffers[CurrentBuffer];
	last_clock=0;
    }
}

void direct_mono_sample16_handler(void)
{
    uae_u32 data0 = audio_channel[0].current_sample;
    uae_u32 data1 = audio_channel[1].current_sample;
    uae_u32 data2 = audio_channel[2].current_sample;
    uae_u32 data3 = audio_channel[3].current_sample;
    DO_CHANNEL_1 (data0, 0);
    DO_CHANNEL_1 (data1, 1);
    DO_CHANNEL_1 (data2, 2);
    DO_CHANNEL_1 (data3, 3);
    data0 &= audio_channel[0].adk_mask;
    data1 &= audio_channel[1].adk_mask;
    data2 &= audio_channel[2].adk_mask;
    data3 &= audio_channel[3].adk_mask;
    data0 += data1;
    data0 += data2;
    data0 += data3;
    {
	uae_u32 data = SBASEVAL16(2) + data0;
	FINISH_DATA(16, 2);
	_farnspokew(direct_sndbufpt, data);
	direct_sndbufpt += 2;
    }

    direct_check_sound_buffers();

    eventtab[ev_sample].evtime = cycles + sample_evtime;
    eventtab[ev_sample].oldcycles = cycles;
}

void direct_mono_sample8_handler(void)
{
    uae_u32 data0 = audio_channel[0].current_sample;
    uae_u32 data1 = audio_channel[1].current_sample;
    uae_u32 data2 = audio_channel[2].current_sample;
    uae_u32 data3 = audio_channel[3].current_sample;
    DO_CHANNEL_1 (data0, 0);
    DO_CHANNEL_1 (data1, 1);
    DO_CHANNEL_1 (data2, 2);
    DO_CHANNEL_1 (data3, 3);
    data0 &= audio_channel[0].adk_mask;
    data1 &= audio_channel[1].adk_mask;
    data2 &= audio_channel[2].adk_mask;
    data3 &= audio_channel[3].adk_mask;
    data0 += data1;
    data0 += data2;
    data0 += data3;
    {
	uae_u32 data = SBASEVAL8(2) + data0;
	FINISH_DATA(8, 2);
	_farnspokeb(direct_sndbufpt++, data);
    }

    direct_check_sound_buffers();

    eventtab[ev_sample].evtime = cycles + sample_evtime;
    eventtab[ev_sample].oldcycles = cycles;
}

void direct_stereo_sample16_handler(void)
{
    uae_u32 data0 = audio_channel[0].current_sample;
    uae_u32 data1 = audio_channel[1].current_sample;
    uae_u32 data2 = audio_channel[2].current_sample;
    uae_u32 data3 = audio_channel[3].current_sample;
    DO_CHANNEL_1 (data0, 0);
    DO_CHANNEL_1 (data1, 1);
    DO_CHANNEL_1 (data2, 2);
    DO_CHANNEL_1 (data3, 3);

    data0 &= audio_channel[0].adk_mask;
    data1 &= audio_channel[1].adk_mask;
    data2 &= audio_channel[2].adk_mask;
    data3 &= audio_channel[3].adk_mask;

    data0 += data3;
    {
	uae_u32 data = SBASEVAL16(1) + data0;
	FINISH_DATA (16, 1);
	_farnspokew(direct_sndbufpt, data);
	direct_sndbufpt += 2;
    }

    data1 += data2;
    {
	uae_u32 data = SBASEVAL16(1) + data1;
	FINISH_DATA (16, 1);
	_farnspokew(direct_sndbufpt, data);
	direct_sndbufpt += 2;
    }

    direct_check_sound_buffers();

    eventtab[ev_sample].evtime = cycles + sample_evtime;
    eventtab[ev_sample].oldcycles = cycles;
}

void direct_stereo_sample8_handler(void)
{
    uae_u32 data0 = audio_channel[0].current_sample;
    uae_u32 data1 = audio_channel[1].current_sample;
    uae_u32 data2 = audio_channel[2].current_sample;
    uae_u32 data3 = audio_channel[3].current_sample;
    DO_CHANNEL_1 (data0, 0);
    DO_CHANNEL_1 (data1, 1);
    DO_CHANNEL_1 (data2, 2);
    DO_CHANNEL_1 (data3, 3);

    data0 &= audio_channel[0].adk_mask;
    data1 &= audio_channel[1].adk_mask;
    data2 &= audio_channel[2].adk_mask;
    data3 &= audio_channel[3].adk_mask;

    data0 += data3;
    {
	uae_u32 data = SBASEVAL8(1) + data0;
	FINISH_DATA (8, 1);
	_farnspokeb(direct_sndbufpt++, data);
    }
    data1 += data2;
    {
	uae_u32 data = SBASEVAL8(1) + data1;
	FINISH_DATA (8, 1);
	_farnspokeb(direct_sndbufpt++, data);
    }

    direct_check_sound_buffers();

    eventtab[ev_sample].evtime = cycles + sample_evtime;
    eventtab[ev_sample].oldcycles = cycles;
}

int init_sound (void)
{
    int tmp;
    int rate;
    int i;

    if (currprefs.sound_minbsiz > currprefs.sound_maxbsiz) {
	fprintf(stderr, "Minimum sound buffer size bigger then maximum, exchanging.\n");
	tmp = currprefs.sound_minbsiz;
	currprefs.sound_minbsiz = currprefs.sound_maxbsiz;
	currprefs.sound_maxbsiz = tmp;
    }

    dspbits = currprefs.sound_bits;
    rate = currprefs.sound_freq;
    sndbufsize = currprefs.sound_maxbsiz;

    if (SB_DetectInitSound(&dspbits, &rate, &sndbufsize, direct_buffers, &currprefs.stereo));
    else if (0/*OTHER_CARD_DETECT_ROUTINE*/);
    else
	return 0;

    currprefs.sound_freq = rate;
    currprefs.sound_minbsiz = (currprefs.sound_minbsiz>>2)<<2;
    currprefs.sound_maxbsiz = sndbufsize;

    sample_evtime = (long)MAXHPOS_PAL * MAXVPOS_PAL * VBLANK_HZ_PAL / rate;

    if (dspbits == 16) {
	init_sound_table16 ();
	if (currprefs.stereo)
	    eventtab[ev_sample].handler = direct_stereo_sample16_handler;
	else
	    eventtab[ev_sample].handler = direct_mono_sample16_handler;
    } else {
	init_sound_table8 ();
	if (currprefs.stereo)
	    eventtab[ev_sample].handler = direct_stereo_sample8_handler;
	else
	    eventtab[ev_sample].handler = direct_mono_sample8_handler;
    }
    printf ("Sound driver found and configured for %d bits at %d Hz, buffer is %d:%d bytes\n",
	    dspbits, rate, currprefs.sound_minbsiz, currprefs.sound_maxbsiz);
    sndbufpt = sndbuffer;
    direct_sndbufpt = direct_buffers[0];

    sound_curfreq = currprefs.sound_freq;
    for (i=0; i<INTERPOL_SIZE; i++)
	freq_buf[i] = sound_curfreq;
    buf_tot = sound_curfreq * INTERPOL_SIZE;

#ifdef FRAME_RATE_HACK
    vsynctime = vsynctime * 9 / 10;
#endif

    return 1;
}

int setup_sound (void)
{
    sound_available = 1;
    return 1;
}

void close_sound(void)
{
}