soloud_tedsid.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /*
  2. TED/SID module for SoLoud audio engine
  3. Copyright (c) 2015-2020 Jari Komppa
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any damages
  6. arising from the use of this software.
  7. Permission is granted to anyone to use this software for any purpose,
  8. including commercial applications, and to alter it and redistribute it
  9. freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you must not
  11. claim that you wrote the original software. If you use this software
  12. in a product, an acknowledgment in the product documentation would be
  13. appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and must not be
  15. misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source
  17. distribution.
  18. */
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include <math.h>
  23. #include "sid.h"
  24. #include "ted.h"
  25. #include "soloud_tedsid.h"
  26. #include "soloud_file.h"
  27. #include "zx7decompress.h"
  28. namespace SoLoud
  29. {
  30. TedSidInstance::TedSidInstance(TedSid *aParent)
  31. {
  32. mParent = aParent;
  33. mSampleCount = 0;
  34. mSID = new SIDsound(mParent->mModel, 0);
  35. mSID->setFrequency(0);
  36. mSID->setSampleRate(TED_SOUND_CLOCK);
  37. mSID->setFrequency(1);
  38. mTED = new TED();
  39. mTED->oscillatorInit();
  40. int i;
  41. for (i = 0; i < 128; i++)
  42. mRegValues[i] = 0;
  43. mPos = 0;
  44. }
  45. unsigned int TedSidInstance::getAudio(float *aBuffer, unsigned int aSamplesToRead, unsigned int /*aBufferSize*/)
  46. {
  47. unsigned int i;
  48. for (i = 0; i < aSamplesToRead; i++)
  49. {
  50. tick();
  51. short sample;
  52. mSID->calcSamples(&sample, 1);
  53. short tedsample = 0;
  54. mTED->renderSound(1, &tedsample);
  55. aBuffer[i] = (sample + tedsample) / 8192.0f;
  56. mSampleCount--;
  57. }
  58. return aSamplesToRead;
  59. }
  60. void TedSidInstance::tick()
  61. {
  62. if (mParent->mOps == 0)
  63. return;
  64. while (mSampleCount == 0)
  65. {
  66. unsigned short op = mParent->mOps[mPos / 2];
  67. mPos += 2;
  68. if (mPos >= mParent->mLength) mPos = mParent->mLooppos;
  69. if (op & 0x8000)
  70. {
  71. mSampleCount = op & 0x7fff;
  72. }
  73. else
  74. {
  75. int reg = (op >> 8) & 0xff;
  76. int val = op & 0xff;
  77. mRegValues[reg] = val;
  78. if (reg < 64)
  79. {
  80. mSID->write(reg, val);
  81. }
  82. else
  83. if (reg < 64 + 5)
  84. {
  85. mTED->writeSoundReg(reg - 64, val);
  86. }
  87. }
  88. }
  89. }
  90. float TedSidInstance::getInfo(unsigned int aInfoKey)
  91. {
  92. return (float)mRegValues[aInfoKey & 127];
  93. }
  94. bool TedSidInstance::hasEnded()
  95. {
  96. return 0;
  97. }
  98. TedSidInstance::~TedSidInstance()
  99. {
  100. delete mSID;
  101. delete mTED;
  102. }
  103. TedSid::TedSid()
  104. {
  105. mBaseSamplerate = TED_SOUND_CLOCK;
  106. mChannels = 1;
  107. mOps = 0;
  108. mModel = 0;
  109. mLength = 0;
  110. mLooppos = 0;
  111. }
  112. TedSid::~TedSid()
  113. {
  114. stop();
  115. delete[] mOps;
  116. mOps = 0;
  117. }
  118. result TedSid::loadMem(const unsigned char *aMem, unsigned int aLength, bool aCopy, bool aTakeOwnership)
  119. {
  120. if (!aMem || aLength == 0)
  121. return INVALID_PARAMETER;
  122. MemoryFile mf;
  123. int res = mf.openMem(aMem, aLength, aCopy, aTakeOwnership);
  124. if (res != SO_NO_ERROR)
  125. {
  126. return res;
  127. }
  128. res = loadFile(&mf);
  129. return res;
  130. }
  131. result TedSid::load(const char *aFilename)
  132. {
  133. if (!aFilename)
  134. return INVALID_PARAMETER;
  135. DiskFile df;
  136. int res = df.open(aFilename);
  137. if (res != SO_NO_ERROR)
  138. {
  139. return res;
  140. }
  141. res = loadFile(&df);
  142. return res;
  143. }
  144. result TedSid::loadFile(File *aFile)
  145. {
  146. if (aFile == NULL)
  147. return INVALID_PARAMETER;
  148. delete[] mOps;
  149. mOps = 0;
  150. // Expect a file wih header and at least one reg write
  151. if (aFile->length() < 34) return FILE_LOAD_FAILED;
  152. aFile->seek(0);
  153. if (aFile->read32() != 'PIHC') return FILE_LOAD_FAILED; // CHIP
  154. if (aFile->read32() != 'ENUT') return FILE_LOAD_FAILED; // TUNE
  155. int dataofs = aFile->read16();
  156. int chiptype = aFile->read8();
  157. // check if this file is for sid, ted, or combination of several
  158. if (!(chiptype == 0 || chiptype == 4 || chiptype == 5 || chiptype == 6)) return FILE_LOAD_FAILED;
  159. int flags = aFile->read8();
  160. int kchunks = aFile->read16();
  161. int lastchunk = aFile->read16();
  162. mLength = (kchunks - 1) * 1024 + lastchunk;
  163. mLooppos = aFile->read16() * 1024 + aFile->read16();
  164. aFile->read32(); // cpuspeed
  165. aFile->read32(); // chipspeed
  166. if ((mFlags & (16 | 32)) == 0) mModel = SID6581;
  167. if ((mFlags & (16 | 32)) == 16) mModel = SID8580;
  168. if ((mFlags & (16 | 32)) == 32) mModel = SID8580DB;
  169. if ((mFlags & (16 | 32)) == 48) mModel = SID6581R1;
  170. mOps = new unsigned short[mLength];
  171. aFile->seek(dataofs);
  172. if (flags & 1)
  173. {
  174. // uncompressed
  175. aFile->read((unsigned char*)mOps, mLength);
  176. }
  177. else
  178. {
  179. // compressed
  180. int len = aFile->length() - dataofs;
  181. unsigned char* buf = new unsigned char[len];
  182. aFile->read(buf, len);
  183. int bufofs = 0;
  184. for (int i = 0; i < kchunks; i++)
  185. {
  186. bufofs += zx7_decompress(buf + bufofs, ((unsigned char*)mOps) + i * 1024);
  187. }
  188. delete[] buf;
  189. }
  190. return SO_NO_ERROR;
  191. }
  192. AudioSourceInstance * TedSid::createInstance()
  193. {
  194. return new TedSidInstance(this);
  195. }
  196. };