more sound/throttle cleanups and improvements

This commit is contained in:
zeromus 2006-08-25 07:05:55 +00:00
parent 11e0d7ebcf
commit dd126e30e5
6 changed files with 174 additions and 220 deletions

View File

@ -5,8 +5,8 @@
#include "common.h"
extern PALETTEENTRY color_palette[256];
extern WAVEFORMATEX wf;
extern int soundo;
//extern WAVEFORMATEX wf;
//extern int soundo;
#define VIDEO_STREAM 0
#define AUDIO_STREAM 1
@ -306,7 +306,6 @@ int FCEUI_AviBegin(const char* fname)
struct VideoSystemInfo vsi;
BITMAPINFOHEADER bi;
const WAVEFORMATEX* wfex = NULL;
int is_pal;
is_pal=FCEUI_GetCurrentVidSystem(&vsi.start_scanline, &vsi.end_scanline);
@ -321,12 +320,20 @@ int FCEUI_AviBegin(const char* fname)
bi.biHeight = vsi.end_scanline-vsi.start_scanline;
bi.biSizeImage = 3 * bi.biWidth * bi.biHeight;
if(soundo)
wfex = &wf;
//mbg 8/25/06 -- hardcoded stuff for now
WAVEFORMATEX wf;
wf.cbSize = sizeof(WAVEFORMATEX);
wf.nAvgBytesPerSec = 44100 * 2;
wf.nBlockAlign = 2;
wf.nChannels = 1;
wf.nSamplesPerSec = 44100;
wf.wBitsPerSample = 16;
wf.wFormatTag = WAVE_FORMAT_PCM;
saved_avi_ext[0]='\0';
if(!avi_open(fname, &bi, wfex, &vsi))
if(!avi_open(fname, &bi, &wf, &vsi))
{
saved_avi_fname[0]='\0';
return 0;

View File

@ -305,8 +305,6 @@ void DoPriority(void)
static int changerecursive=0;
#include "throttle.cpp"
#include "sound.cpp"
#include "video.cpp"
#include "window.cpp"

View File

@ -1,7 +1,7 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2002 Xodnizel
* Copyright (C) 2002 Xodnizel and zeromus
*
* 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
@ -20,10 +20,10 @@
#include <list>
static int mute=0; /* TODO: add to config? add to GUI. */
int silencer=0;
/// controls whether playback is muted
static bool mute = false;
/// indicates whether we've been coerced into outputting 8bit audio
static int bits;
#undef min
#undef max
@ -31,6 +31,8 @@ int silencer=0;
OAKRA_Module_OutputDS *dsout;
//manages a set of small buffers which together work as one large buffer capable of resizing itsself and
//shrinking when a larger buffer is no longer necessary
class BufferSet {
public:
@ -95,14 +97,6 @@ public:
return *(short*)((char*)liveBuffers[buffer]->data+ofs);
}
template <class ST>
ST getElementAtIndex(int addr) {
addr *= sizeof(ST); //shorts are 2bytes
int buffer = (addr+offset)>>BufferSizeBits;
int ofs = (addr+offset) & BufferSizeBitmask;
return *(ST*)((char*)liveBuffers[buffer]->data+ofs);
}
//dequeues the specified number of bytes
void dequeue(int length) {
offset += length;
@ -121,14 +115,14 @@ public:
//not all the bytes you asked for will be locked (no more than one buffer-full)
//try again if you didnt get enough.
//returns the number of bytes locked.
int lock(int length, void **ptr) {
int remain = BufferSize-offset;
*ptr = (char*)liveBuffers[0]->data + offset;
if(length<remain)
return length;
else
return remain;
}
//int lock(int length, void **ptr) {
// int remain = BufferSize-offset;
// *ptr = (char*)liveBuffers[0]->data + offset;
// if(length<remain)
// return length;
// else
// return remain;
//}
void enqueue(int length, void *data) {
int todo = length;
@ -155,58 +149,18 @@ public:
}
};
class PlayerBase : public OAKRA_Module {
public:
BufferSet buffers;
int scale;
PlayerBase() {
scale = 256;
}
void receive(int bytes, void *buf) {
dsout->lock();
buffers.enqueue(bytes,buf);
buffers.decay(60);
dsout->unlock();
}
virtual int getSamplesInBuffer() = 0;
void throttle() {
//wait for the buffer to be satisfactorily low before continuing
for(;;) {
dsout->lock();
int remain = getSamplesInBuffer();
dsout->unlock();
if(remain<44100/60) break;
//if(remain<44100*scale/256/60) break; ??
Sleep(1);
}
}
void setScale(int scale) {
dsout->lock();
this->scale = scale;
dsout->unlock();
}
};
template <class ST,int SHIFT,int ZERO>
class Player : public PlayerBase {
class Player : public OAKRA_Module {
public:
int cursor;
int getSamplesInBuffer() { return buffers.length>>SHIFT; }
BufferSet buffers;
int scale;
//not interpolating! someday it will!
int generate(int samples, void *buf) {
int incr = 256;
int bufferSamples = buffers.length>>SHIFT;
int bufferSamples = buffers.length>>1;
//if we're we're too far behind, playback faster
if(bufferSamples > 44100*3/60) {
@ -222,28 +176,80 @@ public:
int destSamplesCanGenerate = (bufferSamples<<8) / incr;
int todo = std::min(destSamplesCanGenerate,samples);
ST *sbuf = (ST*)buf;
short *sbuf = (short*)buf;
for(int i=0;i<todo;i++) {
sbuf[i] = buffers.getElementAtIndex<ST>(cursor>>8);
sbuf[i] = buffers.getShortAtIndex(cursor>>8);
cursor += incr;
}
buffers.dequeue((cursor>>8)<<SHIFT);
buffers.dequeue((cursor>>8)<<1);
cursor &= 255;
memset(sbuf+todo,ZERO,(samples-todo)<<SHIFT);
//perhaps mute
if(mute) memset(sbuf,0,samples<<1);
else memset(sbuf+todo,0,(samples-todo)<<1);
return samples;
}
Player() {
cursor = 0;
void receive(int bytes, void *buf) {
dsout->lock();
buffers.enqueue(bytes,buf);
buffers.decay(60);
dsout->unlock();
}
void throttle() {
//wait for the buffer to be satisfactorily low before continuing
for(;;) {
dsout->lock();
int remain = buffers.length>>1;
dsout->unlock();
if(remain<44100/60) break;
//if(remain<44100*scale/256/60) break; ??
Sleep(1);
}
}
void setScale(int scale) {
dsout->lock();
this->scale = scale;
dsout->unlock();
}
Player() {
scale = 256;
cursor = 0;
}
};
class ShortPlayer : public Player<short,1,0> {};
class BytePlayer : public Player<unsigned char,0,0x80> {};
static ShortPlayer *shortPlayer;
static BytePlayer *bytePlayer;
static PlayerBase *player;
//this class just converts the primary 16bit audio stream to 8bit
class Player8 : public OAKRA_Module {
public:
Player *player;
Player8(Player *player) { this->player = player; }
int generate(int samples, void *buf) {
int half = samples>>1;
//retrieve first half of 16bit samples
player->generate(half,buf);
//and convert to 8bit
unsigned char *dbuf = (unsigned char*)buf;
short *sbuf = (short*)buf;
for(int i=0;i<half;i++)
dbuf[i] = (sbuf[i]>>8)^0x80;
//now retrieve second half
int remain = samples-half;
short *halfbuf = (short*)alloca(remain<<1);
player->generate(remain,halfbuf);
dbuf += half;
for(int i=0;i<remain;i++)
dbuf[i] = (halfbuf[i]>>8)^0x80;
return samples;
}
};
static Player *player;
static Player8 *player8;
void win_Throttle() {
player->throttle();
@ -265,25 +271,22 @@ void win_SoundInit(int bits) {
fmt.size = OAKRA_Module::calcSize(fmt);
OAKRA_Voice *voice = dsout->getVoice(fmt);
if(bits == 8)
player = bytePlayer = new BytePlayer();
else player = shortPlayer = new ShortPlayer();
player = new Player();
player8 = new Player8(player);
dsout->lock();
voice->setSource(player);
if(bits == 8) voice->setSource(player8);
else voice->setSource(player);
dsout->unlock();
}
void TrashSound() {
delete dsout;
if(dsout) delete dsout;
if(player) delete player;
dsout = 0;
player = 0;
}
//HACK - aviout is expecting this
WAVEFORMATEX wf;
int bittage; //1 -> 8bit
static int bits;
int InitSound() {
@ -297,6 +300,7 @@ int InitSound() {
FCEUD_PrintError("DirectSound: 16-bit sound is not supported. Forcing 8-bit sound.");*/
bits = 16;
}
bits = 8;
win_SoundInit(bits);
@ -315,27 +319,16 @@ void win_SoundWriteData(int32 *buffer, int count) {
//todo..
// FCEUI_AviSoundUpdate((void*)MBuffer, Count);
switch(bits) {
case 16: {
void *tempbuf = alloca(2*count);
short *sbuf = (short *)tempbuf;
for(int i=0;i<count;i++)
sbuf[i] = buffer[i];
player->receive(count*2,tempbuf);
break;
}
case 8: {
void *tempbuf = alloca(count);
unsigned char *bbuf = (unsigned char *)tempbuf;
for(int i=0;i<count;i++)
bbuf[i] = (buffer[i]>>8)^128;
player->receive(count,tempbuf);
}
}
void *tempbuf = alloca(2*count);
short *sbuf = (short *)tempbuf;
for(int i=0;i<count;i++)
sbuf[i] = buffer[i];
player->receive(count*2,tempbuf);
}
//--------
//GUI and control APIs
static HWND uug=0;
@ -524,14 +517,13 @@ void FCEUD_SoundToggle(void)
{
if(mute)
{
mute=0;
FCEU_DispMessage("Sound mute off.");
mute = false;
FCEU_DispMessage("Sound unmuted");
}
else
{
mute=1;
StopSound();
FCEU_DispMessage("Sound mute on.");
mute = true;
FCEU_DispMessage("Sound muted");
}
}
@ -543,12 +535,65 @@ void FCEUD_SoundVolumeAdjust(int n)
case 0: soundvolume=100; break;
case 1: soundvolume+=10; if(soundvolume>150) soundvolume=150; break;
}
mute=0;
mute = false;
FCEUI_SetSoundVolume(soundvolume);
FCEU_DispMessage("Sound volume %d.", soundvolume);
}
//-----------
//throttle stuff
//-----------
static uint64 desiredfps;
static int32 fps_scale_table[]=
{ 3, 3, 4, 8, 16, 32, 64, 128, 192, 256, 384, 512, 768, 1024, 2048, 4096, 8192, 16384, 16384};
int32 fps_scale = 256;
static void RefreshThrottleFPS(void)
{
printf("WTF\n");
fflush(stdout);
desiredfps=FCEUI_GetDesiredFPS()>>8;
desiredfps=(desiredfps*fps_scale)>>8;
}
static void IncreaseEmulationSpeed(void)
{
int i;
for(i=1; fps_scale_table[i]<fps_scale; i++)
;
fps_scale = fps_scale_table[i+1];
}
static void DecreaseEmulationSpeed(void)
{
int i;
for(i=1; fps_scale_table[i]<fps_scale; i++)
;
fps_scale = fps_scale_table[i-1];
}
#define fps_table_size (sizeof(fps_scale_table)/sizeof(fps_scale_table[0]))
void FCEUD_SetEmulationSpeed(int cmd)
{
switch(cmd)
{
case EMUSPEED_SLOWEST: fps_scale=fps_scale_table[0]; break;
case EMUSPEED_SLOWER: DecreaseEmulationSpeed(); break;
case EMUSPEED_NORMAL: fps_scale=256; break;
case EMUSPEED_FASTER: IncreaseEmulationSpeed(); break;
case EMUSPEED_FASTEST: fps_scale=fps_scale_table[fps_table_size-1]; break;
default:
return;
}
RefreshThrottleFPS();
FCEU_DispMessage("emulation speed %d%%",(fps_scale*100)>>8);
}
#include "wave.cpp"

View File

@ -1,84 +0,0 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2002 Xodnizel
*
* 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
*/
//http://www.geisswerks.com/ryan/FAQS/timing.html
static uint64 tmethod,tfreq;
static uint64 desiredfps;
static int32 fps_scale_table[]=
{ 3, 3, 4, 8, 16, 32, 64, 128, 192, 256, 384, 512, 768, 1024, 2048, 4096, 8192, 16384, 16384};
int32 fps_scale = 256;
static void RefreshThrottleFPS(void)
{
printf("WTF\n");
fflush(stdout);
desiredfps=FCEUI_GetDesiredFPS()>>8;
desiredfps=(desiredfps*fps_scale)>>8;
}
//mbg todo - these were used by the FPS calculator in video/cpp
// Quick code for internal FPS display.
//uint64 FCEUD_GetTime(void)
//{
// return(GetCurTime()); //this was using queryperformancecounter yuck
//}
//uint64 FCEUD_GetTimeFreq(void)
//{
// return(tfreq>>16);
//}
static void IncreaseEmulationSpeed(void)
{
int i;
for(i=1; fps_scale_table[i]<fps_scale; i++)
;
fps_scale = fps_scale_table[i+1];
}
static void DecreaseEmulationSpeed(void)
{
int i;
for(i=1; fps_scale_table[i]<fps_scale; i++)
;
fps_scale = fps_scale_table[i-1];
}
#define fps_table_size (sizeof(fps_scale_table)/sizeof(fps_scale_table[0]))
void FCEUD_SetEmulationSpeed(int cmd)
{
switch(cmd)
{
case EMUSPEED_SLOWEST: fps_scale=fps_scale_table[0]; break;
case EMUSPEED_SLOWER: DecreaseEmulationSpeed(); break;
case EMUSPEED_NORMAL: fps_scale=256; break;
case EMUSPEED_FASTER: IncreaseEmulationSpeed(); break;
case EMUSPEED_FASTEST: fps_scale=fps_scale_table[fps_table_size-1]; break;
default:
return;
}
RefreshThrottleFPS();
FCEU_DispMessage("emulation speed %d%%",(fps_scale*100)>>8);
}

View File

@ -646,7 +646,7 @@ LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
case 322:ConfigTiming();break;
case 323:StopSound();ShowNetplayConsole();break;
case 324:StopSound();ConfigPalette();break;
case 325:StopSound();ConfigSound();break;
case 325:StopSound();ConfigSound();break;
case 326:ConfigVideo();break;
case 328:MapInput();break;

View File

@ -45,24 +45,12 @@ void FCEU_WriteWaveData(int32 *Buffer, int Count)
if(soundlog)
wsize+=fwrite(temp,1,Count*sizeof(int16),soundlog);
#ifdef MSVC
if(FCEUI_AviIsRecording())
{
extern int bittage;
if(!bittage)
{
//mbg merge 7/17/06 changed to alloca
//int8 temp2[Count];
int8 *temp2 = (int8*)alloca(Count);
int P;
for(P=0;P<Count;P++)
*(((uint8*)temp2)+P)=((int8)(temp[P]>>8))^128;
FCEUI_AviSoundUpdate((void*)temp2, Count);
}
else
FCEUI_AviSoundUpdate((void*)temp, Count);
}
#endif
#ifdef MSVC
if(FCEUI_AviIsRecording())
{
FCEUI_AviSoundUpdate((void*)temp, Count);
}
#endif
}
int FCEUI_EndWaveRecord(void)