sound.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. /*
  2. * PicoDrive
  3. * (c) Copyright Dave, 2004
  4. * (C) notaz, 2006-2009
  5. *
  6. * This work is licensed under the terms of MAME license.
  7. * See COPYING file in the top-level directory.
  8. */
  9. #include <string.h>
  10. #include "ym2612.h"
  11. #include "sn76496.h"
  12. #include "../pico_int.h"
  13. #include "mix.h"
  14. #include "emu2413/emu2413.h"
  15. void (*PsndMix_32_to_16l)(short *dest, int *src, int count) = mix_32_to_16l_stereo;
  16. // master int buffer to mix to
  17. static s32 PsndBuffer[2*(44100+100)/50];
  18. // cdda output buffer
  19. s16 cdda_out_buffer[2*1152];
  20. // sn76496
  21. extern int *sn76496_regs;
  22. // ym2413
  23. #define YM2413_CLK 3579545
  24. OPLL old_opll;
  25. static OPLL *opll = NULL;
  26. unsigned YM2413_reg;
  27. PICO_INTERNAL void PsndInit(void)
  28. {
  29. opll = OPLL_new(YM2413_CLK, PicoIn.sndRate);
  30. OPLL_setChipType(opll,0);
  31. OPLL_reset(opll);
  32. }
  33. PICO_INTERNAL void PsndExit(void)
  34. {
  35. OPLL_delete(opll);
  36. opll = NULL;
  37. }
  38. PICO_INTERNAL void PsndReset(void)
  39. {
  40. // PsndRerate calls YM2612Init, which also resets
  41. PsndRerate(0);
  42. timers_reset();
  43. }
  44. // to be called after changing sound rate or chips
  45. void PsndRerate(int preserve_state)
  46. {
  47. void *state = NULL;
  48. int target_fps = Pico.m.pal ? 50 : 60;
  49. int target_lines = Pico.m.pal ? 313 : 262;
  50. if (preserve_state) {
  51. state = malloc(0x204);
  52. if (state == NULL) return;
  53. ym2612_pack_state();
  54. memcpy(state, YM2612GetRegs(), 0x204);
  55. }
  56. YM2612Init(Pico.m.pal ? OSC_PAL/7 : OSC_NTSC/7, PicoIn.sndRate, !(PicoIn.opt&POPT_DIS_FM_SSGEG));
  57. if (preserve_state) {
  58. // feed it back it's own registers, just like after loading state
  59. memcpy(YM2612GetRegs(), state, 0x204);
  60. ym2612_unpack_state();
  61. }
  62. if (preserve_state) memcpy(state, sn76496_regs, 28*4); // remember old state
  63. SN76496_init(Pico.m.pal ? OSC_PAL/15 : OSC_NTSC/15, PicoIn.sndRate);
  64. if (preserve_state) memcpy(sn76496_regs, state, 28*4); // restore old state
  65. if(opll != NULL){
  66. if (preserve_state) memcpy(&old_opll, opll, sizeof(OPLL)); // remember old state
  67. OPLL_setRate(opll, PicoIn.sndRate);
  68. OPLL_reset(opll);
  69. }
  70. if (state)
  71. free(state);
  72. // calculate Pico.snd.len
  73. Pico.snd.len = PicoIn.sndRate / target_fps;
  74. Pico.snd.len_e_add = ((PicoIn.sndRate - Pico.snd.len * target_fps) << 16) / target_fps;
  75. Pico.snd.len_e_cnt = 0; // Q16
  76. // samples per line (Q16)
  77. Pico.snd.smpl_mult = 65536LL * PicoIn.sndRate / (target_fps*target_lines);
  78. // samples per z80 clock (Q20)
  79. Pico.snd.clkl_mult = 16 * Pico.snd.smpl_mult * 15/7 / 488;
  80. // clear all buffers
  81. memset32(PsndBuffer, 0, sizeof(PsndBuffer)/4);
  82. memset(cdda_out_buffer, 0, sizeof(cdda_out_buffer));
  83. if (PicoIn.sndOut)
  84. PsndClear();
  85. // set mixer
  86. PsndMix_32_to_16l = (PicoIn.opt & POPT_EN_STEREO) ? mix_32_to_16l_stereo : mix_32_to_16_mono;
  87. mix_reset(PicoIn.opt & POPT_EN_SNDFILTER ? PicoIn.sndFilterAlpha : 0);
  88. if (PicoIn.AHW & PAHW_PICO)
  89. PicoReratePico();
  90. }
  91. PICO_INTERNAL void PsndStartFrame(void)
  92. {
  93. // compensate for float part of Pico.snd.len
  94. Pico.snd.len_use = Pico.snd.len;
  95. Pico.snd.len_e_cnt += Pico.snd.len_e_add;
  96. if (Pico.snd.len_e_cnt >= 0x10000) {
  97. Pico.snd.len_e_cnt -= 0x10000;
  98. Pico.snd.len_use++;
  99. }
  100. }
  101. PICO_INTERNAL void PsndDoDAC(int cyc_to)
  102. {
  103. int pos, len;
  104. int dout = ym2612.dacout;
  105. // number of samples to fill in buffer (Q20)
  106. len = (cyc_to * Pico.snd.clkl_mult) - Pico.snd.dac_pos;
  107. // update position and calculate buffer offset and length
  108. pos = (Pico.snd.dac_pos+0x80000) >> 20;
  109. Pico.snd.dac_pos += len;
  110. len = ((Pico.snd.dac_pos+0x80000) >> 20) - pos;
  111. // avoid loss of the 1st sample of a new block (Q rounding issues)
  112. if (pos+len == 0)
  113. len = 1, Pico.snd.dac_pos += 0x80000;
  114. if (len <= 0)
  115. return;
  116. if (!PicoIn.sndOut)
  117. return;
  118. // fill buffer, applying a rather weak order 1 bessel IIR on the way
  119. // y[n] = (x[n] + x[n-1])*(1/2) (3dB cutoff at 11025 Hz, no gain)
  120. // 1 sample delay for correct IIR filtering over audio frame boundaries
  121. if (PicoIn.opt & POPT_EN_STEREO) {
  122. short *d = PicoIn.sndOut + pos*2;
  123. // left channel only, mixed ro right channel in mixing phase
  124. *d++ += Pico.snd.dac_val2; d++;
  125. while (--len) *d++ += Pico.snd.dac_val, d++;
  126. } else {
  127. short *d = PicoIn.sndOut + pos;
  128. *d++ += Pico.snd.dac_val2;
  129. while (--len) *d++ += Pico.snd.dac_val;
  130. }
  131. Pico.snd.dac_val2 = (Pico.snd.dac_val + dout) >> 1;
  132. Pico.snd.dac_val = dout;
  133. }
  134. PICO_INTERNAL void PsndDoPSG(int line_to)
  135. {
  136. int pos, len;
  137. int stereo = 0;
  138. // Q16, number of samples since last call
  139. len = ((line_to+1) * Pico.snd.smpl_mult) - Pico.snd.psg_pos;
  140. if (len <= 0)
  141. return;
  142. // update position and calculate buffer offset and length
  143. pos = (Pico.snd.psg_pos+0x8000) >> 16;
  144. Pico.snd.psg_pos += len;
  145. len = ((Pico.snd.psg_pos+0x8000) >> 16) - pos;
  146. if (!PicoIn.sndOut || !(PicoIn.opt & POPT_EN_PSG))
  147. return;
  148. if (PicoIn.opt & POPT_EN_STEREO) {
  149. stereo = 1;
  150. pos <<= 1;
  151. }
  152. SN76496Update(PicoIn.sndOut + pos, len, stereo);
  153. }
  154. #if 0
  155. PICO_INTERNAL void PsndDoYM2413(int line_to)
  156. {
  157. int pos, len;
  158. int stereo = 0;
  159. short *buf;
  160. // Q16, number of samples since last call
  161. len = ((line_to+1) * Pico.snd.smpl_mult) - Pico.snd.ym2413_pos;
  162. if (len <= 0)
  163. return;
  164. // update position and calculate buffer offset and length
  165. pos = (Pico.snd.ym2413_pos+0x8000) >> 16;
  166. Pico.snd.ym2413_pos += len;
  167. len = ((Pico.snd.ym2413_pos+0x8000) >> 16) - pos;
  168. if (!PicoIn.sndOut || !(PicoIn.opt & POPT_EN_YM2413))
  169. return;
  170. if (PicoIn.opt & POPT_EN_STEREO) {
  171. stereo = 1;
  172. pos <<= 1;
  173. }
  174. buf = PicoIn.sndOut + pos;
  175. while (len-- > 0) {
  176. int16_t getdata = OPLL_calc(opll) * 3;
  177. *buf++ += getdata;
  178. buf += stereo; // only left for stereo, to be mixed to right later
  179. }
  180. }
  181. #endif
  182. void YM2413_regWrite(unsigned data){
  183. OPLL_writeIO(opll,0,data);
  184. }
  185. void YM2413_dataWrite(unsigned data){
  186. OPLL_writeIO(opll,1,data);
  187. }
  188. PICO_INTERNAL void PsndDoFM(int cyc_to)
  189. {
  190. int pos, len;
  191. int stereo = 0;
  192. // Q16, number of samples since last call
  193. len = (cyc_to * Pico.snd.clkl_mult) - Pico.snd.fm_pos;
  194. // don't do this too often (about once every 4 scanlines)
  195. if (len <= PicoIn.sndRate << 4) // Q16, (PicoIn.sndRate << 16) >> 12
  196. return;
  197. // update position and calculate buffer offset and length
  198. pos = (Pico.snd.fm_pos+0x80000) >> 20;
  199. Pico.snd.fm_pos += len;
  200. len = ((Pico.snd.fm_pos+0x80000) >> 20) - pos;
  201. // fill buffer
  202. if (PicoIn.opt & POPT_EN_STEREO) {
  203. stereo = 1;
  204. pos <<= 1;
  205. }
  206. if (PicoIn.opt & POPT_EN_FM)
  207. YM2612UpdateOne(PsndBuffer + pos, len, stereo, 1);
  208. }
  209. // cdda
  210. static void cdda_raw_update(int *buffer, int length)
  211. {
  212. int ret, cdda_bytes, mult = 1;
  213. cdda_bytes = length*4;
  214. if (PicoIn.sndRate <= 22050 + 100) mult = 2;
  215. if (PicoIn.sndRate < 22050 - 100) mult = 4;
  216. cdda_bytes *= mult;
  217. ret = pm_read_audio(cdda_out_buffer, cdda_bytes, Pico_mcd->cdda_stream);
  218. if (ret < cdda_bytes) {
  219. memset((char *)cdda_out_buffer + ret, 0, cdda_bytes - ret);
  220. Pico_mcd->cdda_stream = NULL;
  221. return;
  222. }
  223. // now mix
  224. switch (mult) {
  225. case 1: mix_16h_to_32(buffer, cdda_out_buffer, length*2); break;
  226. case 2: mix_16h_to_32_s1(buffer, cdda_out_buffer, length*2); break;
  227. case 4: mix_16h_to_32_s2(buffer, cdda_out_buffer, length*2); break;
  228. }
  229. }
  230. void cdda_start_play(int lba_base, int lba_offset, int lb_len)
  231. {
  232. if (Pico_mcd->cdda_type == CT_MP3)
  233. {
  234. int pos1024 = 0;
  235. if (lba_offset)
  236. pos1024 = lba_offset * 1024 / lb_len;
  237. mp3_start_play(Pico_mcd->cdda_stream, pos1024);
  238. return;
  239. }
  240. pm_seek(Pico_mcd->cdda_stream, (lba_base + lba_offset) * 2352, SEEK_SET);
  241. if (Pico_mcd->cdda_type == CT_WAV)
  242. {
  243. // skip headers, assume it's 44kHz stereo uncompressed
  244. pm_seek(Pico_mcd->cdda_stream, 44, SEEK_CUR);
  245. }
  246. }
  247. PICO_INTERNAL void PsndClear(void)
  248. {
  249. int len = Pico.snd.len;
  250. if (Pico.snd.len_e_add) len++;
  251. if (PicoIn.opt & POPT_EN_STEREO)
  252. memset32((int *) PicoIn.sndOut, 0, len); // assume PicoIn.sndOut to be aligned
  253. else {
  254. short *out = PicoIn.sndOut;
  255. if ((uintptr_t)out & 2) { *out++ = 0; len--; }
  256. memset32((int *) out, 0, len/2);
  257. if (len & 1) out[len-1] = 0;
  258. }
  259. if (!(PicoIn.opt & POPT_EN_FM))
  260. memset32(PsndBuffer, 0, PicoIn.opt & POPT_EN_STEREO ? len*2 : len);
  261. // drop pos remainder to avoid rounding errors (not entirely correct though)
  262. Pico.snd.dac_pos = Pico.snd.fm_pos = Pico.snd.psg_pos = Pico.snd.ym2413_pos = 0;
  263. }
  264. static int PsndRender(int offset, int length)
  265. {
  266. int *buf32;
  267. int stereo = (PicoIn.opt & 8) >> 3;
  268. int fmlen = ((Pico.snd.fm_pos+0x80000) >> 20);
  269. int daclen = ((Pico.snd.dac_pos+0x80000) >> 20);
  270. int psglen = ((Pico.snd.psg_pos+0x8000) >> 16);
  271. buf32 = PsndBuffer+(offset<<stereo);
  272. pprof_start(sound);
  273. if (PicoIn.AHW & PAHW_PICO) {
  274. PicoPicoPCMUpdate(PicoIn.sndOut+(offset<<stereo), length-offset, stereo);
  275. return length;
  276. }
  277. // Fill up DAC output in case of missing samples (Q16 rounding errors)
  278. if (length-daclen > 0) {
  279. short *dacbuf = PicoIn.sndOut + (daclen << stereo);
  280. Pico.snd.dac_pos += (length-daclen) << 20;
  281. *dacbuf++ += Pico.snd.dac_val2;
  282. if (stereo) dacbuf++;
  283. for (daclen++; length-daclen > 0; daclen++) {
  284. *dacbuf++ += Pico.snd.dac_val;
  285. if (stereo) dacbuf++;
  286. }
  287. Pico.snd.dac_val2 = Pico.snd.dac_val;
  288. }
  289. // Add in parts of the PSG output not yet done
  290. if (length-psglen > 0) {
  291. short *psgbuf = PicoIn.sndOut + (psglen << stereo);
  292. Pico.snd.psg_pos += (length-psglen) << 16;
  293. if (PicoIn.opt & POPT_EN_PSG)
  294. SN76496Update(psgbuf, length-psglen, stereo);
  295. }
  296. // Add in parts of the FM buffer not yet done
  297. if (length-fmlen > 0) {
  298. int *fmbuf = buf32 + ((fmlen-offset) << stereo);
  299. Pico.snd.fm_pos += (length-fmlen) << 20;
  300. if (PicoIn.opt & POPT_EN_FM)
  301. YM2612UpdateOne(fmbuf, length-fmlen, stereo, 1);
  302. }
  303. // CD: PCM sound
  304. if (PicoIn.AHW & PAHW_MCD) {
  305. pcd_pcm_update(buf32, length-offset, stereo);
  306. }
  307. // CD: CDDA audio
  308. // CD mode, cdda enabled, not data track, CDC is reading
  309. if ((PicoIn.AHW & PAHW_MCD) && (PicoIn.opt & POPT_EN_MCD_CDDA)
  310. && Pico_mcd->cdda_stream != NULL
  311. && !(Pico_mcd->s68k_regs[0x36] & 1))
  312. {
  313. // note: only 44, 22 and 11 kHz supported, with forced stereo
  314. if (Pico_mcd->cdda_type == CT_MP3)
  315. mp3_update(buf32, length-offset, stereo);
  316. else
  317. cdda_raw_update(buf32, length-offset);
  318. }
  319. if ((PicoIn.AHW & PAHW_32X) && (PicoIn.opt & POPT_EN_PWM))
  320. p32x_pwm_update(buf32, length-offset, stereo);
  321. // convert + limit to normal 16bit output
  322. PsndMix_32_to_16l(PicoIn.sndOut+(offset<<stereo), buf32, length-offset);
  323. pprof_end(sound);
  324. return length;
  325. }
  326. PICO_INTERNAL void PsndGetSamples(int y)
  327. {
  328. static int curr_pos = 0;
  329. curr_pos = PsndRender(0, Pico.snd.len_use);
  330. if (PicoIn.writeSound)
  331. PicoIn.writeSound(curr_pos * ((PicoIn.opt & POPT_EN_STEREO) ? 4 : 2));
  332. // clear sound buffer
  333. PsndClear();
  334. }
  335. static int PsndRenderMS(int offset, int length)
  336. {
  337. int stereo = (PicoIn.opt & 8) >> 3;
  338. int psglen = ((Pico.snd.psg_pos+0x8000) >> 16);
  339. int ym2413len = ((Pico.snd.ym2413_pos+0x8000) >> 16);
  340. pprof_start(sound);
  341. // Add in parts of the PSG output not yet done
  342. if (length-psglen > 0) {
  343. short *psgbuf = PicoIn.sndOut + (psglen << stereo);
  344. Pico.snd.psg_pos += (length-psglen) << 16;
  345. if (PicoIn.opt & POPT_EN_PSG)
  346. SN76496Update(psgbuf, length-psglen, stereo);
  347. }
  348. if (length-ym2413len > 0) {
  349. short *ym2413buf = PicoIn.sndOut + (ym2413len << stereo);
  350. Pico.snd.ym2413_pos += (length-ym2413len) << 16;
  351. int len = (length-ym2413len);
  352. if (PicoIn.opt & POPT_EN_YM2413){
  353. while (len-- > 0) {
  354. int16_t getdata = OPLL_calc(opll) * 3;
  355. *ym2413buf += getdata;
  356. ym2413buf += 1<<stereo;
  357. }
  358. }
  359. }
  360. // upmix to "stereo" if needed
  361. if (PicoIn.opt & POPT_EN_STEREO) {
  362. int i;
  363. short *p;
  364. for (i = length, p = (short *)PicoIn.sndOut; i > 0; i--, p+=2)
  365. *(p + 1) = *p;
  366. }
  367. pprof_end(sound);
  368. return length;
  369. }
  370. PICO_INTERNAL void PsndGetSamplesMS(int y)
  371. {
  372. static int curr_pos = 0;
  373. curr_pos = PsndRenderMS(0, Pico.snd.len_use);
  374. if (PicoIn.writeSound != NULL)
  375. PicoIn.writeSound(curr_pos * ((PicoIn.opt & POPT_EN_STEREO) ? 4 : 2));
  376. PsndClear();
  377. }
  378. // vim:shiftwidth=2:ts=2:expandtab