Genesis-Plus-GX/source/sound/blip.c

141 lines
4.3 KiB
C
Raw Normal View History

2011-07-14 00:49:52 +02:00
/* http://www.slack.net/~ant/ */
#include "blip.h"
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This
module 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 Lesser General Public License for more
details. You should have received a copy of the GNU Lesser General Public
License along with this module; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
enum { buf_extra = 2 }; /* extra samples to save past end */
enum { time_bits = 16 }; /* bits in fraction of fixed-point sample counts */
enum { time_unit = 1 << time_bits };
enum { phase_bits = 15 }; /* bits in fraction of deltas in buffer */
enum { phase_count = 1 << phase_bits };
enum { phase_shift = time_bits - phase_bits };
typedef int buf_t; /* type of element in delta buffer */
struct blip_buffer_t
{
int factor; /* clocks to samples conversion factor */
int offset; /* fractional position of clock 0 in delta buffer */
int amp; /* current output amplitude (sum of all deltas up to now) */
int size; /* size of delta buffer */
buf_t buf [65536]; /* delta buffer, only size elements actually allocated */
};
blip_buffer_t* blip_alloc( double clock_rate, double sample_rate, int size )
{
/* Allocate space for structure and delta buffer */
blip_buffer_t* s = (blip_buffer_t*) malloc(
offsetof (blip_buffer_t, buf) + (size + buf_extra) * sizeof (buf_t) );
if ( s != NULL )
{
/* Calculate output:input ratio and convert to fixed-point */
double ratio = sample_rate / clock_rate;
s->factor = (int) (ratio * time_unit + 0.5);
s->size = size;
blip_clear( s );
}
return s;
}
void blip_free( blip_buffer_t* s )
{
free( s );
}
void blip_clear( blip_buffer_t* s )
{
s->offset = 0;
s->amp = 0;
memset( s->buf, 0, (s->size + buf_extra) * sizeof (buf_t) );
}
void blip_add( blip_buffer_t* s, int clocks, int delta )
{
/* Convert to fixed-point time in terms of output samples */
int fixed_time = clocks * s->factor + s->offset;
/* Extract whole and fractional parts */
int index = fixed_time >> time_bits; /* whole */
int phase = fixed_time >> phase_shift & (phase_count - 1); /* fraction */
/* Split delta between first and second samples */
int second = delta * phase;
int first = delta * phase_count - second;
/* Add deltas to buffer */
s->buf [index ] += first;
s->buf [index+1] += second;
}
int blip_clocks_needed( const blip_buffer_t* s, int samples )
{
2011-07-14 00:49:52 +02:00
/* Fixed-point number of samples needed in addition to those in buffer */
int fixed_needed = samples * time_unit - s->offset;
2011-07-14 00:49:52 +02:00
/* If more are needed, convert to clocks and round up */
return (fixed_needed <= 0) ? 0 : (fixed_needed - 1) / s->factor + 1;
}
void blip_end_frame( blip_buffer_t* s, int clocks )
{
s->offset += clocks * s->factor;
}
int blip_samples_avail( const blip_buffer_t* s )
{
return s->offset >> time_bits;
}
[Core/SCD] ---------- * added Mega CD / Sega CD hardware emulation (incl. Sub 68K, CDD, CDC, PCM, GFX rotation/scaling, etc) * added .ISO & .BIN CD image file support * added 512K backup cartridge RAM support * added savestate support for CD games NOTES: ~~~~~~ * to play CD games, original BIOS ROM files are required in /genplus/bios/ directory: unzip & rename them to bios_CD_U.bin, bios_CD_E.bin, bios_CD_J.bin * CD audio tracks (CD-DA) are not supported (yet) [Core/CPU] ---------- * modified 68k core for Mega CD / Sega CD support [Core/VDP] --------------- * improved DMA accuracy * added support for 8-bit VRAM writes with undocumented code value (verified on real hardware by Nemesis) [Gamecube/Wii] --------------- * modified Master System & Game Gear "BIOS" support (files should be named bios_U.sms, bios_J.sms, bios_E.sms & bios.gg and copied to /genplus/bios directory). * replaced "Hard Reset" button by a Soft Reset for systems having a Reset button (Mega Drive / Genesis & Master System) * State & SRAM files are now only compressed when saving to Gamecube Memory Cards * various fixes & cleanup. [Core/SCD] ---------- * added Mega CD / Sega CD hardware emulation (incl. Sub 68K, CDD, CDC, PCM, GFX rotation/scaling, etc) * added .ISO & .BIN CD image file support * added 512K backup cartridge RAM support * added savestate support for CD games NOTES: ~~~~~~ * to play CD games, original BIOS ROM files are required in /genplus/bios/ directory: unzip & rename them to bios_CD_U.bin, bios_CD_E.bin, bios_CD_J.bin * CD audio tracks (CD-DA) are not supported (yet) [Core/CPU] ---------- * modified 68k core for Mega CD / Sega CD support [Core/VDP] --------------- * improved DMA accuracy * added support for 8-bit VRAM writes with undocumented code value (verified on real hardware by Nemesis) [Gamecube/Wii] --------------- * modified Master System & Game Gear "BIOS" support (files should be named bios_U.sms, bios_J.sms, bios_E.sms & bios.gg and copied to /genplus/bios directory). * replaced "Hard Reset" button by a Soft Reset for systems having a Reset button (Mega Drive / Genesis & Master System) * State & SRAM files are now only compressed when saving to Gamecube Memory Cards * various fixes & cleanup.
2012-07-05 21:22:12 +02:00
int blip_read_samples( blip_buffer_t* s, short out[], int stereo)
2011-07-14 00:49:52 +02:00
{
int count = s->offset >> time_bits;
2011-07-14 00:49:52 +02:00
if ( count )
{
/* Sum deltas and write out */
int i, sample;
2011-07-14 00:49:52 +02:00
for ( i = 0; i < count; ++i )
{
2011-07-14 00:49:52 +02:00
/* Apply slight high-pass filter */
s->amp -= s->amp >> 9;
/* Add next delta */
s->amp += s->buf [i];
/* Calculate output sample */
sample = s->amp >> phase_bits;
/* Keep within 16-bit sample range */
if ( sample < -32768 ) sample = -32768;
if ( sample > +32767 ) sample = +32767;
[Core/SCD] ---------- * added Mega CD / Sega CD hardware emulation (incl. Sub 68K, CDD, CDC, PCM, GFX rotation/scaling, etc) * added .ISO & .BIN CD image file support * added 512K backup cartridge RAM support * added savestate support for CD games NOTES: ~~~~~~ * to play CD games, original BIOS ROM files are required in /genplus/bios/ directory: unzip & rename them to bios_CD_U.bin, bios_CD_E.bin, bios_CD_J.bin * CD audio tracks (CD-DA) are not supported (yet) [Core/CPU] ---------- * modified 68k core for Mega CD / Sega CD support [Core/VDP] --------------- * improved DMA accuracy * added support for 8-bit VRAM writes with undocumented code value (verified on real hardware by Nemesis) [Gamecube/Wii] --------------- * modified Master System & Game Gear "BIOS" support (files should be named bios_U.sms, bios_J.sms, bios_E.sms & bios.gg and copied to /genplus/bios directory). * replaced "Hard Reset" button by a Soft Reset for systems having a Reset button (Mega Drive / Genesis & Master System) * State & SRAM files are now only compressed when saving to Gamecube Memory Cards * various fixes & cleanup. [Core/SCD] ---------- * added Mega CD / Sega CD hardware emulation (incl. Sub 68K, CDD, CDC, PCM, GFX rotation/scaling, etc) * added .ISO & .BIN CD image file support * added 512K backup cartridge RAM support * added savestate support for CD games NOTES: ~~~~~~ * to play CD games, original BIOS ROM files are required in /genplus/bios/ directory: unzip & rename them to bios_CD_U.bin, bios_CD_E.bin, bios_CD_J.bin * CD audio tracks (CD-DA) are not supported (yet) [Core/CPU] ---------- * modified 68k core for Mega CD / Sega CD support [Core/VDP] --------------- * improved DMA accuracy * added support for 8-bit VRAM writes with undocumented code value (verified on real hardware by Nemesis) [Gamecube/Wii] --------------- * modified Master System & Game Gear "BIOS" support (files should be named bios_U.sms, bios_J.sms, bios_E.sms & bios.gg and copied to /genplus/bios directory). * replaced "Hard Reset" button by a Soft Reset for systems having a Reset button (Mega Drive / Genesis & Master System) * State & SRAM files are now only compressed when saving to Gamecube Memory Cards * various fixes & cleanup.
2012-07-05 21:22:12 +02:00
out [i << stereo] = sample;
2011-07-14 00:49:52 +02:00
}
/* Copy remaining samples to beginning of buffer and clear the rest */
memmove( s->buf, &s->buf [count], buf_extra * sizeof (buf_t) );
memset( &s->buf [buf_extra], 0, count * sizeof (buf_t) );
2011-07-14 00:49:52 +02:00
/* Remove samples */
s->offset -= count * time_unit;
2011-07-14 00:49:52 +02:00
}
return count;
2011-07-14 00:49:52 +02:00
}