* @param input_channels Number of input channels
* @param input_signed Whether input samples are signed or unsigned
* @param input_rate Frames/second in input
+ * @param input_endian Input endianness (@c ENDIAN_BIG or @c ENDIAN_LITTLE)
* @param output_bits Bits/sample in output
* @param output_channels Number of output channels
* @param output_rate Frames/second in output
* @param output_signed Whether output samples are signed or unsigned
+ * @param output_endian Output endianness (@c ENDIAN_BIG or @c ENDIAN_LITTLE)
*
* For formats with more than two channels it's assume that the first
* two channels are left and right. No particular meaning is attached
int output_bits, int output_channels,
int output_rate, int output_signed,
int output_endian) {
- int error_;
memset(rs, 0, sizeof *rs);
assert(input_bits == 8 || input_bits == 16);
assert(output_bits == 8 || output_bits == 16);
rs->input_bytes_per_frame = rs->input_channels * rs->input_bytes_per_sample;
if(rs->input_rate != rs->output_rate) {
#if HAVE_SAMPLERATE_H
+ int error_;
rs->state = src_new(SRC_SINC_BEST_QUALITY, rs->output_channels, &error_);
if(!rs->state)
- fatal(0, "calling src_new: %s", src_strerror(error_));
+ disorder_fatal(0, "calling src_new: %s", src_strerror(error_));
#else
- fatal(0, "need to resample audio data but libsamplerate not available");
+ disorder_fatal(0, "need to resample audio data but libsamplerate not available");
#endif
}
}
#if HAVE_SAMPLERATE_H
if(rs->state)
src_delete(rs->state);
+#else
+ if(rs){} /* quieten compiler */
#endif
}
* @param where Where to store result
* @return Number of bytes consumed
*/
-static size_t resample_get_sample(struct resampler *rs,
+static size_t resample_get_sample(const struct resampler *rs,
const uint8_t *bytes,
float *where) {
switch(rs->input_bits + rs->input_signed + rs->input_endian) {
case 8+ENDIAN_BIG:
case 8+ENDIAN_LITTLE:
- *where = (bytes[0] - 128)/ 128;
+ *where = (bytes[0] - 128)/ 128.0;
return 1;
case 8+SIGNED+ENDIAN_BIG:
case 8+SIGNED+ENDIAN_LITTLE:
- *where = (int8_t)bytes[0] / 128;
+ *where = (int8_t)bytes[0] / 128.0;
return 1;
case 16+ENDIAN_BIG:
*where = (bytes[0] * 256 + bytes[1] - 32768)/ 32768.0;
*
* The value is clipped naively if it will not fit.
*/
-static size_t resample_put_sample(struct resampler *rs,
+static size_t resample_put_sample(const struct resampler *rs,
float sample,
uint8_t *bytes) {
unsigned value;
- switch(rs->input_bits + rs->input_signed + rs->input_endian) {
+ switch(rs->output_bits + rs->output_signed + rs->output_endian) {
case 8+ENDIAN_BIG:
case 8+ENDIAN_LITTLE:
*bytes = clip(sample * 128.0 + 128, 0, 255);
/** @brief Convert input samples to floats
* @param rs Resampler state
* @param bytes Input bytes
- * @param nbytes Number of input bytes
+ * @param nframes Number of input frames
* @param floats Where to store converted data
*
* @p floats must be big enough. As well as converting to floats this
* the input either mono or stereo, so the result isn't actually going to be
* too bad.
*/
-static void resample_prepare_input(struct resampler *rs,
+static void resample_prepare_input(const struct resampler *rs,
const uint8_t *bytes,
- size_t nbytes,
+ size_t nframes,
float *floats) {
- size_t nframes = nbytes / (rs->input_bytes_per_frame);
-
while(nframes > 0) {
int n;
++floats;
}
}
+ --nframes;
}
}
* @param nbytes Number of bytes to convert
* @param eof Set an end of input stream
* @param converted Called with converted data (possibly more than once)
+ * @param cd Passed to @p cd
* @return Number of bytes consumed
*/
-size_t resample_convert(struct resampler *rs,
+size_t resample_convert(const struct resampler *rs,
const uint8_t *bytes,
size_t nbytes,
int eof,
void (*converted)(uint8_t *bytes,
- size_t nbytes)) {
+ size_t nbytes,
+ void *cd),
+ void *cd) {
size_t nframesin = nbytes / (rs->input_bytes_per_frame);
size_t nsamplesout;
float *input = xcalloc(nframesin * rs->output_channels, sizeof (float));
float *output = 0;
- resample_prepare_input(rs, bytes, nbytes, input);
+ resample_prepare_input(rs, bytes, nframesin, input);
#if HAVE_SAMPLERATE_H
if(rs->state) {
/* A sample-rate conversion must be performed */
SRC_DATA data;
+ memset(&data, 0, sizeof data);
/* Compute how many frames are expected to come out. */
size_t maxframesout = nframesin * rs->output_rate / rs->input_rate + 1;
output = xcalloc(maxframesout * rs->output_channels, sizeof(float));
data.input_frames = nframesin;
data.output_frames = maxframesout;
data.end_of_input = eof;
- data.src_ratio = rs->output_rate / rs->input_rate;
+ data.src_ratio = (double)rs->output_rate / rs->input_rate;
+ D(("nframesin=%zu maxframesout=%zu eof=%d ratio=%d.%06d",
+ nframesin, maxframesout, eof,
+ (int)data.src_ratio,
+ ((int)(data.src_ratio * 1000000) % 1000000)));
int error_ = src_process(rs->state, &data);
if(error_)
- fatal(0, "calling src_process: %s", src_strerror(error_));
+ disorder_fatal(0, "calling src_process: %s", src_strerror(error_));
nframesin = data.input_frames_used;
nsamplesout = data.output_frames_gen * rs->output_channels;
+ D(("new nframesin=%zu nsamplesout=%zu", nframesin, nsamplesout));
}
#endif
if(!output) {
bufused += resample_put_sample(rs, *op++, buffer + bufused);
--nsamplesout;
}
- converted(buffer, bufused);
+ converted(buffer, bufused, cd);
}
if(output != input)
xfree(output);
xfree(input);
+ if(eof){} /* quieten compiler */
/* Report how many input bytes were actually consumed */
+ //fprintf(stderr, "converted %zu frames\n", nframesin);
return nframesin * rs->input_bytes_per_frame;
}