From 1e5e73e9bf9cf32abdb42b1d80fdf772b69939db Mon Sep 17 00:00:00 2001 From: Michael Hahn Date: Sat, 16 Jan 2021 19:21:24 -0500 Subject: [PATCH 1/3] fix buzzing sound in audio --- atari800/src/mzpokeysnd.c | 41 ++++++++++++++++++++++++--------------- atari800/src/pokeysnd.c | 18 ++++++++++++++++- atari800/src/pokeysnd.h | 1 + 3 files changed, 43 insertions(+), 17 deletions(-) diff --git a/atari800/src/mzpokeysnd.c b/atari800/src/mzpokeysnd.c index 3805853..0be8d72 100644 --- a/atari800/src/mzpokeysnd.c +++ b/atari800/src/mzpokeysnd.c @@ -264,6 +264,11 @@ typedef struct stPokeyState } PokeyState; +static struct { + double s16; + double s8; +} volume; + PokeyState pokey_states[NPOKEYS]; /* Forward declarations for ResetPokeyState */ @@ -1421,6 +1426,10 @@ int MZPOKEYSND_Init(ULONG freq17, int playback_freq, UBYTE num_pokeys, #ifdef SYNCHRONIZED_SOUND init_syncsound(); #endif + + volume.s8 = POKEYSND_volume * 0xff / 256.0; + volume.s16 = POKEYSND_volume * 0xffff / 256.0; + return 0; /* OK */ } @@ -2341,16 +2350,16 @@ static void mzpokeysnd_process_8(void* sndbuffer, int sndn) #endif #ifdef VOL_ONLY_SOUND - buffer[0] = (UBYTE)floor((generate_sample(pokey_states) + POKEYSND_sampout - MAX_SAMPLE / 2.0) - * (255.0 / MAX_SAMPLE / 4 * M_PI * 0.95) + 128 + 0.5 + 0.5 * rand() / RAND_MAX - 0.25); + buffer[0] = (UBYTE)floor((generate_sample(pokey_states) + POKEYSND_sampout) + * (255.0 / 2 / MAX_SAMPLE / 4 * M_PI * 0.95) + 128 + 0.5 + 0.5 * rand() / RAND_MAX - 0.25); #else - buffer[0] = (UBYTE)floor((generate_sample(pokey_states) - MAX_SAMPLE / 2.0) - * (255.0 / MAX_SAMPLE / 4 * M_PI * 0.95) + 128 + 0.5 + 0.5 * rand() / RAND_MAX - 0.25); + buffer[0] = (UBYTE)floor(generate_sample(pokey_states) + * (255.0 / 2 / MAX_SAMPLE / 4 * M_PI * 0.95) + 128 + 0.5 + 0.5 * rand() / RAND_MAX - 0.25); #endif for(i=1; i 100) + vol = 100; + if (vol < 0) + vol = 0; + + POKEYSND_volume = vol * 0x100 / 100; +} + static void pokeysnd_process_16(void *sndbuffer, int sndn) { UWORD *buffer = (UWORD *) sndbuffer; @@ -1254,7 +1266,11 @@ static void pokeysnd_process_16(void *sndbuffer, int sndn) pokeysnd_process_8(buffer, sndn); for (i = sndn - 1; i >= 0; i--) { - int smp = ((int) (((UBYTE *) buffer)[i]) - 0x80) * 0x100; +#ifndef POKEYSND_SIGNED_SAMPLES + int smp = ((int) (((UBYTE *) buffer)[i]) - 0x80) * POKEYSND_volume; +#else + int smp = ((int) ((SBYTE *) buffer)[i]) * POKEYSND_volume; +#endif if (smp > 32767) smp = 32767; diff --git a/atari800/src/pokeysnd.h b/atari800/src/pokeysnd.h index 8cf15a8..6267f18 100644 --- a/atari800/src/pokeysnd.h +++ b/atari800/src/pokeysnd.h @@ -84,6 +84,7 @@ extern "C" { extern SLONG POKEYSND_playback_freq; extern UBYTE POKEYSND_num_pokeys; extern int POKEYSND_snd_flags; +extern int POKEYSND_volume; extern int POKEYSND_enable_new_pokey; extern int POKEYSND_stereo_enabled; From 3d38cd1c79b87c21b8471fa7f74c493dcf39fecb Mon Sep 17 00:00:00 2001 From: Michael Hahn Date: Sat, 16 Jan 2021 19:34:28 -0500 Subject: [PATCH 2/3] fix buzzing sound in audio --- atari800/src/votraxsnd.c | 4 +- atari800/src/votraxsnd.h | 283 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 274 insertions(+), 13 deletions(-) diff --git a/atari800/src/votraxsnd.c b/atari800/src/votraxsnd.c index d70560a..6edf36e 100644 --- a/atari800/src/votraxsnd.c +++ b/atari800/src/votraxsnd.c @@ -267,8 +267,8 @@ void VOTRAXSND_Process(void *sndbuffer, int sndn) while (sndn > 0) { int amount = ((sndn > VTRX_BLOCK_SIZE) ? VTRX_BLOCK_SIZE : sndn); votrax_process(votrax_buffer, amount, temp_votrax_buffer); - if (bit16) mix((SWORD *)sndbuffer, votrax_buffer, amount, 128/4); - else mix8((UBYTE *)sndbuffer, votrax_buffer, amount, 128/4); + if (bit16) mix((SWORD *)sndbuffer, votrax_buffer, amount, POKEYSND_volume >> 3); + else mix8((UBYTE *)sndbuffer, votrax_buffer, amount, POKEYSND_volume >> 3); sndbuffer = (char *) sndbuffer + VTRX_BLOCK_SIZE*(bit16 ? 2 : 1)*((num_pokeys == 2) ? 2: 1); sndn -= VTRX_BLOCK_SIZE; } diff --git a/atari800/src/votraxsnd.h b/atari800/src/votraxsnd.h index 0b26675..6edf36e 100644 --- a/atari800/src/votraxsnd.h +++ b/atari800/src/votraxsnd.h @@ -1,15 +1,276 @@ -#ifndef VOTRAXSND_H_ -#define VOTRAXSND_H_ +/* + * votraxsnd.c - Atari800 interface to votrax.c + * + * Copyright (C) 2007-2010 Atari800 development team (see DOC/CREDITS) + * + * This file is part of the Atari800 emulator project which emulates + * the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers. + * + * Atari800 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. + * + * Atari800 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 Atari800; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#include +#include #include "atari.h" -#include "votrax.h" +#include "util.h" +#include "votraxsnd.h" +#ifdef PBI_XLD +#include "pbi_xld.h" +#endif +#ifdef VOICEBOX +#include "voicebox.h" +#endif +#include "pokey.h" +#include "log.h" -void VOTRAXSND_PutByte(UBYTE byte); -void VOTRAXSND_Init(int playback_freq, int n_pokeys, int b16); -void VOTRAXSND_Frame(void); -void VOTRAXSND_Process(void *sndbuffer, int sndn); -extern int VOTRAXSND_busy; -void VOTRAXSND_Reinit(void); -void VOTRAXSND_ModifyRatio(double factor); +/* Votrax */ + +#define VTRX_RATE 24500 + +static double ratio; +static int bit16; +#define VTRX_BLOCK_SIZE 1024 +SWORD *temp_votrax_buffer = NULL; +SWORD *votrax_buffer = NULL; +int VOTRAXSND_busy = FALSE; +static int votrax_sync_samples; +static int dsprate; +static int num_pokeys; +static int samples_per_frame; +/*if SYNCHRONIZED_SOUND is not used and the sound generation runs in a + * separate thread, then these variables are accessed in two different + * threads: */ +static int votrax_written = FALSE; +static int votrax_written_byte = 0x3f; + +void VOTRAXSND_PutByte(UBYTE byte) +{ + /* put byte to voice box */ + votrax_sync_samples = (int)((1.0/ratio)*(double)Votrax_Samples((votrax_written_byte&0x3f), (byte&0x3f), votrax_sync_samples)); + votrax_written = TRUE; + votrax_written_byte = byte; + if (!VOTRAXSND_busy) { + VOTRAXSND_busy = TRUE; +#ifdef PBI_XLD + if (PBI_XLD_enabled) { + PBI_XLD_votrax_busy_callback(TRUE); /* idle -> busy */ + } +#endif + } +} + +static void VOTRAXSND_busy_callback_async(int busy_status) +{ + return; + /* do nothing */ +} + +static int votraxsnd_enabled(void) +{ + if ( +#ifdef VOICEBOX + !VOICEBOX_enabled && +#endif +#ifdef PBI_XLD + !PBI_XLD_v_enabled && + +#endif + 1) return FALSE; + else return TRUE; +} + +/* called from POKEYSND_Init */ +void VOTRAXSND_Init(int playback_freq, int n_pokeys, int b16) +{ + static struct Votrax_interface vi; + int temp_votrax_buffer_size; + bit16 = b16; + dsprate = playback_freq; + num_pokeys = n_pokeys; + if (!votraxsnd_enabled()) return; + if (num_pokeys != 1 && num_pokeys != 2) { + Log_print("VOTRAXSND_Init: cannot handle num_pokeys=%d", num_pokeys); +#ifdef PBI_XLD + PBI_XLD_v_enabled = FALSE; +#endif +#ifdef VOICEBOX + VOICEBOX_enabled = FALSE; +#endif + return; + } + vi.num = 1; + vi.BusyCallback = VOTRAXSND_busy_callback_async; + Votrax_Stop(); + Votrax_Start((void *)&vi); + samples_per_frame = dsprate/(Atari800_tv_mode == Atari800_TV_PAL ? 50 : 60); + ratio = (double)VTRX_RATE/(double)dsprate; +#ifdef VOICEBOX + temp_votrax_buffer_size = (int)(VTRX_BLOCK_SIZE*ratio*(VOICEBOX_BASEAUDF+1) + 10); /* +10 .. little extra? */ +#else + temp_votrax_buffer_size = (int)(VTRX_BLOCK_SIZE*ratio + 10); /* +10 .. little extra? */ +#endif + free(temp_votrax_buffer); + temp_votrax_buffer = (SWORD *)Util_malloc(temp_votrax_buffer_size*sizeof(SWORD)); + free(votrax_buffer); + votrax_buffer = (SWORD *)Util_malloc(VTRX_BLOCK_SIZE*sizeof(SWORD)); + + VOTRAXSND_busy = FALSE; + votrax_sync_samples = 0; +} + +void VOTRAXSND_Reinit(void) +{ + if (dsprate) VOTRAXSND_Init(dsprate, num_pokeys, bit16); +} + +/* process votrax and interpolate samples */ +static void votrax_process(SWORD *v_buffer, int len, SWORD *temp_v_buffer) +{ + static SWORD last_sample; + static SWORD last_sample2; + static double startpos; + static int have; + int max_left_sample_index = (int)(startpos + (double)(len - 1)*ratio); + int pos = 0; + double fraction = 0; + int i; + int floor_next_pos; + + if (have == 2) { + temp_v_buffer[0] = last_sample; + temp_v_buffer[1] = last_sample2; + Votrax_Update(0, temp_v_buffer + 2, (max_left_sample_index + 1 + 1) - 2); + } + else if (have == 1) { + temp_v_buffer[0] = last_sample; + Votrax_Update(0, temp_v_buffer + 1, (max_left_sample_index + 1 + 1) - 1); + } + else if (have == 0) { + Votrax_Update(0, temp_v_buffer, max_left_sample_index + 1 + 1); + } + else if (have < 0) { + Votrax_Update(0, temp_v_buffer, -have); + Votrax_Update(0, temp_v_buffer, max_left_sample_index + 1 + 1); + } + + for (i = 0; i < len; i++) { + SWORD left_sample; + SWORD right_sample; + SWORD interp_sample; + pos = (int)(startpos + (double)i*ratio); + fraction = startpos + (double)i*ratio - (double)pos; + left_sample = temp_v_buffer[pos]; + right_sample = temp_v_buffer[pos+1]; + interp_sample = (int)(left_sample + fraction*(double)(right_sample-left_sample)); + v_buffer[i] = interp_sample; + } + floor_next_pos = (int)(startpos + (double)len*ratio); + startpos = (startpos + (double)len*ratio) - (double)floor_next_pos; + if (floor_next_pos == max_left_sample_index) + { + have = 2; + last_sample = temp_v_buffer[floor_next_pos]; + last_sample2 = temp_v_buffer[floor_next_pos+1]; + } + else if (floor_next_pos == max_left_sample_index + 1) { + have = 1; + last_sample = temp_v_buffer[floor_next_pos]; + } + else { + have = (floor_next_pos - (max_left_sample_index + 2)); + } +} + +/* 16 bit mixing */ +static void mix(SWORD *dst, SWORD *src, int sndn, int volume) +{ + SWORD s1, s2; + int val; + + while (sndn--) { + s1 = *src; + s1 = s1*volume/128; + s2 = *dst; + src++; + val = s1 + s2; + if (val > 32767) val = 32767; + if (val < -32768) val = -32768; + *dst++ = val; + if (num_pokeys == 2) { + dst++; + } + } +} + +/* 8 bit mixing */ +static void mix8(UBYTE *dst, SWORD *src, int sndn, int volume) +{ + SWORD s1, s2; + int val; + + while (sndn--) { + s1 = *src; + s1 = s1*volume/128; + s2 = ((int)(*dst) - 0x80)*256; + src++; + val = s1 + s2; + if (val > 32767) val = 32767; + if (val < -32768) val = -32768; + *dst++ = (UBYTE)((val/256) + 0x80); + if (num_pokeys == 2) { + dst++; + } + } +} + +void VOTRAXSND_Frame(void) +{ + if (!votraxsnd_enabled()) return; +#ifdef VOICEBOX + if (VOICEBOX_enabled && VOICEBOX_ii) { + double factor = (VOICEBOX_BASEAUDF+1.0)/(POKEY_AUDF[3]+1.0); + ratio = (double)VTRX_RATE/(double)dsprate * factor; + samples_per_frame = ((double)dsprate/(double)(Atari800_tv_mode == Atari800_TV_PAL ? 50 : 60)) / factor; + } +#endif + votrax_sync_samples -= samples_per_frame; + if (votrax_sync_samples <= 0 ) { + votrax_sync_samples = 0; + VOTRAXSND_busy = FALSE; +#ifdef PBI_XLD + PBI_XLD_votrax_busy_callback(FALSE); /* busy -> idle */ +#endif + } +} + +void VOTRAXSND_Process(void *sndbuffer, int sndn) +{ + if (!votraxsnd_enabled()) return; + + if(votrax_written) { + votrax_written = FALSE; + Votrax_PutByte(votrax_written_byte); + } + sndn /= num_pokeys; + while (sndn > 0) { + int amount = ((sndn > VTRX_BLOCK_SIZE) ? VTRX_BLOCK_SIZE : sndn); + votrax_process(votrax_buffer, amount, temp_votrax_buffer); + if (bit16) mix((SWORD *)sndbuffer, votrax_buffer, amount, POKEYSND_volume >> 3); + else mix8((UBYTE *)sndbuffer, votrax_buffer, amount, POKEYSND_volume >> 3); + sndbuffer = (char *) sndbuffer + VTRX_BLOCK_SIZE*(bit16 ? 2 : 1)*((num_pokeys == 2) ? 2: 1); + sndn -= VTRX_BLOCK_SIZE; + } +} -#endif /* VOTRAXSND_H_ */ From e8ae39f00c397a21056dfd623036842118b33d44 Mon Sep 17 00:00:00 2001 From: Michael Hahn Date: Sat, 16 Jan 2021 19:45:24 -0500 Subject: [PATCH 3/3] fix buzzing sound in audio --- atari800/src/votraxsnd.h | 283 ++------------------------------------- 1 file changed, 11 insertions(+), 272 deletions(-) diff --git a/atari800/src/votraxsnd.h b/atari800/src/votraxsnd.h index 6edf36e..0b26675 100644 --- a/atari800/src/votraxsnd.h +++ b/atari800/src/votraxsnd.h @@ -1,276 +1,15 @@ -/* - * votraxsnd.c - Atari800 interface to votrax.c - * - * Copyright (C) 2007-2010 Atari800 development team (see DOC/CREDITS) - * - * This file is part of the Atari800 emulator project which emulates - * the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers. - * - * Atari800 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. - * - * Atari800 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 Atari800; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ +#ifndef VOTRAXSND_H_ +#define VOTRAXSND_H_ -#include -#include #include "atari.h" -#include "util.h" -#include "votraxsnd.h" -#ifdef PBI_XLD -#include "pbi_xld.h" -#endif -#ifdef VOICEBOX -#include "voicebox.h" -#endif -#include "pokey.h" -#include "log.h" +#include "votrax.h" -/* Votrax */ - -#define VTRX_RATE 24500 - -static double ratio; -static int bit16; -#define VTRX_BLOCK_SIZE 1024 -SWORD *temp_votrax_buffer = NULL; -SWORD *votrax_buffer = NULL; -int VOTRAXSND_busy = FALSE; -static int votrax_sync_samples; -static int dsprate; -static int num_pokeys; -static int samples_per_frame; -/*if SYNCHRONIZED_SOUND is not used and the sound generation runs in a - * separate thread, then these variables are accessed in two different - * threads: */ -static int votrax_written = FALSE; -static int votrax_written_byte = 0x3f; - -void VOTRAXSND_PutByte(UBYTE byte) -{ - /* put byte to voice box */ - votrax_sync_samples = (int)((1.0/ratio)*(double)Votrax_Samples((votrax_written_byte&0x3f), (byte&0x3f), votrax_sync_samples)); - votrax_written = TRUE; - votrax_written_byte = byte; - if (!VOTRAXSND_busy) { - VOTRAXSND_busy = TRUE; -#ifdef PBI_XLD - if (PBI_XLD_enabled) { - PBI_XLD_votrax_busy_callback(TRUE); /* idle -> busy */ - } -#endif - } -} - -static void VOTRAXSND_busy_callback_async(int busy_status) -{ - return; - /* do nothing */ -} - -static int votraxsnd_enabled(void) -{ - if ( -#ifdef VOICEBOX - !VOICEBOX_enabled && -#endif -#ifdef PBI_XLD - !PBI_XLD_v_enabled && - -#endif - 1) return FALSE; - else return TRUE; -} - -/* called from POKEYSND_Init */ -void VOTRAXSND_Init(int playback_freq, int n_pokeys, int b16) -{ - static struct Votrax_interface vi; - int temp_votrax_buffer_size; - bit16 = b16; - dsprate = playback_freq; - num_pokeys = n_pokeys; - if (!votraxsnd_enabled()) return; - if (num_pokeys != 1 && num_pokeys != 2) { - Log_print("VOTRAXSND_Init: cannot handle num_pokeys=%d", num_pokeys); -#ifdef PBI_XLD - PBI_XLD_v_enabled = FALSE; -#endif -#ifdef VOICEBOX - VOICEBOX_enabled = FALSE; -#endif - return; - } - vi.num = 1; - vi.BusyCallback = VOTRAXSND_busy_callback_async; - Votrax_Stop(); - Votrax_Start((void *)&vi); - samples_per_frame = dsprate/(Atari800_tv_mode == Atari800_TV_PAL ? 50 : 60); - ratio = (double)VTRX_RATE/(double)dsprate; -#ifdef VOICEBOX - temp_votrax_buffer_size = (int)(VTRX_BLOCK_SIZE*ratio*(VOICEBOX_BASEAUDF+1) + 10); /* +10 .. little extra? */ -#else - temp_votrax_buffer_size = (int)(VTRX_BLOCK_SIZE*ratio + 10); /* +10 .. little extra? */ -#endif - free(temp_votrax_buffer); - temp_votrax_buffer = (SWORD *)Util_malloc(temp_votrax_buffer_size*sizeof(SWORD)); - free(votrax_buffer); - votrax_buffer = (SWORD *)Util_malloc(VTRX_BLOCK_SIZE*sizeof(SWORD)); - - VOTRAXSND_busy = FALSE; - votrax_sync_samples = 0; -} - -void VOTRAXSND_Reinit(void) -{ - if (dsprate) VOTRAXSND_Init(dsprate, num_pokeys, bit16); -} - -/* process votrax and interpolate samples */ -static void votrax_process(SWORD *v_buffer, int len, SWORD *temp_v_buffer) -{ - static SWORD last_sample; - static SWORD last_sample2; - static double startpos; - static int have; - int max_left_sample_index = (int)(startpos + (double)(len - 1)*ratio); - int pos = 0; - double fraction = 0; - int i; - int floor_next_pos; - - if (have == 2) { - temp_v_buffer[0] = last_sample; - temp_v_buffer[1] = last_sample2; - Votrax_Update(0, temp_v_buffer + 2, (max_left_sample_index + 1 + 1) - 2); - } - else if (have == 1) { - temp_v_buffer[0] = last_sample; - Votrax_Update(0, temp_v_buffer + 1, (max_left_sample_index + 1 + 1) - 1); - } - else if (have == 0) { - Votrax_Update(0, temp_v_buffer, max_left_sample_index + 1 + 1); - } - else if (have < 0) { - Votrax_Update(0, temp_v_buffer, -have); - Votrax_Update(0, temp_v_buffer, max_left_sample_index + 1 + 1); - } - - for (i = 0; i < len; i++) { - SWORD left_sample; - SWORD right_sample; - SWORD interp_sample; - pos = (int)(startpos + (double)i*ratio); - fraction = startpos + (double)i*ratio - (double)pos; - left_sample = temp_v_buffer[pos]; - right_sample = temp_v_buffer[pos+1]; - interp_sample = (int)(left_sample + fraction*(double)(right_sample-left_sample)); - v_buffer[i] = interp_sample; - } - floor_next_pos = (int)(startpos + (double)len*ratio); - startpos = (startpos + (double)len*ratio) - (double)floor_next_pos; - if (floor_next_pos == max_left_sample_index) - { - have = 2; - last_sample = temp_v_buffer[floor_next_pos]; - last_sample2 = temp_v_buffer[floor_next_pos+1]; - } - else if (floor_next_pos == max_left_sample_index + 1) { - have = 1; - last_sample = temp_v_buffer[floor_next_pos]; - } - else { - have = (floor_next_pos - (max_left_sample_index + 2)); - } -} - -/* 16 bit mixing */ -static void mix(SWORD *dst, SWORD *src, int sndn, int volume) -{ - SWORD s1, s2; - int val; - - while (sndn--) { - s1 = *src; - s1 = s1*volume/128; - s2 = *dst; - src++; - val = s1 + s2; - if (val > 32767) val = 32767; - if (val < -32768) val = -32768; - *dst++ = val; - if (num_pokeys == 2) { - dst++; - } - } -} - -/* 8 bit mixing */ -static void mix8(UBYTE *dst, SWORD *src, int sndn, int volume) -{ - SWORD s1, s2; - int val; - - while (sndn--) { - s1 = *src; - s1 = s1*volume/128; - s2 = ((int)(*dst) - 0x80)*256; - src++; - val = s1 + s2; - if (val > 32767) val = 32767; - if (val < -32768) val = -32768; - *dst++ = (UBYTE)((val/256) + 0x80); - if (num_pokeys == 2) { - dst++; - } - } -} - -void VOTRAXSND_Frame(void) -{ - if (!votraxsnd_enabled()) return; -#ifdef VOICEBOX - if (VOICEBOX_enabled && VOICEBOX_ii) { - double factor = (VOICEBOX_BASEAUDF+1.0)/(POKEY_AUDF[3]+1.0); - ratio = (double)VTRX_RATE/(double)dsprate * factor; - samples_per_frame = ((double)dsprate/(double)(Atari800_tv_mode == Atari800_TV_PAL ? 50 : 60)) / factor; - } -#endif - votrax_sync_samples -= samples_per_frame; - if (votrax_sync_samples <= 0 ) { - votrax_sync_samples = 0; - VOTRAXSND_busy = FALSE; -#ifdef PBI_XLD - PBI_XLD_votrax_busy_callback(FALSE); /* busy -> idle */ -#endif - } -} - -void VOTRAXSND_Process(void *sndbuffer, int sndn) -{ - if (!votraxsnd_enabled()) return; - - if(votrax_written) { - votrax_written = FALSE; - Votrax_PutByte(votrax_written_byte); - } - sndn /= num_pokeys; - while (sndn > 0) { - int amount = ((sndn > VTRX_BLOCK_SIZE) ? VTRX_BLOCK_SIZE : sndn); - votrax_process(votrax_buffer, amount, temp_votrax_buffer); - if (bit16) mix((SWORD *)sndbuffer, votrax_buffer, amount, POKEYSND_volume >> 3); - else mix8((UBYTE *)sndbuffer, votrax_buffer, amount, POKEYSND_volume >> 3); - sndbuffer = (char *) sndbuffer + VTRX_BLOCK_SIZE*(bit16 ? 2 : 1)*((num_pokeys == 2) ? 2: 1); - sndn -= VTRX_BLOCK_SIZE; - } -} +void VOTRAXSND_PutByte(UBYTE byte); +void VOTRAXSND_Init(int playback_freq, int n_pokeys, int b16); +void VOTRAXSND_Frame(void); +void VOTRAXSND_Process(void *sndbuffer, int sndn); +extern int VOTRAXSND_busy; +void VOTRAXSND_Reinit(void); +void VOTRAXSND_ModifyRatio(double factor); +#endif /* VOTRAXSND_H_ */