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