1 #include <Python.h>
2 #include <stdint.h>
3
4 /********************************************************
5 Audio Tools, a module and set of tools for manipulating audio data
6 Copyright (C) 2007-2014 Brian Langenberger
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 *******************************************************/
22
23 struct queue {
24 uint32_t *values;
25 unsigned total_size;
26 unsigned head_index;
27 unsigned tail_index;
28 };
29
30 struct accuraterip_v1 {
31 unsigned index;
32
33 uint32_t *checksums; /*array of AccurateRip V1 checksums*/
34
35 /*saved values necessary for calculating incremental
36 AccurateRip V1 checksums*/
37 struct queue *initial_values;
38 struct queue *final_values;
39 uint32_t values_sum;
40 };
41
42 struct accuraterip_v2 {
43 unsigned index;
44
45 uint32_t checksum; /*the AccurateRip V2 checksum*/
46
47 unsigned current_offset; /*offset of the checksum in window*/
48
49 unsigned initial_offset; /*initially specified window offset*/
50 };
51
52 typedef struct {
53 PyObject_HEAD
54
55 unsigned total_pcm_frames; /*total PCM frames in the window*/
56
57 unsigned pcm_frame_range; /*range of the window, starting from 1*/
58
59 unsigned processed_frames; /*total frames processed so far*/
60
61 /*values not between start and end offset are treated as 0*/
62 unsigned start_offset; /*initial index offset*/
63 unsigned end_offset; /*final index offset*/
64
65 struct accuraterip_v1 accuraterip_v1;
66 struct accuraterip_v2 accuraterip_v2;
67
68 PyObject* framelist_class;
69 } accuraterip_Checksum;
70
71 static PyObject*
72 Checksum_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
73
74 int
75 Checksum_init(accuraterip_Checksum *self, PyObject *args, PyObject *kwds);
76
77 void
78 Checksum_dealloc(accuraterip_Checksum *self);
79
80 static PyObject*
81 Checksum_update(accuraterip_Checksum* self, PyObject *args);
82
83 static void
84 update_frame_v1(struct accuraterip_v1 *v1,
85 unsigned total_pcm_frames,
86 unsigned start_offset,
87 unsigned end_offset,
88 unsigned value);
89
90 static void
91 update_frame_v2(struct accuraterip_v2 *v2,
92 unsigned total_pcm_frames,
93 unsigned start_offset,
94 unsigned end_offset,
95 unsigned value);
96
97 static struct queue*
98 init_queue(unsigned total_size);
99
100 static void
101 free_queue(struct queue *queue);
102
103 static inline int
queue_full(const struct queue * queue)104 queue_full(const struct queue *queue)
105 {
106 return (queue->tail_index == queue->total_size);
107 }
108
109 static inline void
queue_push(struct queue * queue,uint32_t value)110 queue_push(struct queue *queue, uint32_t value)
111 {
112 queue->values[queue->tail_index++] = value;
113 }
114
115 static inline uint32_t
queue_pop(struct queue * queue)116 queue_pop(struct queue *queue)
117 {
118 return queue->values[queue->head_index++];
119 }
120
121 static PyObject*
122 Checksum_checksums_v1(accuraterip_Checksum* self, PyObject *args);
123
124 static PyObject*
125 Checksum_checksum_v2(accuraterip_Checksum* self, PyObject *args);
126
127 static PyMethodDef Checksum_methods[] = {
128 {"update", (PyCFunction)Checksum_update,
129 METH_VARARGS, "update(framelist)"},
130 {"checksums_v1", (PyCFunction)Checksum_checksums_v1,
131 METH_NOARGS, "checksums_v1() -> [crc, crc, ...]"},
132 {"checksum_v2", (PyCFunction)Checksum_checksum_v2,
133 METH_NOARGS, "checksum_v2() -> crc"},
134 {NULL}
135 };
136
137 static PyTypeObject accuraterip_ChecksumType = {
138 PyVarObject_HEAD_INIT(NULL, 0)
139 "_accuraterip.Checksum", /*tp_name*/
140 sizeof(accuraterip_Checksum), /*tp_basicsize*/
141 0, /*tp_itemsize*/
142 (destructor)Checksum_dealloc, /*tp_dealloc*/
143 0, /*tp_print*/
144 0, /*tp_getattr*/
145 0, /*tp_setattr*/
146 0, /*tp_compare*/
147 0, /*tp_repr*/
148 0, /*tp_as_number*/
149 0, /*tp_as_sequence*/
150 0, /*tp_as_mapping*/
151 0, /*tp_hash */
152 0, /*tp_call*/
153 0, /*tp_str*/
154 0, /*tp_getattro*/
155 0, /*tp_setattro*/
156 0, /*tp_as_buffer*/
157 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
158 "Checksum objects", /* tp_doc */
159 0, /* tp_traverse */
160 0, /* tp_clear */
161 0, /* tp_richcompare */
162 0, /* tp_weaklistoffset */
163 0, /* tp_iter */
164 0, /* tp_iternext */
165 Checksum_methods, /* tp_methods */
166 0, /* tp_members */
167 0, /* tp_getset */
168 0, /* tp_base */
169 0, /* tp_dict */
170 0, /* tp_descr_get */
171 0, /* tp_descr_set */
172 0, /* tp_dictoffset */
173 (initproc)Checksum_init, /* tp_init */
174 0, /* tp_alloc */
175 Checksum_new, /* tp_new */
176 };
177