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

« back to all changes in this revision

Viewing changes to src/datasource.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:
1
1
/*
2
 
 * Copyright (C) 2002 2003 2004 2005, Magnus Hjorth
 
2
 * Copyright (C) 2002 2003 2004 2005 2006, Magnus Hjorth
3
3
 *
4
4
 * This file is part of mhWaveEdit.
5
5
 *
250
250
 
251
251
gboolean datasource_dump(Datasource *ds, off_t position, 
252
252
                         off_t length, EFILE *file, int dither_mode, 
253
 
                         StatusBar *bar)
 
253
                         StatusBar *bar, off_t *clipcount)
254
254
{
255
255
     gchar *buf;
256
256
     off_t i;
259
259
     buf = g_malloc(DUMP_BUFSIZE);
260
260
     while (length > 0) {
261
261
          i = MIN(length*ds->format.samplebytes,DUMP_BUFSIZE);
262
 
          u = datasource_read_array(ds,position,i,buf,dither_mode);
 
262
          u = datasource_read_array(ds,position,i,buf,dither_mode,clipcount);
263
263
          if (u==0 || e_fwrite(buf,u,file) || status_bar_progress(bar,u)) { 
264
264
               datasource_close(ds); 
265
265
               g_free(buf);
281
281
     if (datasource_open(ds)) return TRUE;
282
282
 
283
283
     c = g_malloc(sz);
284
 
     if (datasource_read_array(ds,0,sz,c, dither_mode)) {
 
284
     if (datasource_read_array(ds,0,sz,c, dither_mode,NULL)) {
285
285
          g_free(c);
286
286
          datasource_close(ds);
287
287
          return TRUE;
385
385
 
386
386
static guint datasource_clone_read_array(Datasource *source, off_t sampleno,
387
387
                                         guint size, gpointer buffer, 
388
 
                                         int dither_mode)
 
388
                                         int dither_mode, off_t *clipcount)
389
389
{
390
390
     /* This is not optimized but it's only used in rare cases so the important
391
391
      * thing is that it works.*/
405
405
     orig_size = size + orig_adjust + source->data.clone->format.samplebytes - 1;
406
406
     p = g_malloc(orig_size);
407
407
     x = datasource_read_array(source->data.clone, orig_sampleno, orig_size, p,
408
 
                               dither_mode);
 
408
                               dither_mode,clipcount);
409
409
     if (x != 0) {
410
410
          g_assert(x-orig_adjust >= size);
411
411
          memcpy(buffer, p+orig_adjust, size);
512
512
 
513
513
static guint datasource_read_array_main(Datasource *source, 
514
514
                                        off_t sampleno, guint size, 
515
 
                                        gpointer buffer, int dither_mode)
 
515
                                        gpointer buffer, int dither_mode,
 
516
                                        off_t *clipcount)
516
517
{
517
518
     off_t x;
518
519
     guint u;
519
 
     gchar *c;
 
520
     sample_t *c;
520
521
     switch (source->type) {
521
522
     case DATASOURCE_REAL:
522
523
          memcpy(buffer,source->data.real+sampleno*source->format.samplebytes,
547
548
                    (source,sampleno,size/source->format.samplebytes,buffer);
548
549
     case DATASOURCE_REF:
549
550
          return datasource_read_array_main(source->data.clone,sampleno,size,
550
 
                                            buffer,dither_mode);
 
551
                                            buffer,dither_mode,clipcount);
551
552
     case DATASOURCE_CLONE:
552
553
          return datasource_clone_read_array(source,sampleno,size,buffer,
553
 
                                             dither_mode);
 
554
                                             dither_mode,clipcount);
554
555
     case DATASOURCE_BYTESWAP:
555
556
          u = datasource_read_array_main(source->data.clone,sampleno,size,
556
 
                                         buffer,dither_mode);
 
557
                                         buffer,dither_mode,clipcount);
557
558
          if (u>0) byteswap(buffer,source->format.samplesize,u);
558
559
          return u;
559
560
     case DATASOURCE_CONVERT:
561
562
          if (source->format.type == DATAFORMAT_FLOAT && 
562
563
              source->format.samplesize == sizeof(sample_t)) 
