57
57
struct convdata_base {
58
58
struct driver_data *driver;
59
Ringbuf *passthru_buffer;
61
guint32 writecount,readcount;
63
guint32 inrate,outrate;
61
66
static GList *drivers = NULL;
224
228
Dataformat *format, guint32 outrate, int dither_mode)
226
230
struct convdata_sox cd,*cdp;
227
232
gchar c[512],d[64],e[64];
228
233
if (format->type == DATAFORMAT_FLOAT || format->samplesize == 3 ||
229
234
XOR(format->bigendian,IS_BIGENDIAN)) {
240
245
cd.converting = FALSE;
241
246
memcpy(&(cd.format),format,sizeof(Dataformat));
243
sox_dialog_format_string(d,sizeof(d),format->samplerate,
244
format->sign,format->samplesize,
246
sox_dialog_format_string(e,sizeof(e),outrate,format->sign,
247
format->samplesize,format->channels);
248
sox_dialog_format_string(d,sizeof(d),&(cd.format));
249
memcpy(&fmt,&(cd.format),sizeof(fmt));
250
fmt.samplerate = outrate;
251
sox_dialog_format_string(e,sizeof(e),&fmt);
252
/* driver->id+4 converts driver name to effect name, for example
253
* "sox_resample" to "resample" */
248
254
g_snprintf(c,sizeof(c),"sox %s - %s - %s",d,e,driver->id+4);
249
256
cd.pipehandle = pipe_dialog_open_pipe(c,cd.fds,TRUE);
250
257
if (cd.pipehandle == NULL) return NULL;
252
258
cd.tmpbuf_size = 0;
253
259
cd.tmpbuf_in_size = 0;
254
260
cd.close_status = 0;
467
472
struct convdata_repeat *data;
468
473
data = g_malloc(sizeof(*data));
469
data->driver = driver;
470
474
data->databuf = ringbuf_new(realtime ? 1024*format->samplebytes :
471
475
format->samplerate * format->samplebytes);
472
data->outrate = outrate;
473
476
data->fracpos = 1.0;
474
477
data->ratio = (format->samplerate) / ((gfloat)outrate);
475
478
memcpy(&(data->format),format,sizeof(Dataformat));
501
504
bufsize -= bufsize % data->format.samplebytes;
503
if (data->format.samplerate == data->outrate)
506
if (data->format.samplerate == data->b.outrate)
504
507
return ringbuf_dequeue(data->databuf,buf,bufsize);
673
675
rateconv *rateconv_new(gboolean realtime, const char *driver_id,
674
Dataformat *format, guint32 outrate, int dither_mode)
676
Dataformat *format, guint32 outrate, int dither_mode,
677
680
struct driver_data *d;
681
struct convdata_base *conv;
678
682
register_drivers();
680
684
/* If desired sample rate is same as input rate, use the repeat
681
685
* driver, which has special case for this. */
682
686
if (format->samplerate == outrate && !realtime)
683
return repeat_driver->new_func(repeat_driver,realtime,format,
684
outrate,dither_mode);
687
driver_id = "repeat";
686
689
l = realtime ? realtime_drivers : drivers;
687
690
for (; l!=NULL; l=l->next) {
688
691
d = (struct driver_data *)l->data;
689
if (!strcmp(d->id,driver_id))
690
return d->new_func(d,realtime,format,outrate,dither_mode);
692
if (!strcmp(d->id,driver_id)) {
693
conv = d->new_func(d,realtime,format,outrate,dither_mode);
694
if (conv == NULL) return NULL;
696
conv->inrate = format->samplerate;
697
conv->outrate = outrate;
699
conv->passthru_buffer =
700
ringbuf_new(16384 - (16384%format->samplebytes));
702
conv->passthru_buffer = NULL;
703
conv->emptying = FALSE;
704
conv->readcount = conv->writecount = 0;
705
conv->empty_point = 0;
695
712
gint rateconv_write(rateconv *conv, void *data, guint bufsize)
697
714
struct convdata_base *convdata = (struct convdata_base *)conv;
698
return convdata->driver->write_func(conv,data,bufsize);
717
if (convdata->passthru_buffer != NULL &&
718
convdata->inrate == convdata->outrate) {
719
i = ringbuf_freespace(convdata->passthru_buffer);
720
if (i < bufsize) bufsize = i;
722
j = convdata->driver->write_func(conv,data,bufsize);
723
if (j > 0 && i > 0) {
725
i = ringbuf_enqueue(convdata->passthru_buffer,data,j);
728
if (j > 0) convdata->writecount += j;
701
732
gint rateconv_read(rateconv *conv, void *data, guint bufsize)
703
734
struct convdata_base *convdata = (struct convdata_base *)conv;
704
return convdata->driver->read_func(conv,data,bufsize);
737
i = convdata->driver->read_func(conv,data,bufsize);
741
convdata->readcount += i;
742
while (convdata->readcount > convdata->outrate) {
743
convdata->readcount -= convdata->outrate;
745
if (convdata->empty_point > convdata->outrate)
746
convdata->empty_point -= convdata->outrate;
748
convdata->empty_point = 0;
750
if (convdata->writecount > convdata->inrate)
751
convdata->writecount -= convdata->inrate;
753
convdata->writecount = 0;
757
if (convdata->emptying &&
758
convdata->readcount >= convdata->empty_point)
759
convdata->emptying = FALSE;
761
if (convdata->passthru_buffer != NULL &&
762
convdata->inrate == convdata->outrate && !convdata->emptying)
763
return ringbuf_dequeue(convdata->passthru_buffer,data,i);
707
769
gboolean rateconv_hasdata(rateconv *conv)
716
778
return convdata->driver->destroy_func(conv);
781
#define FLOAT(x) ((float)x)
782
#define GUINT32(x) ((guint32)x)
719
784
void rateconv_set_outrate(rateconv *conv, guint32 outrate)
721
786
struct convdata_base *convdata = (struct convdata_base *)conv;
722
787
g_assert(convdata->driver->is_realtime);
723
788
convdata->driver->set_outrate_func(conv,outrate);
789
convdata->outrate = outrate;
790
if (convdata->passthru_buffer != NULL &&
791
convdata->outrate == convdata->inrate) {
792
ringbuf_drain(convdata->passthru_buffer);
793
convdata->emptying = TRUE;
794
convdata->empty_point = GUINT32(FLOAT(convdata->writecount) *
795
(FLOAT(convdata->outrate) /
796
FLOAT(convdata->inrate)));