sound.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. // This is part of Pico Library
  2. // (c) Copyright 2004 Dave, All rights reserved.
  3. // (c) Copyright 2006,2007 notaz, All rights reserved.
  4. // Free for non-commercial use.
  5. // For commercial use, separate licencing terms must be obtained.
  6. #include <string.h>
  7. #include "ym2612.h"
  8. #include "sn76496.h"
  9. #include "../pico_int.h"
  10. #include "../cd/pcm.h"
  11. #include "mix.h"
  12. void (*PsndMix_32_to_16l)(short *dest, int *src, int count) = mix_32_to_16l_stereo;
  13. // master int buffer to mix to
  14. static int PsndBuffer[2*(44100+100)/50];
  15. // dac
  16. static unsigned short dac_info[312+4]; // pppppppp ppppllll, p - pos in buff, l - length to write for this sample
  17. // cdda output buffer
  18. short cdda_out_buffer[2*1152];
  19. // for Pico
  20. int PsndRate=0;
  21. int PsndLen=0; // number of mono samples, multiply by 2 for stereo
  22. int PsndLen_exc_add=0; // this is for non-integer sample counts per line, eg. 22050/60
  23. int PsndLen_exc_cnt=0;
  24. int PsndDacLine=0;
  25. short *PsndOut=NULL; // PCM data buffer
  26. // timers
  27. int timer_a_next_oflow, timer_a_step; // in z80 cycles
  28. int timer_b_next_oflow, timer_b_step;
  29. // sn76496
  30. extern int *sn76496_regs;
  31. static void dac_recalculate(void)
  32. {
  33. int i, dac_cnt, pos, len, lines = Pico.m.pal ? 312 : 262, mid = Pico.m.pal ? 68 : 93;
  34. if (PsndLen <= lines)
  35. {
  36. // shrinking algo
  37. dac_cnt = -PsndLen;
  38. len=1; pos=0;
  39. dac_info[225] = 1;
  40. for(i=226; i != 225; i++)
  41. {
  42. if (i >= lines) i = 0;
  43. len = 0;
  44. if(dac_cnt < 0) {
  45. len=1;
  46. pos++;
  47. dac_cnt += lines;
  48. }
  49. dac_cnt -= PsndLen;
  50. dac_info[i] = (pos<<4)|len;
  51. }
  52. }
  53. else
  54. {
  55. // stretching
  56. dac_cnt = PsndLen;
  57. pos=0;
  58. for(i = 225; i != 224; i++)
  59. {
  60. if (i >= lines) i = 0;
  61. len=0;
  62. while(dac_cnt >= 0) {
  63. dac_cnt -= lines;
  64. len++;
  65. }
  66. if (i == mid) // midpoint
  67. while(pos+len < PsndLen/2) {
  68. dac_cnt -= lines;
  69. len++;
  70. }
  71. dac_cnt += PsndLen;
  72. dac_info[i] = (pos<<4)|len;
  73. pos+=len;
  74. }
  75. // last sample
  76. for(len = 0, i = pos; i < PsndLen; i++) len++;
  77. if (PsndLen_exc_add) len++;
  78. dac_info[224] = (pos<<4)|len;
  79. }
  80. mid = (dac_info[lines-1] & 0xfff0) + ((dac_info[lines-1] & 0xf) << 4);
  81. for (i = lines; i < sizeof(dac_info) / sizeof(dac_info[0]); i++)
  82. dac_info[i] = mid;
  83. //for(i=len=0; i < lines; i++) {
  84. // printf("%03i : %03i : %i\n", i, dac_info[i]>>4, dac_info[i]&0xf);
  85. // len+=dac_info[i]&0xf;
  86. //}
  87. //printf("rate is %i, len %f\n", PsndRate, (double)PsndRate/(Pico.m.pal ? 50.0 : 60.0));
  88. //printf("len total: %i, last pos: %i\n", len, pos);
  89. //exit(8);
  90. }
  91. PICO_INTERNAL void PsndReset(void)
  92. {
  93. // PsndRerate calls YM2612Init, which also resets
  94. PsndRerate(0);
  95. timers_reset();
  96. }
  97. // to be called after changing sound rate or chips
  98. void PsndRerate(int preserve_state)
  99. {
  100. void *state = NULL;
  101. int target_fps = Pico.m.pal ? 50 : 60;
  102. // not all rates are supported in MCD mode due to mp3 decoder limitations
  103. if (PicoAHW & PAHW_MCD) {
  104. if (!(11025-100 <= PsndRate && PsndRate <= 11025+100) &&
  105. !(22050-100 <= PsndRate && PsndRate <= 22050+100) &&
  106. !(44100-100 <= PsndRate && PsndRate <= 44100+100))
  107. PsndRate = 22050;
  108. PicoOpt |= POPT_EN_STEREO; // force stereo
  109. }
  110. if (preserve_state) {
  111. state = malloc(0x204);
  112. if (state == NULL) return;
  113. ym2612_pack_state();
  114. memcpy(state, YM2612GetRegs(), 0x204);
  115. }
  116. YM2612Init(Pico.m.pal ? OSC_PAL/7 : OSC_NTSC/7, PsndRate);
  117. if (preserve_state) {
  118. // feed it back it's own registers, just like after loading state
  119. memcpy(YM2612GetRegs(), state, 0x204);
  120. ym2612_unpack_state();
  121. if ((PicoAHW & PAHW_MCD) && !(Pico_mcd->s68k_regs[0x36] & 1) && (Pico_mcd->scd.Status_CDC & 1))
  122. cdda_start_play();
  123. }
  124. if (preserve_state) memcpy(state, sn76496_regs, 28*4); // remember old state
  125. SN76496_init(Pico.m.pal ? OSC_PAL/15 : OSC_NTSC/15, PsndRate);
  126. if (preserve_state) memcpy(sn76496_regs, state, 28*4); // restore old state
  127. if (state)
  128. free(state);
  129. // calculate PsndLen
  130. PsndLen=PsndRate / target_fps;
  131. PsndLen_exc_add=((PsndRate - PsndLen*target_fps)<<16) / target_fps;
  132. PsndLen_exc_cnt=0;
  133. // recalculate dac info
  134. dac_recalculate();
  135. if (PicoAHW & PAHW_MCD)
  136. pcm_set_rate(PsndRate);
  137. // clear all buffers
  138. memset32(PsndBuffer, 0, sizeof(PsndBuffer)/4);
  139. memset(cdda_out_buffer, 0, sizeof(cdda_out_buffer));
  140. if (PsndOut)
  141. PsndClear();
  142. // set mixer
  143. PsndMix_32_to_16l = (PicoOpt & POPT_EN_STEREO) ? mix_32_to_16l_stereo : mix_32_to_16_mono;
  144. if (PicoAHW & PAHW_PICO)
  145. PicoReratePico();
  146. }
  147. PICO_INTERNAL void PsndDoDAC(int line_to)
  148. {
  149. int pos, pos1, len;
  150. int dout = ym2612.dacout;
  151. int line_from = PsndDacLine;
  152. PsndDacLine = line_to + 1;
  153. pos =dac_info[line_from]>>4;
  154. pos1=dac_info[line_to];
  155. len = ((pos1>>4)-pos) + (pos1&0xf);
  156. if (!len) return;
  157. if (PicoOpt & POPT_EN_STEREO) {
  158. short *d = PsndOut + pos*2;
  159. for (; len > 0; len--, d+=2) *d = dout;
  160. } else {
  161. short *d = PsndOut + pos;
  162. for (; len > 0; len--, d++) *d = dout;
  163. }
  164. #if 0
  165. if (do_pcm) {
  166. int *d = PsndBuffer;
  167. d += (PicoOpt&8) ? pos*2 : pos;
  168. pcm_update(d, len, 1);
  169. }
  170. #endif
  171. }
  172. // cdda
  173. static pm_file *cdda_stream = NULL;
  174. static void cdda_raw_update(int *buffer, int length)
  175. {
  176. int ret, cdda_bytes, mult = 1;
  177. if (cdda_stream == NULL)
  178. return;
  179. cdda_bytes = length*4;
  180. if (PsndRate <= 22050 + 100) mult = 2;
  181. if (PsndRate < 22050 - 100) mult = 4;
  182. cdda_bytes *= mult;
  183. ret = pm_read(cdda_out_buffer, cdda_bytes, cdda_stream);
  184. if (ret < cdda_bytes) {
  185. memset((char *)cdda_out_buffer + ret, 0, cdda_bytes - ret);
  186. cdda_stream = NULL;
  187. return;
  188. }
  189. // now mix
  190. switch (mult) {
  191. case 1: mix_16h_to_32(buffer, cdda_out_buffer, length*2); break;
  192. case 2: mix_16h_to_32_s1(buffer, cdda_out_buffer, length*2); break;
  193. case 4: mix_16h_to_32_s2(buffer, cdda_out_buffer, length*2); break;
  194. }
  195. }
  196. PICO_INTERNAL void cdda_start_play(void)
  197. {
  198. int lba_offset, index, lba_length, i;
  199. elprintf(EL_STATUS, "cdda play track #%i", Pico_mcd->scd.Cur_Track);
  200. index = Pico_mcd->scd.Cur_Track - 1;
  201. lba_offset = Pico_mcd->scd.Cur_LBA - Track_to_LBA(index + 1);
  202. if (lba_offset < 0) lba_offset = 0;
  203. lba_offset += Pico_mcd->TOC.Tracks[index].Offset;
  204. // find the actual file for this track
  205. for (i = index; i > 0; i--)
  206. if (Pico_mcd->TOC.Tracks[i].F != NULL) break;
  207. if (Pico_mcd->TOC.Tracks[i].F == NULL) {
  208. elprintf(EL_STATUS|EL_ANOMALY, "no track?!");
  209. return;
  210. }
  211. if (Pico_mcd->TOC.Tracks[i].ftype == TYPE_MP3)
  212. {
  213. int pos1024 = 0;
  214. lba_length = Pico_mcd->TOC.Tracks[i].Length;
  215. for (i++; i < Pico_mcd->TOC.Last_Track; i++) {
  216. if (Pico_mcd->TOC.Tracks[i].F != NULL) break;
  217. lba_length += Pico_mcd->TOC.Tracks[i].Length;
  218. }
  219. if (lba_offset)
  220. pos1024 = lba_offset * 1024 / lba_length;
  221. mp3_start_play(Pico_mcd->TOC.Tracks[index].F, pos1024);
  222. return;
  223. }
  224. cdda_stream = Pico_mcd->TOC.Tracks[i].F;
  225. PicoCDBufferFlush(); // buffering relies on fp not being touched
  226. pm_seek(cdda_stream, lba_offset * 2352, SEEK_SET);
  227. if (Pico_mcd->TOC.Tracks[i].ftype == TYPE_WAV)
  228. {
  229. // skip headers, assume it's 44kHz stereo uncompressed
  230. pm_seek(cdda_stream, 44, SEEK_CUR);
  231. }
  232. }
  233. PICO_INTERNAL void PsndClear(void)
  234. {
  235. int len = PsndLen;
  236. if (PsndLen_exc_add) len++;
  237. if (PicoOpt & POPT_EN_STEREO)
  238. memset32((int *) PsndOut, 0, len); // assume PsndOut to be aligned
  239. else {
  240. short *out = PsndOut;
  241. if ((long)out & 2) { *out++ = 0; len--; }
  242. memset32((int *) out, 0, len/2);
  243. if (len & 1) out[len-1] = 0;
  244. }
  245. }
  246. static int PsndRender(int offset, int length)
  247. {
  248. int buf32_updated = 0;
  249. int *buf32 = PsndBuffer+offset;
  250. int stereo = (PicoOpt & 8) >> 3;
  251. // emulating CD && PCM option enabled && PCM chip on && have enabled channels
  252. int do_pcm = (PicoAHW & PAHW_MCD) && (PicoOpt&POPT_EN_MCD_PCM) &&
  253. (Pico_mcd->pcm.control & 0x80) && Pico_mcd->pcm.enabled;
  254. offset <<= stereo;
  255. pprof_start(sound);
  256. #if !SIMPLE_WRITE_SOUND
  257. if (offset == 0) { // should happen once per frame
  258. // compensate for float part of PsndLen
  259. PsndLen_exc_cnt += PsndLen_exc_add;
  260. if (PsndLen_exc_cnt >= 0x10000) {
  261. PsndLen_exc_cnt -= 0x10000;
  262. length++;
  263. }
  264. }
  265. #endif
  266. // PSG
  267. if (PicoOpt & POPT_EN_PSG)
  268. SN76496Update(PsndOut+offset, length, stereo);
  269. if (PicoAHW & PAHW_PICO) {
  270. PicoPicoPCMUpdate(PsndOut+offset, length, stereo);
  271. return length;
  272. }
  273. // Add in the stereo FM buffer
  274. if (PicoOpt & POPT_EN_FM) {
  275. buf32_updated = YM2612UpdateOne(buf32, length, stereo, 1);
  276. } else
  277. memset32(buf32, 0, length<<stereo);
  278. //printf("active_chs: %02x\n", buf32_updated);
  279. (void)buf32_updated;
  280. // CD: PCM sound
  281. if (do_pcm) {
  282. pcm_update(buf32, length, stereo);
  283. //buf32_updated = 1;
  284. }
  285. // CD: CDDA audio
  286. // CD mode, cdda enabled, not data track, CDC is reading
  287. if ((PicoAHW & PAHW_MCD) && (PicoOpt & POPT_EN_MCD_CDDA) &&
  288. !(Pico_mcd->s68k_regs[0x36] & 1) && (Pico_mcd->scd.Status_CDC & 1))
  289. {
  290. // note: only 44, 22 and 11 kHz supported, with forced stereo
  291. int index = Pico_mcd->scd.Cur_Track - 1;
  292. if (Pico_mcd->TOC.Tracks[index].ftype == TYPE_MP3)
  293. mp3_update(buf32, length, stereo);
  294. else
  295. cdda_raw_update(buf32, length);
  296. }
  297. if ((PicoAHW & PAHW_32X) && (PicoOpt & POPT_EN_PWM))
  298. p32x_pwm_update(buf32, length, stereo);
  299. // convert + limit to normal 16bit output
  300. PsndMix_32_to_16l(PsndOut+offset, buf32, length);
  301. pprof_end(sound);
  302. return length;
  303. }
  304. // to be called on 224 or line_sample scanlines only
  305. PICO_INTERNAL void PsndGetSamples(int y)
  306. {
  307. #if SIMPLE_WRITE_SOUND
  308. if (y != 224) return;
  309. PsndRender(0, PsndLen);
  310. if (PicoWriteSound)
  311. PicoWriteSound(PsndLen * ((PicoOpt & POPT_EN_STEREO) ? 4 : 2));
  312. PsndClear();
  313. #else
  314. static int curr_pos = 0;
  315. if (y == 224)
  316. {
  317. if (emustatus & 2)
  318. curr_pos += PsndRender(curr_pos, PsndLen-PsndLen/2);
  319. else curr_pos = PsndRender(0, PsndLen);
  320. if (emustatus & 1)
  321. emustatus |= 2;
  322. else emustatus &= ~2;
  323. if (PicoWriteSound)
  324. PicoWriteSound(curr_pos * ((PicoOpt & POPT_EN_STEREO) ? 4 : 2));
  325. // clear sound buffer
  326. PsndClear();
  327. }
  328. else if (emustatus & 3) {
  329. emustatus|= 2;
  330. emustatus&=~1;
  331. curr_pos = PsndRender(0, PsndLen/2);
  332. }
  333. #endif
  334. }
  335. PICO_INTERNAL void PsndGetSamplesMS(void)
  336. {
  337. int stereo = (PicoOpt & 8) >> 3;
  338. int length = PsndLen;
  339. #if !SIMPLE_WRITE_SOUND
  340. // compensate for float part of PsndLen
  341. PsndLen_exc_cnt += PsndLen_exc_add;
  342. if (PsndLen_exc_cnt >= 0x10000) {
  343. PsndLen_exc_cnt -= 0x10000;
  344. length++;
  345. }
  346. #endif
  347. // PSG
  348. if (PicoOpt & POPT_EN_PSG)
  349. SN76496Update(PsndOut, length, stereo);
  350. // upmix to "stereo" if needed
  351. if (stereo) {
  352. int i, *p;
  353. for (i = length, p = (void *)PsndOut; i > 0; i--, p++)
  354. *p |= *p << 16;
  355. }
  356. if (PicoWriteSound != NULL)
  357. PicoWriteSound(length * ((PicoOpt & POPT_EN_STEREO) ? 4 : 2));
  358. PsndClear();
  359. }