563
564
               return datasource_read_array_fp(source->data.clone,sampleno,u,
564
 
                                               buffer,dither_mode) *
 
565
                                               buffer,dither_mode,clipcount) *
565
566
                    source->format.samplebytes ;
566
567
          c = g_malloc(u*sizeof(sample_t)*source->format.channels);
567
568
          u = datasource_read_array_fp(source->data.clone, sampleno, u, 
568
 
                                       (gpointer)c,dither_mode);
 
569
                                       (gpointer)c,dither_mode,clipcount);
569
570
          if (u > 0) {
 
571
               if (clipcount != NULL)
 
572
                    *clipcount += 
 
573
                         unnormalized_count(c,u*source->format.channels);
570
574
               convert_array(c,&dataformat_sample_t,buffer,&(source->format),
571
575
                             u*source->format.channels,dither_mode);
572
576
          }
579
583
}
580
584
 
581
585
guint datasource_read_array(Datasource *source, off_t sampleno, guint size,
582
 
                            gpointer buffer, int dither_mode)
 
586
                            gpointer buffer, int dither_mode, 
 
587
                            off_t *clipcount)
583
588
{
584
589
     off_t o;
585
590
     g_assert(source->opencount > 0);
593
598
     if (size == 0) return 0;
594
599
     /* Do it */
595
600
     return datasource_read_array_main(source,sampleno,size,buffer,
596
 
                                       dither_mode);
 
601
                                       dither_mode,clipcount);
597
602
}
598
603
 
599
604
gboolean datasource_read(Datasource *source, off_t sampleno, gpointer buffer, 
600
605
                         int dither_mode)
601
606
{
602
607
     return (datasource_read_array(source,sampleno,source->format.samplebytes,
603
 
                                   buffer,dither_mode) 
 
608
                                   buffer,dither_mode,NULL) 
604
609
             != source->format.samplebytes);
605
610
}
606
611
 
607
612
 
608
613
guint datasource_read_array_fp(Datasource *source, off_t sampleno,
609
614
                               guint samples, sample_t *buffer, 
610
 
                               int dither_mode)
 
615
                               int dither_mode, off_t *clipcount)
611
616
{
612
617
     gchar *p;
613
618
     guint x,s;
629
634
     case DATASOURCE_REF:
630
635
     case DATASOURCE_CONVERT:
631
636
          return datasource_read_array_fp(source->data.clone,sampleno,
632
 
                                          samples,buffer,dither_mode);
 
637
                                          samples,buffer,dither_mode,
 
638
                                          clipcount);
633
639
     default:
634
640
          if (source->format.type == DATAFORMAT_FLOAT &&
635
641
              source->format.samplesize == sizeof(sample_t))
636
642
               
637
643
               return datasource_read_array(source,sampleno,
638
644
                                            samples*source->format.samplebytes,
639
 
                                            buffer, dither_mode) 
 
645
                                            buffer, dither_mode, clipcount) 
640
646
                    / source->format.samplebytes;
641
647
               
642
648
          s = samples * source->format.samplebytes;
643
649
          p = g_malloc(s);
644
 
          x = datasource_read_array(source,sampleno,s,p,dither_mode);
 
650
          x = datasource_read_array(source,sampleno,s,p,dither_mode,clipcount);
645
651
          g_assert(x==s || x==0);
