An audio player for macOS 10.8 and newer. https://kode54.net/cog
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

447 lines
17KB

  1. #include "coding.h"
  2. /* PS-ADPCM table, defined as rational numbers (as in the spec) */
  3. static const float ps_adpcm_coefs_f[16][2] = {
  4. { 0.0 , 0.0 }, //{ 0.0 , 0.0 },
  5. { 0.9375 , 0.0 }, //{ 60.0 / 64.0 , 0.0 },
  6. { 1.796875 , -0.8125 }, //{ 115.0 / 64.0 , -52.0 / 64.0 },
  7. { 1.53125 , -0.859375 }, //{ 98.0 / 64.0 , -55.0 / 64.0 },
  8. { 1.90625 , -0.9375 }, //{ 122.0 / 64.0 , -60.0 / 64.0 },
  9. /* extended table used in few PS3 games, found in ELFs */
  10. { 0.46875 , -0.0 }, //{ 30.0 / 64.0 , -0.0 / 64.0 },
  11. { 0.8984375 , -0.40625 }, //{ 57.5 / 64.0 , -26.0 / 64.0 },
  12. { 0.765625 , -0.4296875 }, //{ 49.0 / 64.0 , -27.5 / 64.0 },
  13. { 0.953125 , -0.46875 }, //{ 61.0 / 64.0 , -30.0 / 64.0 },
  14. { 0.234375 , -0.0 }, //{ 15.0 / 64.0 , -0.0 / 64.0 },
  15. { 0.44921875, -0.203125 }, //{ 28.75/ 64.0 , -13.0 / 64.0 },
  16. { 0.3828125 , -0.21484375}, //{ 24.5 / 64.0 , -13.75/ 64.0 },
  17. { 0.4765625 , -0.234375 }, //{ 30.5 / 64.0 , -15.0 / 64.0 },
  18. { 0.5 , -0.9375 }, //{ 32.0 / 64.0 , -60.0 / 64.0 },
  19. { 0.234375 , -0.9375 }, //{ 15.0 / 64.0 , -60.0 / 64.0 },
  20. { 0.109375 , -0.9375 }, //{ 7.0 / 64.0 , -60.0 / 64.0 },
  21. };
  22. /* PS-ADPCM table, defined as spec_coef*64 (for int implementations) */
  23. static const int ps_adpcm_coefs_i[5][2] = {
  24. { 0 , 0 },
  25. { 60 , 0 },
  26. { 115 , -52 },
  27. { 98 , -55 },
  28. { 122 , -60 },
  29. #if 0
  30. /* extended table from PPSSPP (PSP emu), found by tests (unused?) */
  31. { 0 , 0 },
  32. { 0 , 0 },
  33. { 52 , 0 },
  34. { 55 , -2 },
  35. { 60 ,-125 },
  36. { 0 , 0 },
  37. { 0 , -91 },
  38. { 0 , 0 },
  39. { 2 ,-216 },
  40. { 125 , -6 },
  41. { 0 ,-151 },
  42. #endif
  43. };
  44. /* Decodes Sony's PS-ADPCM (sometimes called SPU-ADPCM or VAG, just "ADPCM" in the SDK docs).
  45. * Very similar to XA ADPCM (see xa_decoder for extended info).
  46. *
  47. * Some official PC tools decode using float coefs (from the spec), as does this code, but
  48. * consoles/games/libs would vary (PS1 could do it in hardware using BRR/XA's logic, FMOD may
  49. * depend on platform, PS3 games use floats, etc). There are rounding diffs between implementations.
  50. */
  51. /* standard PS-ADPCM (float math version) */
  52. void decode_psx(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int is_badflags, int config) {
  53. uint8_t frame[0x10] = {0};
  54. off_t frame_offset;
  55. int i, frames_in, sample_count = 0;
  56. size_t bytes_per_frame, samples_per_frame;
  57. uint8_t coef_index, shift_factor, flag;
  58. int32_t hist1 = stream->adpcm_history1_32;
  59. int32_t hist2 = stream->adpcm_history2_32;
  60. int extended_mode = (config == 1);
  61. /* external interleave (fixed size), mono */
  62. bytes_per_frame = 0x10;
  63. samples_per_frame = (bytes_per_frame - 0x02) * 2; /* always 28 */
  64. frames_in = first_sample / samples_per_frame;
  65. first_sample = first_sample % samples_per_frame;
  66. /* parse frame header */
  67. frame_offset = stream->offset + bytes_per_frame * frames_in;
  68. read_streamfile(frame, frame_offset, bytes_per_frame, stream->streamfile); /* ignore EOF errors */
  69. coef_index = (frame[0] >> 4) & 0xf;
  70. shift_factor = (frame[0] >> 0) & 0xf;
  71. flag = frame[1]; /* only lower nibble needed */
  72. /* upper filters only used in few PS3 games, normally 0 */
  73. if (!extended_mode) {
  74. VGM_ASSERT_ONCE(coef_index > 5 || shift_factor > 12, "PS-ADPCM: incorrect coefs/shift at %x\n", (uint32_t)frame_offset);
  75. if (coef_index > 5)
  76. coef_index = 0;
  77. if (shift_factor > 12)
  78. shift_factor = 9; /* supposedly, from Nocash PSX docs */
  79. }
  80. if (is_badflags) /* some games store garbage or extra internal logic in the flags, must be ignored */
  81. flag = 0;
  82. VGM_ASSERT_ONCE(flag > 7,"PS-ADPCM: unknown flag at %x\n", (uint32_t)frame_offset); /* meta should use PSX-badflags */
  83. /* decode nibbles */
  84. for (i = first_sample; i < first_sample + samples_to_do; i++) {
  85. int32_t sample = 0;
  86. if (flag < 0x07) { /* with flag 0x07 decoded sample must be 0 */
  87. uint8_t nibbles = frame[0x02 + i/2];
  88. sample = i&1 ? /* low nibble first */
  89. (nibbles >> 4) & 0x0f :
  90. (nibbles >> 0) & 0x0f;
  91. sample = (int16_t)((sample << 12) & 0xf000) >> shift_factor; /* 16b sign extend + scale */
  92. sample = (int32_t)(sample + ps_adpcm_coefs_f[coef_index][0]*hist1 + ps_adpcm_coefs_f[coef_index][1]*hist2);
  93. sample = clamp16(sample);
  94. }
  95. outbuf[sample_count] = sample;
  96. sample_count += channelspacing;
  97. hist2 = hist1;
  98. hist1 = sample;
  99. }
  100. stream->adpcm_history1_32 = hist1;
  101. stream->adpcm_history2_32 = hist2;
  102. }
  103. /* PS-ADPCM with configurable frame size and no flag (int math version).
  104. * Found in some PC/PS3 games (FF XI in sizes 0x3/0x5/0x9/0x41, Afrika in size 0x4, Blur/James Bond in size 0x33, etc).
  105. *
  106. * Uses int/float math depending on config (PC/other code may be int, PS3 float). */
  107. void decode_psx_configurable(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int frame_size, int config) {
  108. uint8_t frame[0x50] = {0};
  109. off_t frame_offset;
  110. int i, frames_in, sample_count = 0;
  111. size_t bytes_per_frame, samples_per_frame;
  112. uint8_t coef_index, shift_factor;
  113. int32_t hist1 = stream->adpcm_history1_32;
  114. int32_t hist2 = stream->adpcm_history2_32;
  115. int extended_mode = (config == 1);
  116. int float_mode = (config == 1);
  117. /* external interleave (variable size), mono */
  118. bytes_per_frame = frame_size;
  119. samples_per_frame = (bytes_per_frame - 0x01) * 2;
  120. frames_in = first_sample / samples_per_frame;
  121. first_sample = first_sample % samples_per_frame;
  122. /* parse frame header */
  123. frame_offset = stream->offset + bytes_per_frame * frames_in;
  124. read_streamfile(frame, frame_offset, bytes_per_frame, stream->streamfile); /* ignore EOF errors */
  125. coef_index = (frame[0] >> 4) & 0xf;
  126. shift_factor = (frame[0] >> 0) & 0xf;
  127. /* upper filters only used in few PS3 games, normally 0 */
  128. if (!extended_mode) {
  129. VGM_ASSERT_ONCE(coef_index > 5 || shift_factor > 12, "PS-ADPCM: incorrect coefs/shift at %x\n", (uint32_t)frame_offset);
  130. if (coef_index > 5)
  131. coef_index = 0;
  132. if (shift_factor > 12)
  133. shift_factor = 9; /* supposedly, from Nocash PSX docs */
  134. }
  135. /* decode nibbles */
  136. for (i = first_sample; i < first_sample + samples_to_do; i++) {
  137. int32_t sample = 0;
  138. uint8_t nibbles = frame[0x01 + i/2];
  139. sample = i&1 ? /* low nibble first */
  140. (nibbles >> 4) & 0x0f :
  141. (nibbles >> 0) & 0x0f;
  142. sample = (int16_t)((sample << 12) & 0xf000) >> shift_factor; /* 16b sign extend + scale */
  143. sample = float_mode ?
  144. (int32_t)(sample + ps_adpcm_coefs_f[coef_index][0]*hist1 + ps_adpcm_coefs_f[coef_index][1]*hist2) :
  145. sample + ((ps_adpcm_coefs_i[coef_index][0]*hist1 + ps_adpcm_coefs_i[coef_index][1]*hist2) >> 6);
  146. sample = clamp16(sample);
  147. outbuf[sample_count] = sample;
  148. sample_count += channelspacing;
  149. hist2 = hist1;
  150. hist1 = sample;
  151. }
  152. stream->adpcm_history1_32 = hist1;
  153. stream->adpcm_history2_32 = hist2;
  154. }
  155. /* PS-ADPCM from Pivotal games, exactly like psx_cfg but with float math (reverse engineered from the exe) */
  156. void decode_psx_pivotal(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int frame_size) {
  157. uint8_t frame[0x50] = {0};
  158. off_t frame_offset;
  159. int i, frames_in, sample_count = 0;
  160. size_t bytes_per_frame, samples_per_frame;
  161. uint8_t coef_index, shift_factor;
  162. int32_t hist1 = stream->adpcm_history1_32;
  163. int32_t hist2 = stream->adpcm_history2_32;
  164. float scale;
  165. /* external interleave (variable size), mono */
  166. bytes_per_frame = frame_size;
  167. samples_per_frame = (bytes_per_frame - 0x01) * 2;
  168. frames_in = first_sample / samples_per_frame;
  169. first_sample = first_sample % samples_per_frame;
  170. /* parse frame header */
  171. frame_offset = stream->offset + bytes_per_frame * frames_in;
  172. read_streamfile(frame, frame_offset, bytes_per_frame, stream->streamfile); /* ignore EOF errors */
  173. coef_index = (frame[0] >> 4) & 0xf;
  174. shift_factor = (frame[0] >> 0) & 0xf;
  175. VGM_ASSERT_ONCE(coef_index > 5 || shift_factor > 12, "PS-ADPCM-piv: incorrect coefs/shift\n");
  176. if (coef_index > 5) /* just in case */
  177. coef_index = 5;
  178. if (shift_factor > 12) /* same */
  179. shift_factor = 12;
  180. scale = (float)(1.0 / (double)(1 << shift_factor));
  181. /* decode nibbles */
  182. for (i = first_sample; i < first_sample + samples_to_do; i++) {
  183. int32_t sample = 0;
  184. uint8_t nibbles = frame[0x01 + i/2];
  185. sample = !(i&1) ? /* low nibble first */
  186. (nibbles >> 0) & 0x0f :
  187. (nibbles >> 4) & 0x0f;
  188. sample = (int16_t)((sample << 12) & 0xf000); /* 16b sign extend + default scale */
  189. sample = sample*scale + ps_adpcm_coefs_f[coef_index][0]*hist1 + ps_adpcm_coefs_f[coef_index][1]*hist2; /* actually substracts negative coefs but whatevs */
  190. outbuf[sample_count] = clamp16(sample);
  191. sample_count += channelspacing;
  192. hist2 = hist1;
  193. hist1 = sample; /* not clamped but no difference */
  194. }
  195. stream->adpcm_history1_32 = hist1;
  196. stream->adpcm_history2_32 = hist2;
  197. }
  198. /* Find loop samples in PS-ADPCM data and return if the file loops.
  199. *
  200. * PS-ADPCM/VAG has optional bit flags that control looping in the SPU.
  201. * Possible combinations (as usually defined in Sony's docs):
  202. * - 0x0 (0000): Normal decode
  203. * - 0x1 (0001): End marker (last frame)
  204. * - 0x2 (0010): Loop region (marks files that *may* have loop flags somewhere)
  205. * - 0x3 (0011): Loop end (jump to loop address)
  206. * - 0x4 (0100): Start marker
  207. * - 0x5 (0101): Same as 0x07? Extremely rare [Blood Omen: Legacy of Kain (PS1)]
  208. * - 0x6 (0110): Loop start (save loop address)
  209. * - 0x7 (0111): End marker and don't decode
  210. * - 0x8+(1NNN): Not valid
  211. */
  212. static int ps_find_loop_offsets_internal(STREAMFILE *sf, off_t start_offset, size_t data_size, int channels, size_t interleave, int32_t * p_loop_start, int32_t * p_loop_end, int config) {
  213. int num_samples = 0, loop_start = 0, loop_end = 0;
  214. int loop_start_found = 0, loop_end_found = 0;
  215. off_t offset = start_offset;
  216. off_t max_offset = start_offset + data_size;
  217. size_t interleave_consumed = 0;
  218. int detect_full_loops = config & 1;
  219. if (data_size == 0 || channels == 0 || (channels > 1 && interleave == 0))
  220. return 0;
  221. while (offset < max_offset) {
  222. uint8_t flag = read_u8(offset+0x01, sf) & 0x0F; /* lower nibble only (for HEVAG) */
  223. /* theoretically possible and would use last 0x06 */
  224. VGM_ASSERT_ONCE(loop_start_found && flag == 0x06, "PS LOOPS: multiple loop start found at %x\n", (uint32_t)offset);
  225. if (flag == 0x06 && !loop_start_found) {
  226. loop_start = num_samples; /* loop start before this frame */
  227. loop_start_found = 1;
  228. }
  229. if (flag == 0x03 && !loop_end) {
  230. loop_end = num_samples + 28; /* loop end after this frame */
  231. loop_end_found = 1;
  232. /* ignore strange case in Commandos (PS2), has many loop starts and ends */
  233. if (channels == 1
  234. && offset + 0x10 < max_offset
  235. && (read_u8(offset + 0x11, sf) & 0x0F) == 0x06) {
  236. loop_end = 0;
  237. loop_end_found = 0;
  238. }
  239. if (loop_start_found && loop_end_found)
  240. break;
  241. }
  242. /* hack for some games that don't have loop points but do full loops,
  243. * if there is a "partial" 0x07 end flag pretend it wants to loop
  244. * (sometimes this will loop non-looping tracks, and won't loop all repeating files)
  245. * seems only used in Ratchet & Clank series and Ecco the Dolphin */
  246. if (flag == 0x01 && detect_full_loops) {
  247. static const uint8_t eof[0x10] = {0xFF,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
  248. uint8_t buf[0x10];
  249. uint8_t hdr = read_u8(offset + 0x00, sf);
  250. int read = read_streamfile(buf, offset+0x10, sizeof(buf), sf);
  251. if (read > 0
  252. && buf[0] != 0x00 /* ignore blank frame */
  253. && buf[0] != 0x0c /* ignore silent frame */
  254. && buf[0] != 0x3c /* ignore some L-R tracks with different end flags */
  255. ) {
  256. /* assume full loop with repeated frame header and null frame */
  257. if (hdr == buf[0] && memcmp(buf+1, eof+1, sizeof(buf) - 1) == 0) {
  258. loop_start = 28; /* skip first frame as it's null in PS-ADPCM */
  259. loop_end = num_samples + 28; /* loop end after this frame */
  260. loop_start_found = 1;
  261. loop_end_found = 1;
  262. //;VGM_LOG("PS LOOPS: full loop found\n");
  263. break;
  264. }
  265. }
  266. }
  267. num_samples += 28;
  268. offset += 0x10;
  269. /* skip other channels */
  270. interleave_consumed += 0x10;
  271. if (interleave_consumed == interleave) {
  272. interleave_consumed = 0;
  273. offset += interleave*(channels - 1);
  274. }
  275. }
  276. VGM_ASSERT(loop_start_found && !loop_end_found, "PS LOOPS: found loop start but not loop end\n");
  277. VGM_ASSERT(loop_end_found && !loop_start_found, "PS LOOPS: found loop end but not loop start\n");
  278. //;VGM_LOG("PS LOOPS: start=%i, end=%i\n", loop_start, loop_end);
  279. /* From Sony's docs: if only loop_end is set loop back to "phoneme region start", but in practice doesn't */
  280. if (loop_start_found && loop_end_found) {
  281. *p_loop_start = loop_start;
  282. *p_loop_end = loop_end;
  283. return 1;
  284. }
  285. return 0; /* no loop */
  286. }
  287. int ps_find_loop_offsets(STREAMFILE *sf, off_t start_offset, size_t data_size, int channels, size_t interleave, int32_t *p_loop_start, int32_t *p_loop_end) {
  288. return ps_find_loop_offsets_internal(sf, start_offset, data_size, channels, interleave, p_loop_start, p_loop_end, 0);
  289. }
  290. int ps_find_loop_offsets_full(STREAMFILE *sf, off_t start_offset, size_t data_size, int channels, size_t interleave, int32_t *p_loop_start, int32_t *p_loop_end) {
  291. return ps_find_loop_offsets_internal(sf, start_offset, data_size, channels, interleave, p_loop_start, p_loop_end, 1);
  292. }
  293. size_t ps_find_padding(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, size_t interleave, int discard_empty) {
  294. off_t min_offset, offset;
  295. size_t frame_size = 0x10;
  296. size_t padding_size = 0;
  297. size_t interleave_consumed = 0;
  298. if (data_size == 0 || channels == 0 || (channels > 0 && interleave == 0))
  299. return 0;
  300. offset = start_offset + data_size;
  301. /* in rare cases (ex. Gitaroo Man) channels have inconsistent empty padding, use first as guide */
  302. offset = offset - interleave * (channels - 1);
  303. /* some files have padding spanning multiple interleave blocks */
  304. min_offset = start_offset; //offset - interleave;
  305. while (offset > min_offset) {
  306. uint32_t f1,f2,f3,f4;
  307. uint8_t flag;
  308. int is_empty = 0;
  309. offset -= frame_size;
  310. f1 = read_32bitBE(offset+0x00,streamFile);
  311. f2 = read_32bitBE(offset+0x04,streamFile);
  312. f3 = read_32bitBE(offset+0x08,streamFile);
  313. f4 = read_32bitBE(offset+0x0c,streamFile);
  314. flag = (f1 >> 16) & 0xFF;
  315. if (f1 == 0 && f2 == 0 && f3 == 0 && f4 == 0)
  316. is_empty = 1;
  317. if (!is_empty && discard_empty) {
  318. if (flag == 0x07 || flag == 0x77)
  319. is_empty = 1; /* 'discard frame' flag */
  320. else if ((f1 & 0xFF00FFFF) == 0 && f2 == 0 && f3 == 0 && f4 == 0)
  321. is_empty = 1; /* silent with flags (typical for looping files) */
  322. else if ((f1 & 0xFF00FFFF) == 0x0C000000 && f2 == 0 && f3 == 0 && f4 == 0)
  323. is_empty = 1; /* silent (maybe shouldn't ignore flag 0x03?) */
  324. else if ((f1 & 0x0000FFFF) == 0x00007777 && f2 == 0x77777777 && f3 ==0x77777777 && f4 == 0x77777777)
  325. is_empty = 1; /* silent-ish */
  326. }
  327. if (!is_empty)
  328. break;
  329. padding_size += frame_size * channels;
  330. /* skip other channels */
  331. interleave_consumed += 0x10;
  332. if (interleave_consumed == interleave) {
  333. interleave_consumed = 0;
  334. offset -= interleave*(channels - 1);
  335. }
  336. }
  337. return padding_size;
  338. }
  339. size_t ps_bytes_to_samples(size_t bytes, int channels) {
  340. if (channels <= 0) return 0;
  341. return bytes / channels / 0x10 * 28;
  342. }
  343. size_t ps_cfg_bytes_to_samples(size_t bytes, size_t frame_size, int channels) {
  344. int samples_per_frame = (frame_size - 0x01) * 2;
  345. return bytes / channels / frame_size * samples_per_frame;
  346. }
  347. /* test PS-ADPCM frames for correctness */
  348. int ps_check_format(STREAMFILE *streamFile, off_t offset, size_t max) {
  349. off_t max_offset = offset + max;
  350. if (max_offset > get_streamfile_size(streamFile))
  351. max_offset = get_streamfile_size(streamFile);
  352. while (offset < max_offset) {
  353. uint8_t predictor = (read_8bit(offset+0x00,streamFile) >> 4) & 0x0f;
  354. uint8_t flags = read_8bit(offset+0x01,streamFile);
  355. if (predictor > 5 || flags > 7) {
  356. return 0;
  357. }
  358. offset += 0x10;
  359. }
  360. return 1;
  361. }