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