Implemented sound transfer over the network (for Linux). This hasn't

been even the least tested yet, so don't try this code. You have been
warned!
This commit is contained in:
simon.kagstrom 2009-04-09 13:42:49 +00:00
parent 189833e30f
commit 42a6e19e0d
7 changed files with 68 additions and 30 deletions

View File

@ -608,7 +608,8 @@ void C64::network_vblank()
/* Has the peer sent any data? */ /* Has the peer sent any data? */
if (remote->ReceiveUpdate() == true) if (remote->ReceiveUpdate() == true)
{ {
if (remote->DecodeUpdate(remote->GetScreen(), js) == false) if (remote->DecodeUpdate(remote->GetScreen(),
js, this->TheSID) == false)
{ {
/* Disconnect or sending crap, remove this guy! */ /* Disconnect or sending crap, remove this guy! */
delete remote; delete remote;
@ -621,16 +622,16 @@ void C64::network_vblank()
remote->ResetNetworkUpdate(); remote->ResetNetworkUpdate();
if (this->network_connection_type == MASTER && if (this->network_connection_type == MASTER &&
remote->ThrottleTraffic()) { !remote->ThrottleTraffic()) {
/* Skip this frame if the data rate is too high */ /* Skip this frame if the data rate is too high */
has_throttled = true; has_throttled = true;
return; remote->EncodeDisplay(master, remote->GetScreen());
} }
/* Perhaps send updates to the other side (what is determined by /* Perhaps send updates to the other side (what is determined by
* if this is the master or not) */ * if this is the master or not) */
remote->EncodeJoystickUpdate(*js); remote->EncodeJoystickUpdate(*js);
remote->EncodeDisplay(master, remote->GetScreen()); remote->EncodeSound();
if (remote->SendUpdate() == false) if (remote->SendUpdate() == false)
{ {

View File

@ -48,7 +48,7 @@ Network::Network(const char *remote_host, int port, bool is_master)
this->InitNetwork(); this->InitNetwork();
this->is_master = is_master; Network::is_master = is_master;
this->connected = false; this->connected = false;
/* "big enough" buffer */ /* "big enough" buffer */
@ -262,7 +262,7 @@ bool Network::CompareSquare(Uint8 *a, Uint8 *b)
void Network::EncodeDisplay(Uint8 *master, Uint8 *remote) void Network::EncodeDisplay(Uint8 *master, Uint8 *remote)
{ {
if (!this->is_master) if (!Network::is_master)
return; return;
for ( int sq = 0; sq < N_SQUARES_H * N_SQUARES_W; sq++ ) for ( int sq = 0; sq < N_SQUARES_H * N_SQUARES_W; sq++ )
{ {
@ -408,8 +408,8 @@ size_t Network::EncodeSoundBuffer(struct NetworkUpdate *dst, Uint8 *buf, size_t
printf("Not implemented\n"); printf("Not implemented\n");
dst->size = 0; dst->size = 0;
/* Try encoding as RLE, but if it's too large, go for RAW */ /* Try encoding as RLE, but if it's too large, go for RAW */
out = this->EncodeSoundRLE(dst, buf, len); // out = this->EncodeSoundRLE(dst, buf, len);
if (out > len) // if (out > len)
out = this->EncodeSoundRaw(dst, buf, len); out = this->EncodeSoundRaw(dst, buf, len);
dst->size = out + sizeof(struct NetworkUpdate); dst->size = out + sizeof(struct NetworkUpdate);
@ -418,14 +418,29 @@ size_t Network::EncodeSoundBuffer(struct NetworkUpdate *dst, Uint8 *buf, size_t
void Network::EncodeSound() void Network::EncodeSound()
{ {
NetworkUpdate *dst = (NetworkUpdate *)this->cur_ud;
static Uint8 tmp_buf[NETWORK_SOUND_BUF_SIZE];
int offset = 0;
/* Nothing to encode? */ /* Nothing to encode? */
if (!this->is_master || if (!Network::is_master ||
Network::sample_head == Network::sample_tail) Network::sample_head == Network::sample_tail)
return; return;
while (Network::sample_tail != Network::sample_head)
if (Network::sample_tail > Network::sample_head)
{ {
Network::sample_tail = (Network::sample_tail + 1) % NETWORK_SOUND_BUF_SIZE; memcpy(tmp_buf + offset, Network::sample_buf + Network::sample_tail,
NETWORK_SOUND_BUF_SIZE - Network::sample_tail);
offset += NETWORK_SOUND_BUF_SIZE - Network::sample_tail;
Network::sample_tail = 0;
} }
memcpy(tmp_buf + offset, Network::sample_buf + Network::sample_tail,
Network::sample_head - Network::sample_tail);
offset += Network::sample_head - Network::sample_tail;
Network::sample_tail = Network::sample_head;
this->EncodeSoundBuffer(dst, tmp_buf, offset);
this->AddNetworkUpdate(dst);
} }
void Network::PushSound(uint8 vol) void Network::PushSound(uint8 vol)
@ -439,7 +454,7 @@ void Network::EncodeJoystickUpdate(Uint8 v)
struct NetworkUpdate *dst = this->cur_ud; struct NetworkUpdate *dst = this->cur_ud;
struct NetworkUpdateJoystick *j = (NetworkUpdateJoystick *)dst->data; struct NetworkUpdateJoystick *j = (NetworkUpdateJoystick *)dst->data;
if (this->is_master || this->cur_joystick_data == v) if (Network::is_master || this->cur_joystick_data == v)
return; return;
dst = InitNetworkUpdate(dst, JOYSTICK_UPDATE, dst = InitNetworkUpdate(dst, JOYSTICK_UPDATE,
sizeof(NetworkUpdate) + sizeof(NetworkUpdateJoystick)); sizeof(NetworkUpdate) + sizeof(NetworkUpdateJoystick));
@ -450,14 +465,15 @@ void Network::EncodeJoystickUpdate(Uint8 v)
} }
size_t Network::DecodeSoundUpdate(struct NetworkUpdate *src, char *buf) size_t Network::DecodeSoundUpdate(struct NetworkUpdate *src, MOS6581 *dst)
{ {
size_t out; size_t out;
if (src->type == SOUND_UPDATE_RAW) if (src->type == SOUND_UPDATE_RAW)
{ {
out = src->size - sizeof(struct NetworkUpdate); out = src->size - sizeof(struct NetworkUpdate);
memcpy(buf, src->data, out); for (int i = 0; i < out; i++)
dst->PushVolume(src->data[i]);
} }
else else
out = 0; out = 0;
@ -790,7 +806,7 @@ bool Network::DeMarshalAllData(NetworkUpdate *ud, size_t max_size,
return this->DeMarshalData(p); return this->DeMarshalData(p);
} }
bool Network::DecodeUpdate(uint8 *screen, uint8 *js) bool Network::DecodeUpdate(uint8 *screen, uint8 *js, MOS6581 *dst)
{ {
NetworkUpdate *p = this->ud; NetworkUpdate *p = this->ud;
bool out = true; bool out = true;
@ -803,14 +819,14 @@ bool Network::DecodeUpdate(uint8 *screen, uint8 *js)
case DISPLAY_UPDATE_RLE: case DISPLAY_UPDATE_RLE:
case DISPLAY_UPDATE_DIFF: case DISPLAY_UPDATE_DIFF:
/* No screen updates _to_ the master */ /* No screen updates _to_ the master */
if (this->is_master) if (Network::is_master)
break; break;
if (this->DecodeDisplayUpdate(screen, p) == false) if (this->DecodeDisplayUpdate(screen, p) == false)
out = false; out = false;
break; break;
case JOYSTICK_UPDATE: case JOYSTICK_UPDATE:
/* No joystick updates _from_ the master */ /* No joystick updates _from_ the master */
if (js && this->is_master) if (js && Network::is_master)
{ {
NetworkUpdateJoystick *j = (NetworkUpdateJoystick *)p->data; NetworkUpdateJoystick *j = (NetworkUpdateJoystick *)p->data;
*js = j->val; *js = j->val;
@ -842,7 +858,7 @@ bool Network::ConnectToBroker()
NetworkUpdatePeerInfo *pi = (NetworkUpdatePeerInfo *)ud->data; NetworkUpdatePeerInfo *pi = (NetworkUpdatePeerInfo *)ud->data;
bool out; bool out;
pi->is_master = this->is_master; pi->is_master = Network::is_master;
pi->key = ThePrefs.NetworkKey; pi->key = ThePrefs.NetworkKey;
pi->version = FRODO_NETWORK_PROTOCOL_VERSION; pi->version = FRODO_NETWORK_PROTOCOL_VERSION;
strcpy((char*)pi->name, ThePrefs.NetworkName); strcpy((char*)pi->name, ThePrefs.NetworkName);
@ -1062,7 +1078,7 @@ network_connection_error_t Network::ConnectFSM()
case CONN_CONNECT_TO_BROKER: case CONN_CONNECT_TO_BROKER:
if (this->ConnectToBroker() == true) if (this->ConnectToBroker() == true)
{ {
if (this->is_master) if (Network::is_master)
this->network_connection_state = CONN_WAIT_FOR_PEER_ADDRESS; this->network_connection_state = CONN_WAIT_FOR_PEER_ADDRESS;
else else
this->network_connection_state = CONN_WAIT_FOR_PEER_LIST; this->network_connection_state = CONN_WAIT_FOR_PEER_LIST;
@ -1117,7 +1133,7 @@ bool Network::Connect()
0x00, 0x80, 0x80)); 0x00, 0x80, 0x80));
menu_print_font(real_screen, 255,255,0, 30, 30, menu_print_font(real_screen, 255,255,0, 30, 30,
"Connecting... Hold Esc or 1 to abort"); "Connecting... Hold Esc or 1 to abort");
if (this->is_master) if (Network::is_master)
menu_print_font(real_screen, 255,255,0, 30, 50, menu_print_font(real_screen, 255,255,0, 30, 50,
"(Waiting for client connection)"); "(Waiting for client connection)");
SDL_Flip(real_screen); SDL_Flip(real_screen);
@ -1186,6 +1202,7 @@ void Network::Disconnect()
uint8 Network::sample_buf[NETWORK_SOUND_BUF_SIZE]; uint8 Network::sample_buf[NETWORK_SOUND_BUF_SIZE];
int Network::sample_head; int Network::sample_head;
int Network::sample_tail; int Network::sample_tail;
bool Network::is_master = true; /* Assume until set false */
#if defined(GEKKO) #if defined(GEKKO)
#include "NetworkWii.h" #include "NetworkWii.h"

View File

@ -8,6 +8,8 @@
#endif #endif
#include <SDL.h> #include <SDL.h>
#include "SID.h"
#define FRODO_NETWORK_PROTOCOL_VERSION 2 #define FRODO_NETWORK_PROTOCOL_VERSION 2
#define FRODO_NETWORK_MAGIC 0x1976 #define FRODO_NETWORK_MAGIC 0x1976
@ -150,7 +152,7 @@ public:
void EncodeJoystickUpdate(Uint8 v); void EncodeJoystickUpdate(Uint8 v);
bool DecodeUpdate(uint8 *screen, uint8 *js); bool DecodeUpdate(uint8 *screen, uint8 *js, MOS6581 *dst);
void ResetNetworkUpdate(void); void ResetNetworkUpdate(void);
@ -199,12 +201,13 @@ public:
static void PushSound(uint8 vol); static void PushSound(uint8 vol);
static bool is_master; /* Some peers are more equal than others */
protected: protected:
void InitNetwork(); void InitNetwork();
void ShutdownNetwork(); void ShutdownNetwork();
size_t DecodeSoundUpdate(struct NetworkUpdate *src, char *buf); size_t DecodeSoundUpdate(struct NetworkUpdate *src, MOS6581 *dst);
size_t EncodeSoundRLE(struct NetworkUpdate *dst, size_t EncodeSoundRLE(struct NetworkUpdate *dst,
Uint8 *buffer, size_t len); Uint8 *buffer, size_t len);
@ -339,7 +342,6 @@ protected:
Uint8 *screen; Uint8 *screen;
int joystick_port; int joystick_port;
bool is_master; /* Some peers are more equal than others */
bool connected; bool connected;
Uint8 cur_joystick_data; Uint8 cur_joystick_data;

View File

@ -363,6 +363,7 @@ public:
virtual ~DigitalRenderer(); virtual ~DigitalRenderer();
virtual void Reset(void); virtual void Reset(void);
virtual void PushVolume(uint8 volume);
virtual void EmulateLine(void); virtual void EmulateLine(void);
virtual void WriteRegister(uint16 adr, uint8 byte); virtual void WriteRegister(uint16 adr, uint8 byte);
virtual void NewPrefs(Prefs *prefs); virtual void NewPrefs(Prefs *prefs);

View File

@ -49,6 +49,7 @@ public:
void GetState(MOS6581State *ss); void GetState(MOS6581State *ss);
void SetState(MOS6581State *ss); void SetState(MOS6581State *ss);
void EmulateLine(void); void EmulateLine(void);
void PushVolume(uint8); /* For the network */
private: private:
void open_close_renderer(int old_type, int new_type); void open_close_renderer(int old_type, int new_type);
@ -66,6 +67,7 @@ public:
virtual ~SIDRenderer() {} virtual ~SIDRenderer() {}
virtual void Reset(void)=0; virtual void Reset(void)=0;
virtual void EmulateLine(void)=0; virtual void EmulateLine(void)=0;
virtual void PushVolume(uint8)=0;
virtual void WriteRegister(uint16 adr, uint8 byte)=0; virtual void WriteRegister(uint16 adr, uint8 byte)=0;
virtual void NewPrefs(Prefs *prefs)=0; virtual void NewPrefs(Prefs *prefs)=0;
virtual void Pause(void)=0; virtual void Pause(void)=0;
@ -122,6 +124,12 @@ inline void MOS6581::EmulateLine(void)
} }
inline void MOS6581::PushVolume(uint8 vol)
{
if (the_renderer != NULL)
the_renderer->PushVolume(vol);
}
/* /*
* Read from register * Read from register
*/ */

View File

@ -36,7 +36,7 @@
#define HAVE_CWSID 1 #define HAVE_CWSID 1
#include "VIC.h" #include "VIC.h"
#include "Network.h"
/* /*
* Initialization * Initialization
@ -115,16 +115,13 @@ void DigitalRenderer::Resume(void)
* Fill buffer, sample volume (for sampled voice) * Fill buffer, sample volume (for sampled voice)
*/ */
void DigitalRenderer::EmulateLine(void) void DigitalRenderer::PushVolume(uint8 vol)
{ {
static int divisor = 0; static int divisor = 0;
static int to_output = 0; static int to_output = 0;
static int buffer_pos = 0; static int buffer_pos = 0;
if (!ready) sample_buf[sample_in_ptr] = vol;
return;
sample_buf[sample_in_ptr] = volume;
sample_in_ptr = (sample_in_ptr + 1) % SAMPLE_BUF_SIZE; sample_in_ptr = (sample_in_ptr + 1) % SAMPLE_BUF_SIZE;
// Now see how many samples have to be added for this line // Now see how many samples have to be added for this line
@ -143,6 +140,15 @@ void DigitalRenderer::EmulateLine(void)
} }
} }
void DigitalRenderer::EmulateLine(void)
{
if (!ready)
return;
Network::PushSound(volume);
if (Network::is_master)
this->PushVolume(volume);
}
/* /*
* Renderer for Catweasel card * Renderer for Catweasel card
@ -156,6 +162,7 @@ public:
virtual void Reset(void); virtual void Reset(void);
virtual void EmulateLine(void) {} virtual void EmulateLine(void) {}
virtual void PushVolume(uint8) {}
virtual void WriteRegister(uint16 adr, uint8 byte); virtual void WriteRegister(uint16 adr, uint8 byte);
virtual void NewPrefs(Prefs *prefs) {} virtual void NewPrefs(Prefs *prefs) {}
virtual void Pause(void) {} virtual void Pause(void) {}

View File

@ -2,12 +2,13 @@
* SID_linux.i - 6581 emulation, Linux specific stuff * SID_linux.i - 6581 emulation, Linux specific stuff
* *
* Frodo (C) 1994-1997,2002 Christian Bauer * Frodo (C) 1994-1997,2002 Christian Bauer
* Linux sound stuff by Bernd Schmidt * Wii sound stuff by Simon Kagstrom
*/ */
#include "gcaudio.h" #include "gcaudio.h"
#include "VIC.h" #include "VIC.h"
#include "Network.h"
/* /*
* Initialization * Initialization
@ -69,6 +70,7 @@ void DigitalRenderer::EmulateLine(void)
if (!ready) if (!ready)
return; return;
Network::PushSound(volume);
sample_buf[sample_in_ptr] = volume; sample_buf[sample_in_ptr] = volume;
sample_in_ptr = (sample_in_ptr + 1) % SAMPLE_BUF_SIZE; sample_in_ptr = (sample_in_ptr + 1) % SAMPLE_BUF_SIZE;