646
652
          if (x==s) {
647
653
               convert_array(p,&(source->format),buffer,&dataformat_sample_t,
657
663
gboolean datasource_read_fp(Datasource *ds, off_t sampleno, sample_t *buffer,
658
664
                            int dither_mode)
659
665
{
660
 
     return (datasource_read_array_fp(ds,sampleno,1,buffer,dither_mode)!=1);
 
666
     return (datasource_read_array_fp(ds,sampleno,1,buffer,dither_mode,NULL)!=1);
661
667
}
662
668
 
663
669
static gboolean datasource_uses_file(Datasource *ds, gchar *filename)
689
695
          ds = (Datasource *)l->data;
690
696
          if (!datasource_uses_file(ds,filename)) continue;
691
697
 
692
 
          /* FIXME: When multiple tempdir support has been added, try moving to
693
 
           * all different partitions before copying */
 
698
          /* For the first affected datasource (backup == NULL), the file is
 
699
           * moved to a temporary directory and the filename in the datasource 
 
700
           * is updated. For each remaining sources, the file is copied.
 
701
           *
 
702
           * This is not optimal, but the case with more than one reference to
 
703
           * a file can only happen when the user has opened the same file
 
704
           * multiple times.
 
705
           */
694
706
          if (backup == NULL) {
 
707
               /* This loop first tries to move the file to each temporary 
 
708
                * directory. If all directories fail, we copy the file. */
695
709
               dirnum = 0;
696
710
               while (1) {
697
711
                    t = get_temp_filename(dirnum);
760
774
     ds = gtk_type_new(datasource_get_type());
761
775
     ds->type = DATASOURCE_CONVERT;
762
776
     memcpy(&(ds->format),new_format,sizeof(Dataformat));
 
777
     ds->format.samplebytes = ds->format.samplesize * ds->format.channels;
763
778
     ds->length = source->length;
764
779
     ds->bytes = ds->length * new_format->samplebytes;
765
780
     ds->data.clone = source;
767
782
     gtk_object_sink(GTK_OBJECT(source));
768
783
     return ds;     
769
784
}
 
785
 
 
786
#define NS 4096
 
787
static gint datasource_clip_check_fp(Datasource *ds, StatusBar *bar)
 
788
{
 
789
     sample_t *buf;     
 
790
     off_t o;
 
791
     guint i;
 
792
     off_t clipcount = 0;
 
793
     g_assert(ds->format.type == DATAFORMAT_FLOAT);
 
794
     if (datasource_open(ds)) return -1;
 
795
     buf = g_malloc(sizeof(sample_t) * ds->format.samplebytes);
 
796
     for (o=0; o<ds->length; ) {
 
797
          i = datasource_read_array_fp(ds,o,NS,buf,DITHER_UNSPEC,&clipcount);
 
798
          o += i;
 
799
          if (i == 0) {
 
800
               g_free(buf);
 
801
               datasource_close(ds);
 
802
               return -1;
 
803
          }       
 
804
          if (clipcount > 0) {
 
805
               g_free(buf);
 
806
               datasource_close(ds);
 
807
               return 1;
 
808
          }
 
809
          if (status_bar_progress(bar,NS)) {
 
810
               g_free(buf);
 
811
               datasource_close(ds);
 
812
               return -2;
 
813
          }       
 
814
     }
 
815
     datasource_close(ds);
 
816
     g_free(buf);
 
817
     return 0;
 
818
}
 
819
#undef NS
 
820
 
 
821
gint datasource_clip_check(Datasource *ds, StatusBar *bar)
 
822
{
 
823
     gint i;
 
824
     switch (ds->type) {
 
825
     case DATASOURCE_SNDFILE:
 
826
     case DATASOURCE_SNDFILE_TEMPORARY:
 
827
          /* Libsndfile is always used with normalization turned on */
 
828
          return 0;
 
829
     case DATASOURCE_SILENCE:
 
830
          /* Trivial */
 
831
          return 0;
 
832
     case DATASOURCE_REAL:
 
833
     case DATASOURCE_VIRTUAL:
 
834
     case DATASOURCE_TEMPFILE:
 
835
          /* If we contain PCM data, clipping can't occur */
 
836
          if (ds->format.type == DATAFORMAT_PCM) return 0;
 
837
          return datasource_clip_check_fp(ds,bar);
 
838
     case DATASOURCE_BYTESWAP:
 
839
     case DATASOURCE_CLONE:
 
840
          /* This could cause clipping in special cases. 
 
841
           * That clipping can not be solved by normalizing the data. */
 
842
          i = datasource_clip_check(ds->data.clone,bar);
 
843
          if (i < 0) return i;
 
844
          if (i > 0) return 2;
 
845
          if (ds->format.type == DATAFORMAT_FLOAT) 
 
846
               return datasource_clip_check_fp(ds,bar);
 
847
          else
 
848
               return 0;
 
849
     case DATASOURCE_REF:
 
850
     case DATASOURCE_CONVERT:
 
851
          return datasource_clip_check(ds->data.clone,bar);
 
852
     default:
 
853
          break;
 
854
     }
 
855
     g_assert_not_reached();
 
856
     return 0;
 
857
}