~ubuntu-branches/ubuntu/karmic/mhwaveedit/karmic

« back to all changes in this revision

Viewing changes to src/rateconv.c

  • Committer: Bazaar Package Importer
  • Author(s): Free Ekanayaka
  • Date: 2008-01-08 22:20:37 UTC
  • mfrom: (2.1.6 hardy)
  • Revision ID: james.westby@ubuntu.com-20080108222037-tsazhckl5vmc8yih
Tags: 1.4.14-2
Added desktop file (Closes: #457849), thanks to Marco Rodrigues

Show diffs side-by-side

added added

removed removed

Lines of Context:
56
56
 
57
57
struct convdata_base {
58
58
     struct driver_data *driver;
 
59
     Ringbuf *passthru_buffer;
 
60
     gboolean emptying;     
 
61
     guint32 writecount,readcount;
 
62
     guint32 empty_point;
 
63
     guint32 inrate,outrate;
59
64
};
60
65
 
61
66
static GList *drivers = NULL;
66
71
#ifdef HAVE_LIBSAMPLERATE
67
72
 
68
73
struct convdata_src {
69
 
     struct driver_data *driver;
 
74
     struct convdata_base b;
70
75
     Dataformat format;
71
76
     SRC_STATE *state;
72
77
     long maxframes;
97
102
     }
98
103
 
99
104
     cd = g_malloc(sizeof(*cd));
100
 
     cd->driver = driver;
101
105
     cd->state = state;
102
106
     memcpy(&(cd->format),format,sizeof(Dataformat));     
103
107
     frames = 16384;
206
210
#endif
207
211
 
208
212
struct convdata_sox {
209
 
     struct driver_data *driver;
 
213
     struct convdata_base b;
210
214
     Dataformat format;
211
215
     gboolean converting;
212
216
     Dataformat convert_from_format;
224
228
                        Dataformat *format, guint32 outrate, int dither_mode)
225
229
{
226
230
     struct convdata_sox cd,*cdp;
 
231
     Dataformat fmt;
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));
242
247
     }
243
 
     sox_dialog_format_string(d,sizeof(d),format->samplerate,
244
 
                              format->sign,format->samplesize,
245
 
                              format->channels);
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);
 
255
     /* puts(c); */
249
256
     cd.pipehandle = pipe_dialog_open_pipe(c,cd.fds,TRUE);
250
257
     if (cd.pipehandle == NULL) return NULL;
251
 
     cd.driver = driver;
252
258
     cd.tmpbuf_size = 0;
253
259
     cd.tmpbuf_in_size = 0;
254
260
     cd.close_status = 0;
452
458
}
453
459
 
454
460
struct convdata_repeat {
455
 
     struct driver_data *driver;
 
461
     struct convdata_base b;
456
462
     Ringbuf *databuf;
457
463
     Dataformat format;
458
 
     guint32 outrate;
459
464
     gchar cursamp[32];
460
465
     gfloat fracpos, ratio;
461
466
};
466
471
{
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));
500
503
 
501
504
     bufsize -= bufsize % data->format.samplebytes;
502
505
 
503
 
     if (data->format.samplerate == data->outrate) 
 
506
     if (data->format.samplerate == data->b.outrate) 
504
507
          return ringbuf_dequeue(data->databuf,buf,bufsize);     
505
508
 
506
509
     i = bufsize;
537
540
static void repeat_set_outrate(gpointer convdata, guint32 outrate)
538
541
{
539
542
     struct convdata_repeat *data = (struct convdata_repeat *)convdata;
540
 
     data->outrate = outrate;
541
543
     data->ratio = (data->format.samplerate) / ((gfloat)outrate);
542
544
}
543
545
 
671
673
}
672
674
 
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
                       gboolean passthru)
675
678
{
676
679
     GList *l;
677
680
     struct driver_data *d;
 
681
     struct convdata_base *conv;
678
682
     register_drivers();
679
683
 
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";
685
688
 
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;
 
695
               conv->driver = d;
 
696
               conv->inrate = format->samplerate;
 
697
               conv->outrate = outrate;
 
698
               if (passthru)
 
699
                    conv->passthru_buffer = 
 
700
                         ringbuf_new(16384 - (16384%format->samplebytes));
 
701
               else
 
702
                    conv->passthru_buffer = NULL;
 
703
               conv->emptying = FALSE;
 
704
               conv->readcount = conv->writecount = 0;
 
705
               conv->empty_point = 0;
 
706
               return conv;
 
707
          }
691
708
     }     
692
709
     return NULL;
693
710
}
695
712
gint rateconv_write(rateconv *conv, void *data, guint bufsize)
696
713
{
697
714
     struct convdata_base *convdata = (struct convdata_base *)conv;
698
 
     return convdata->driver->write_func(conv,data,bufsize);
 
715
     guint i = 0;
 
716
     gint j;
 
717
     if (convdata->passthru_buffer != NULL && 
 
718
         convdata->inrate == convdata->outrate) {
 
719
          i = ringbuf_freespace(convdata->passthru_buffer);
 
720
          if (i < bufsize) bufsize = i;   
 
721
     }
 
722
     j = convdata->driver->write_func(conv,data,bufsize);
 
723
     if (j > 0 && i > 0) {
 
724
          g_assert(j <= i);
 
725
          i = ringbuf_enqueue(convdata->passthru_buffer,data,j);
 
726
          g_assert(i == j);
 
727
     }
 
728
     if (j > 0) convdata->writecount += j;
 
729
     return j;
699
730
}
700
731
 
701
732
gint rateconv_read(rateconv *conv, void *data, guint bufsize)
702
733
{
703
734
     struct convdata_base *convdata = (struct convdata_base *)conv;
704
 
     return convdata->driver->read_func(conv,data,bufsize);
 
735
     gint i;
 
736
 
 
737
     i = convdata->driver->read_func(conv,data,bufsize);
 
738
 
 
739
     if (i > 0) {
 
740
 
 
741
          convdata->readcount += i;
 
742
          while (convdata->readcount > convdata->outrate) {
 
743
               convdata->readcount -= convdata->outrate;
 
744
 
 
745
               if (convdata->empty_point > convdata->outrate)
 
746
                    convdata->empty_point -= convdata->outrate;
 
747
               else
 
748
                    convdata->empty_point = 0;
 
749
 
 
750
               if (convdata->writecount > convdata->inrate)
 
751
                    convdata->writecount -= convdata->inrate;
 
752
               else
 
753
                    convdata->writecount = 0;          
 
754
 
 
755
          }
 
756
 
 
757
          if (convdata->emptying && 
 
758
              convdata->readcount >= convdata->empty_point)
 
759
               convdata->emptying = FALSE;
 
760
 
 
761
          if (convdata->passthru_buffer != NULL && 
 
762
              convdata->inrate == convdata->outrate && !convdata->emptying)
 
763
               return ringbuf_dequeue(convdata->passthru_buffer,data,i);
 
764
 
 
765
     }
 
766
     return i;
705
767
}
706
768
 
707
769
gboolean rateconv_hasdata(rateconv *conv)
716
778
     return convdata->driver->destroy_func(conv);
717
779
}
718
780
 
 
781
#define FLOAT(x) ((float)x)
 
782
#define GUINT32(x) ((guint32)x)
 
783
 
719
784
void rateconv_set_outrate(rateconv *conv, guint32 outrate)
720
785
{
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)));     
 
797
     }
724
798
}