10 typedef float* float_ptr
;
12 void* xmalloc(size_t size
)
14 void* x
= malloc(size
);
16 fprintf(stderr
, "Out of memory!\n");
22 double tonumber(const char* value
)
25 double x
= strtod(value
, &end
);
27 fprintf(stderr
, "Invalid number %s!\n", value
);
33 int main(int argc
, char** argv
)
35 unsigned char iobuffer
[BLOCKSIZE
* SAMPLESIZE
];
36 float filterbuffer
[BLOCKSIZE
];
37 unsigned bufferfill
= 0;
43 float_ptr past_input
[CHANNELS
];
44 float_ptr past_output
[CHANNELS
];
49 unsigned input_current
= 0;
50 unsigned input_lag
= 0;
53 fprintf(stderr
, "Syntax: %s <in> <out> <coefficients>\n", argv
[0]);
54 fprintf(stderr
, "<in> and <out> are raw audio data (not audio dumps).\n");
55 fprintf(stderr
, "Coefficient prefixed with '#' is b0 (if none is marked so,\n");
56 fprintf(stderr
, "Then the first coefficient for numerator is b0 (the coefficients\n");
57 fprintf(stderr
, "are in order of increasing index). Coefficients prefixed with '/'\n");
58 fprintf(stderr
, "are sent to denominator (first as a0).\n");
62 input_coeffs
= xmalloc(argc
* sizeof(float));
63 output_coeffs
= xmalloc((argc
+ 1) * sizeof(float));
64 for(unsigned j
= 0; j
< CHANNELS
; j
++)
65 past_input
[j
] = xmalloc(argc
* sizeof(float));;
66 for(unsigned j
= 0; j
< CHANNELS
; j
++)
67 past_output
[j
] = xmalloc(argc
* sizeof(float));;
72 for(int i
= 3; i
< argc
; i
++) {
73 if(argv
[i
][0] == '#') {
74 input_lag
= input_size
;
75 input_coeffs
[input_size
++] = tonumber(argv
[i
] + 1);
76 } else if(argv
[i
][0] == '/') {
77 output_coeffs
[output_size
++] = tonumber(argv
[i
] + 1);
79 input_coeffs
[input_size
++] = tonumber(argv
[i
]);
83 output_coeffs
[output_size
++] = 1;
86 FILE* in
= fopen(argv
[1], "rb");
88 fprintf(stderr
, "Can't open '%s' (for input)\n", argv
[1]);
91 FILE* out
= fopen(argv
[2], "wb");
93 fprintf(stderr
, "Can't open '%s' (for output)\n", argv
[2]);
97 //Prefill the previous input and output buffers.
98 for(unsigned i
= 0; i
< input_size
; i
++)
99 for(unsigned j
= 0; j
< CHANNELS
; j
++)
100 past_input
[j
][i
] = 0;
101 for(unsigned i
= 0; i
< output_size
; i
++)
102 for(unsigned j
= 0; j
< CHANNELS
; j
++)
103 past_output
[j
][i
] = 0;
106 //Read the sample data.
109 for(unsigned i
= 0; i
< BLOCKSIZE
; i
++)
112 for(unsigned i
= 0; i
< BLOCKSIZE
* SAMPLESIZE
; i
++)
118 r
= fread(iobuffer
, SAMPLESIZE
, BLOCKSIZE
, in
);
125 for(unsigned i
= 0; i
< BLOCKSIZE
; i
++) {
126 short sample
= ((unsigned short)iobuffer
[i
* SAMPLESIZE
+ 0]) |
127 ((unsigned short)iobuffer
[i
* SAMPLESIZE
+ 1] << 8);
128 filterbuffer
[i
] += (float)sample
;
133 for(unsigned i
= 0; i
< BLOCKSIZE
; i
++) {
135 unsigned old_lag
= input_lag
;
136 int chan
= i
% CHANNELS
;
138 memmove(past_input
[chan
] + 1, past_input
[chan
], (input_size
- 1) *
140 past_input
[chan
][0] = filterbuffer
[i
];
141 if(chan
== CHANNELS
- 1 && old_lag
< input_current
)
143 if(old_lag
< input_current
)
146 for(unsigned j
= 0; j
< input_size
; j
++)
147 sample
+= input_coeffs
[j
] * past_input
[chan
][j
];
148 for(unsigned j
= 1; j
< output_size
; j
++)
149 sample
-= output_coeffs
[j
] * past_output
[chan
][j
- 1];
150 sample
/= output_coeffs
[0];
152 filterbuffer
[bufferfill
++] = sample
;
154 memmove(past_output
[chan
] + 1, past_output
[chan
], (output_size
- 1) *
156 past_output
[chan
][0] = sample
;
159 if(written
+ bufferfill
> total
)
160 bufferfill
= total
- written
;
163 for(unsigned i
= 0; i
< BLOCKSIZE
; i
++) {
164 int sample
= (int)filterbuffer
[i
];
165 if(sample
< -32768) {
173 unsigned short value
= (unsigned short)sample
;
174 iobuffer
[i
* SAMPLESIZE
+ 0] = (unsigned char)sample
;
175 iobuffer
[i
* SAMPLESIZE
+ 1] = (unsigned char)(sample
>> 8);
177 if(fwrite(iobuffer
, SAMPLESIZE
, bufferfill
, out
) < bufferfill
) {
178 fprintf(stderr
, "Can't write output file.\n");
181 written
+= bufferfill
;
183 if(eof
&& total
== written
)
188 fprintf(stderr
, "Can't close output file.\n");
193 fprintf(stderr
, "Warning: %llu of %llu sample(s) truncated in value.\n", cut
, total
);