1 /*
2 * This file is part of cyanrip.
3 *
4 * cyanrip is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * cyanrip is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with cyanrip; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #pragma once
20
21 #include <stdint.h>
22 #include <libavutil/crc.h>
23
24 #include "cyanrip_main.h"
25
26 typedef struct cyanrip_checksum_ctx {
27 const AVCRC *eac_ctx;
28 uint32_t eac_crc;
29 uint32_t acu_start;
30 uint32_t acu_end;
31 uint32_t acu_mult;
32 uint32_t acu_sum_1;
33 uint32_t acu_sum_1_450;
34 uint32_t acu_sum_2;
35 } cyanrip_checksum_ctx;
36
crip_init_checksum_ctx(cyanrip_ctx * ctx,cyanrip_checksum_ctx * s,cyanrip_track * t)37 static inline void crip_init_checksum_ctx(cyanrip_ctx *ctx, cyanrip_checksum_ctx *s, cyanrip_track *t)
38 {
39 s->eac_ctx = av_crc_get_table(AV_CRC_32_IEEE_LE);
40 s->eac_crc = UINT32_MAX;
41 s->acu_start = 0;
42 s->acu_end = t->nb_samples;
43 s->acu_mult = 1;
44 s->acu_sum_1 = 0x0;
45 s->acu_sum_1_450 = 0x0;
46 s->acu_sum_2 = 0x0;
47
48 t->computed_crcs = 0;
49
50 if (t->acurip_track_is_first)
51 s->acu_start += (CDIO_CD_FRAMESIZE_RAW * 5) >> 2;
52 if (t->acurip_track_is_last)
53 s->acu_end -= (CDIO_CD_FRAMESIZE_RAW * 5) >> 2;
54 }
55
crip_process_checksums(cyanrip_checksum_ctx * s,const uint8_t * data,int bytes)56 static inline void crip_process_checksums(cyanrip_checksum_ctx *s, const uint8_t *data, int bytes)
57 {
58 if (!bytes)
59 return;
60
61 s->eac_crc = av_crc(s->eac_ctx, s->eac_crc, data, bytes);
62
63 /* Loop over samples */
64 for (int j = 0; j < (bytes >> 2); j++) {
65 if (s->acu_mult >= s->acu_start && s->acu_mult <= s->acu_end) {
66 uint32_t val = AV_RL32(&data[j*4]);
67 uint64_t tmp = (uint64_t)val * (uint64_t)s->acu_mult;
68 uint32_t lo = (uint32_t)(tmp & (uint64_t)UINT32_MAX);
69 uint32_t hi = (uint32_t)(tmp / (uint64_t)0x100000000);
70 s->acu_sum_1 += s->acu_mult * val;
71 s->acu_sum_2 += hi;
72 s->acu_sum_2 += lo;
73 }
74 if (((s->acu_mult - 1) >= (450 * (CDIO_CD_FRAMESIZE_RAW >> 2))) &&
75 ((s->acu_mult - 1) < (451 * (CDIO_CD_FRAMESIZE_RAW >> 2)))) {
76 uint32_t mult = s->acu_mult - (450 * (CDIO_CD_FRAMESIZE_RAW >> 2));
77 s->acu_sum_1_450 += AV_RL32(&data[j*4]) * mult;
78 }
79 s->acu_mult++;
80 }
81 }
82
crip_finalize_checksums(cyanrip_checksum_ctx * s,cyanrip_track * t)83 static inline void crip_finalize_checksums(cyanrip_checksum_ctx *s, cyanrip_track *t)
84 {
85 t->computed_crcs = 1;
86 t->eac_crc = s->eac_crc ^ UINT32_MAX;
87 t->acurip_checksum_v1 = s->acu_sum_1;
88 t->acurip_checksum_v1_450 = s->acu_sum_1_450;
89 t->acurip_checksum_v2 = s->acu_sum_2;
90 }
91