diff options
author | Wolfram Sang <wsa@the-dreams.de> | 2022-03-04 18:37:30 +0100 |
---|---|---|
committer | Solomon Peachy <pizza@shaftnet.org> | 2023-02-07 09:19:32 -0500 |
commit | e8135fea5a10dba25fefe991bf6bc36f351e2919 (patch) | |
tree | a17571dc0c1bc25a824f639be88d461245d62e89 /lib/rbcodec/codecs/cRSID/host | |
parent | 1c26f565bf0ae50495dc8d2139f76bd367728cd6 (diff) | |
download | rockbox-e8135fea5a10dba25fefe991bf6bc36f351e2919.tar.gz rockbox-e8135fea5a10dba25fefe991bf6bc36f351e2919.zip |
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
Diffstat (limited to 'lib/rbcodec/codecs/cRSID/host')
-rw-r--r-- | lib/rbcodec/codecs/cRSID/host/audio.c | 62 | ||||
-rw-r--r-- | lib/rbcodec/codecs/cRSID/host/file.c | 60 |
2 files changed, 122 insertions, 0 deletions
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 @@ | |||
1 | |||
2 | #ifdef CRSID_PLATFORM_PC | ||
3 | |||
4 | #include <SDL/SDL.h> | ||
5 | |||
6 | |||
7 | void cRSID_soundCallback(void* userdata, unsigned char *buf, int len) { | ||
8 | cRSID_generateSound( (cRSID_C64instance*)userdata, buf, len ); | ||
9 | } | ||
10 | |||
11 | |||
12 | void* cRSID_initSound(cRSID_C64instance* C64, unsigned short samplerate, unsigned short buflen) { | ||
13 | static SDL_AudioSpec soundspec; | ||
14 | if ( SDL_Init(SDL_INIT_AUDIO) < 0 ) { | ||
15 | fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError()); return NULL; | ||
16 | } | ||
17 | soundspec.freq=samplerate; soundspec.channels=1; soundspec.format=AUDIO_S16; | ||
18 | soundspec.samples=buflen; soundspec.userdata=C64; soundspec.callback=cRSID_soundCallback; | ||
19 | if ( SDL_OpenAudio(&soundspec, NULL) < 0 ) { | ||
20 | fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError()); return NULL; | ||
21 | } | ||
22 | return (void*)&soundspec; | ||
23 | } | ||
24 | |||
25 | |||
26 | void cRSID_closeSound (void) { | ||
27 | SDL_PauseAudio(1); SDL_CloseAudio(); | ||
28 | } | ||
29 | |||
30 | |||
31 | void cRSID_startSound (void) { | ||
32 | SDL_PauseAudio(0); | ||
33 | } | ||
34 | |||
35 | |||
36 | void cRSID_stopSound (void) { | ||
37 | SDL_PauseAudio(1); | ||
38 | } | ||
39 | |||
40 | |||
41 | void cRSID_generateSound(cRSID_C64instance* C64instance, unsigned char *buf, unsigned short len) { | ||
42 | static unsigned short i; | ||
43 | static int Output; | ||
44 | for(i=0;i<len;i+=2) { | ||
45 | Output=cRSID_generateSample(C64instance); //cRSID_emulateC64(C64instance); | ||
46 | //if (Output>=32767) Output=32767; else if (Output<=-32768) Output=-32768; //saturation logic on overflow | ||
47 | buf[i]=Output&0xFF; buf[i+1]=Output>>8; | ||
48 | } | ||
49 | } | ||
50 | |||
51 | |||
52 | #endif | ||
53 | |||
54 | |||
55 | static inline signed short cRSID_generateSample (cRSID_C64instance* C64) { //call this from custom buffer-filler | ||
56 | static int Output; | ||
57 | Output=cRSID_emulateC64(C64); | ||
58 | if (C64->PSIDdigiMode) Output += cRSID_playPSIDdigi(C64); | ||
59 | if (Output>=32767) Output=32767; else if (Output<=-32768) Output=-32768; //saturation logic on overflow | ||
60 | return (signed short) Output; | ||
61 | } | ||
62 | |||
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 @@ | |||
1 | |||
2 | |||
3 | #ifdef CRSID_PLATFORM_PC | ||
4 | |||
5 | int cRSID_loadSIDfile (unsigned char* SIDfileData, char* filename, int maxlen) { | ||
6 | static signed short Data; | ||
7 | static signed int SizeCnt; | ||
8 | static FILE *SIDfile; | ||
9 | |||
10 | if ( (SIDfile=fopen(filename,"rb")) == NULL ) return CRSID_ERROR_LOAD; | ||
11 | |||
12 | SizeCnt=0; | ||
13 | |||
14 | while ( (Data=fgetc(SIDfile)) != EOF ) { | ||
15 | if (SizeCnt >= maxlen) return CRSID_ERROR_LOAD; | ||
16 | SIDfileData[SizeCnt] = Data; SizeCnt++; | ||
17 | } | ||
18 | |||
19 | fclose(SIDfile); | ||
20 | return SizeCnt; | ||
21 | } | ||
22 | |||
23 | #endif | ||
24 | |||
25 | |||
26 | cRSID_SIDheader* cRSID_processSIDfile(cRSID_C64instance* C64, unsigned char* filedata, int filesize) { | ||
27 | int i; | ||
28 | unsigned short SIDdataOffset; | ||
29 | cRSID_SIDheader* SIDheader; | ||
30 | static const char MagicStringPSID[]="PSID"; | ||
31 | //static const char MagicStringRSID[]="RSID"; | ||
32 | |||
33 | C64->SIDheader = SIDheader = (cRSID_SIDheader*) filedata; | ||
34 | |||
35 | for (i=0x0000; i < 0xA000; ++i) C64->RAMbank[i]=0; //fresh start (maybe some bugged SIDs want 0 at certain RAM-locations) | ||
36 | for (i=0xC000; i < 0xD000; ++i) C64->RAMbank[i]=0; | ||
37 | |||
38 | if ( SIDheader->MagicString[0] != 'P' && SIDheader->MagicString[0] != 'R' ) return NULL; | ||
39 | for (i=1; i < (int)(sizeof(MagicStringPSID)-1); ++i) { if (SIDheader->MagicString[i] != MagicStringPSID[i]) return NULL; } | ||
40 | C64->RealSIDmode = ( SIDheader->MagicString[0] == 'R' ); | ||
41 | |||
42 | if (SIDheader->LoadAddressH==0 && SIDheader->LoadAddressH==0) { //load-address taken from first 2 bytes of the C64 PRG | ||
43 | C64->LoadAddress = (filedata[SIDheader->HeaderSize+1]<<8) + (filedata[SIDheader->HeaderSize+0]); | ||
44 | SIDdataOffset = SIDheader->HeaderSize+2; | ||
45 | } | ||
46 | else { //load-adress taken from SID-header | ||
47 | C64->LoadAddress = (SIDheader->LoadAddressH<<8) + (SIDheader->LoadAddressL); | ||
48 | SIDdataOffset = SIDheader->HeaderSize; | ||
49 | } | ||
50 | |||
51 | for (i=SIDdataOffset; i<filesize; ++i) C64->RAMbank [ C64->LoadAddress + (i-SIDdataOffset) ] = filedata[i]; | ||
52 | |||
53 | i = C64->LoadAddress + (filesize-SIDdataOffset); | ||
54 | C64->EndAddress = (i<0x10000) ? i : 0xFFFF; | ||
55 | |||
56 | C64->PSIDdigiMode = ( !C64->RealSIDmode && (SIDheader->ModelFormatStandard & 2) ); | ||
57 | |||
58 | return C64->SIDheader; | ||
59 | } | ||
60 | |||