From e8135fea5a10dba25fefe991bf6bc36f351e2919 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 4 Mar 2022 18:37:30 +0100 Subject: codec: sid: add cRSID-1.0 for 21st century SID playback Plain import of the library parts first. Adaptions to Rockbox will follow. A *lot* of kudos go to Mihaly Horvath for creating this library from his already lightweight cSID-light, mainly for Rockbox. Besides a lot of other things, he made his algorithms integer-only and significantly improved the C64 emulation, so finally RSIDs could be played as well as PSIDs. TinySID was nice for what it is, but this is a quantum leap in SID playback quality for Rockbox. Check for example: https://hvsc.csdb.dk/MUSICIANS/P/Page_Jason/Eighth.sid https://hvsc.csdb.dk/MUSICIANS/J/Jeff/Blowing.sid Change-Id: I353e12fbfd7cd8696b834616e55743e7b844a73e --- lib/rbcodec/codecs/cRSID/host/audio.c | 62 +++++++++++++++++++++++++++++++++++ lib/rbcodec/codecs/cRSID/host/file.c | 60 +++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 lib/rbcodec/codecs/cRSID/host/audio.c create mode 100644 lib/rbcodec/codecs/cRSID/host/file.c (limited to 'lib/rbcodec/codecs/cRSID/host') diff --git a/lib/rbcodec/codecs/cRSID/host/audio.c b/lib/rbcodec/codecs/cRSID/host/audio.c new file mode 100644 index 0000000000..2e06279113 --- /dev/null +++ b/lib/rbcodec/codecs/cRSID/host/audio.c @@ -0,0 +1,62 @@ + +#ifdef CRSID_PLATFORM_PC + +#include + + +void cRSID_soundCallback(void* userdata, unsigned char *buf, int len) { + cRSID_generateSound( (cRSID_C64instance*)userdata, buf, len ); +} + + +void* cRSID_initSound(cRSID_C64instance* C64, unsigned short samplerate, unsigned short buflen) { + static SDL_AudioSpec soundspec; + if ( SDL_Init(SDL_INIT_AUDIO) < 0 ) { + fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError()); return NULL; + } + soundspec.freq=samplerate; soundspec.channels=1; soundspec.format=AUDIO_S16; + soundspec.samples=buflen; soundspec.userdata=C64; soundspec.callback=cRSID_soundCallback; + if ( SDL_OpenAudio(&soundspec, NULL) < 0 ) { + fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError()); return NULL; + } + return (void*)&soundspec; +} + + +void cRSID_closeSound (void) { + SDL_PauseAudio(1); SDL_CloseAudio(); +} + + +void cRSID_startSound (void) { + SDL_PauseAudio(0); +} + + +void cRSID_stopSound (void) { + SDL_PauseAudio(1); +} + + +void cRSID_generateSound(cRSID_C64instance* C64instance, unsigned char *buf, unsigned short len) { + static unsigned short i; + static int Output; + for(i=0;i=32767) Output=32767; else if (Output<=-32768) Output=-32768; //saturation logic on overflow + buf[i]=Output&0xFF; buf[i+1]=Output>>8; + } +} + + +#endif + + +static inline signed short cRSID_generateSample (cRSID_C64instance* C64) { //call this from custom buffer-filler + static int Output; + Output=cRSID_emulateC64(C64); + if (C64->PSIDdigiMode) Output += cRSID_playPSIDdigi(C64); + if (Output>=32767) Output=32767; else if (Output<=-32768) Output=-32768; //saturation logic on overflow + return (signed short) Output; +} + diff --git a/lib/rbcodec/codecs/cRSID/host/file.c b/lib/rbcodec/codecs/cRSID/host/file.c new file mode 100644 index 0000000000..c87f37ebb4 --- /dev/null +++ b/lib/rbcodec/codecs/cRSID/host/file.c @@ -0,0 +1,60 @@ + + +#ifdef CRSID_PLATFORM_PC + +int cRSID_loadSIDfile (unsigned char* SIDfileData, char* filename, int maxlen) { + static signed short Data; + static signed int SizeCnt; + static FILE *SIDfile; + + if ( (SIDfile=fopen(filename,"rb")) == NULL ) return CRSID_ERROR_LOAD; + + SizeCnt=0; + + while ( (Data=fgetc(SIDfile)) != EOF ) { + if (SizeCnt >= maxlen) return CRSID_ERROR_LOAD; + SIDfileData[SizeCnt] = Data; SizeCnt++; + } + + fclose(SIDfile); + return SizeCnt; +} + +#endif + + +cRSID_SIDheader* cRSID_processSIDfile(cRSID_C64instance* C64, unsigned char* filedata, int filesize) { + int i; + unsigned short SIDdataOffset; + cRSID_SIDheader* SIDheader; + static const char MagicStringPSID[]="PSID"; + //static const char MagicStringRSID[]="RSID"; + + C64->SIDheader = SIDheader = (cRSID_SIDheader*) filedata; + + for (i=0x0000; i < 0xA000; ++i) C64->RAMbank[i]=0; //fresh start (maybe some bugged SIDs want 0 at certain RAM-locations) + for (i=0xC000; i < 0xD000; ++i) C64->RAMbank[i]=0; + + if ( SIDheader->MagicString[0] != 'P' && SIDheader->MagicString[0] != 'R' ) return NULL; + for (i=1; i < (int)(sizeof(MagicStringPSID)-1); ++i) { if (SIDheader->MagicString[i] != MagicStringPSID[i]) return NULL; } + C64->RealSIDmode = ( SIDheader->MagicString[0] == 'R' ); + + if (SIDheader->LoadAddressH==0 && SIDheader->LoadAddressH==0) { //load-address taken from first 2 bytes of the C64 PRG + C64->LoadAddress = (filedata[SIDheader->HeaderSize+1]<<8) + (filedata[SIDheader->HeaderSize+0]); + SIDdataOffset = SIDheader->HeaderSize+2; + } + else { //load-adress taken from SID-header + C64->LoadAddress = (SIDheader->LoadAddressH<<8) + (SIDheader->LoadAddressL); + SIDdataOffset = SIDheader->HeaderSize; + } + + for (i=SIDdataOffset; iRAMbank [ C64->LoadAddress + (i-SIDdataOffset) ] = filedata[i]; + + i = C64->LoadAddress + (filesize-SIDdataOffset); + C64->EndAddress = (i<0x10000) ? i : 0xFFFF; + + C64->PSIDdigiMode = ( !C64->RealSIDmode && (SIDheader->ModelFormatStandard & 2) ); + + return C64->SIDheader; +} + -- cgit v1.2.3