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

« back to all changes in this revision

Viewing changes to src/chunk.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 2007, Magnus Hjorth
3
3
 *
4
4
 * This file is part of mhWaveEdit.
5
5
 *
151
151
     gchar buf[4096];
152
152
     if (conv == NULL) 
153
153
          conv = rateconv_new(FALSE,conv_driver,informat,
154
 
                              conv_outrate,conv_dither_mode);
 
154
                              conv_outrate,conv_dither_mode,FALSE);
155
155
     if (conv == NULL) return TRUE;
156
156
     if (sample_size == 0) rateconv_write(conv,NULL,0);
157
157
     while (1) {
196
196
                            dither_mode,
197
197
                            bar, _("Converting samplerate"));
198
198
     /* puts("chunk_convert_samplerate: calling rateconv_destroy"); */
199
 
     if (conv != NULL) rateconv_destroy(conv);
 
199
     if (conv != NULL) {
 
200
          rateconv_destroy(conv);
 
201
          conv = NULL;
 
202
     }
200
203
     return c;
201
204
}
202
205
 
287
290
{
288
291
     GList *l;
289
292
     DataPart *dp;
 
293
     off_t clipcount = 0;
290
294
     l = chunk->parts;
291
295
     while (l) {
292
296
          dp = (DataPart *)l->data;
293
297
          if (datasource_dump(dp->ds,dp->position,dp->length,file,
294
 
                              dither_mode,bar))
 
298
                              dither_mode,bar,&clipcount))
295
299
               return TRUE;
296
300
          l = l->next;
297
301
     }
298
 
     return FALSE;
 
302
     return clipwarn(clipcount,TRUE);
299
303
}
300
304
 
301
305
static gboolean has_fake_pcm(Chunk *c)
331
335
     Dataformat *tofmt;
332
336
     gchar buf[16384];
333
337
     int dither_mode;
 
338
     off_t *clipcount;
334
339
};
335
340
 
336
341
static gboolean convert_back_write(WriteoutID id, gpointer data, guint length)
338
343
     struct convert_back *cbp = (struct convert_back *)id;
339
344
     guint i;
340
345
     i = length / sizeof(sample_t);
 
346
     *(cbp->clipcount) += unnormalized_count(data,i);
341
347
     convert_array(data,&dataformat_sample_t,cbp->buf,cbp->tofmt,i,
342
348
                   cbp->dither_mode);
343
349
     return tempfile_write(cbp->tmp,cbp->buf,i*cbp->tofmt->samplesize);
349
355
                          Dataformat *tofmt, int dither_mode,
350
356
                          StatusBar *bar, gchar *title)
351
357
{
 
358
     /* This code has to keep track of five different sample formats:
 
359
      *   1) The Chunk's native format (chunk->format)
 
360
      *   2) The processing function's input format (informat)
 
361
      *   3) The processing function's output format (outformat)
 
362
      *   4) The output temporary file's format (outformat or tofmt)
 
363
      *   5) The output Chunk's native format (tofmt)
 
364
      *
 
365
      * These modes are possible:
 
366
      *
 
367
      *   1) Native format all the way
 
368
      *      if must_convert == FALSE and no FP data in chunk
 
369
      *      convert = FALSE, convert_back = FALSE,
 
370
      *      formats (1)=(2)=(3), (4)=(5)
 
371
      *
 
372
      *   2) FP processing with FP tempfiles
 
373
      *      if must_convert == TRUE || FP data in chunk
 
374
      *      convert = TRUE, convert_back = FALSE
 
375
      *      formats (2)=(3)=floating point version of (1)
 
376
      *      format (4)=floating point version of (5)
 
377
      *
 
378
      *   3) FP processing with native tempfiles
 
379
      *      (this mode is only used if the "use FP tempfiles option" is 
 
380
      *      disabled, could cause quality loss)
 
381
      *      if (must_convert == TRUE || FP data in chunk) && 
 
382
      *          !chunk_filter_use_floating_tempfiles,
 
383
      *      convert = TRUE, convert_back = TRUE
 
384
      *      formats (2)=(3)=floating point version of (1),  (4)=(5)
 
385
      */
 
386
 
 
387
 
352
388
     guint proc_size,single_size,full_size;
353
389
     gchar buf[8192];
354
390
     off_t samplepos=0, samplesleft=chunk->length;
357
393
     Dataformat informat,outformat;
358
394
     ChunkHandle *ch;
359
395
     TempFile tmp;
360
 
     Chunk *ds,*r;
 
396
     Chunk *ds,*r;     
361
397
     struct convert_back *cbp = NULL;
 
398
     off_t clipcount = 0;
362
399
     
363
400
     /* Force processing in floating-point if any of the Datasources has 
364
401
      * faked pcm data */
394
431
          cbp->tmp = tmp;
395
432
          cbp->tofmt = tofmt;
396
433
          cbp->dither_mode = dither_mode;
 
434
          cbp->clipcount = &clipcount;
397
435
     }
398
436
     status_bar_begin_progress(bar,samplesleft,title);
399
437
 
401
439
          if (convert)
402
440
               u = chunk_read_array_fp(ch,samplepos,
403
441
                                       MIN(sizeof(buf)/full_size,samplesleft),
404
 
                                       (sample_t *)buf,dither_mode)*full_size;
 
442
                                       (sample_t *)buf,dither_mode,
 
443
                                       &clipcount) *
 
444
                    full_size;
405
445
          else
406
446
               u = chunk_read_array(ch,samplepos,
407
447
                                    MIN(sizeof(buf),samplesleft*full_size),buf,
408
 
                                    dither_mode);
 
448
                                    dither_mode,&clipcount);
409
449
          if (!u) {
410
450
               chunk_close(ch);
411
451
               tempfile_abort(tmp);
447
487
     chunk_close(ch);
448
488
     ds = tempfile_finished(tmp);
449
489
     status_bar_end_progress(bar);
 
490
     if (cbp != NULL) g_free(cbp);
 
491
 
 
492
     if (clipwarn(clipcount,TRUE)) {
 
493
          gtk_object_sink(GTK_OBJECT(ds));
 
494
          return NULL;
 
495
     }
450
496
 
451
497
     /* Check if the datasources format is the same as the user expects. If 
452
498
      * not, convert. */
465
511
 
466
512
gboolean chunk_parse(Chunk *chunk, chunk_parse_proc proc, 
467
513
                     gboolean allchannels, gboolean convert, int dither_mode, 
468
 
                     StatusBar *bar, gchar *title)
 
514
                     StatusBar *bar, gchar *title, off_t samplepos, 
 
515
                     gboolean reverse)
469
516
{
470
517
 
471
518
     guint single_size,full_size,proc_size;
472
519
     gchar buf[4096],*c=NULL,*d;
473
 
     off_t samplepos=0, samplesleft=chunk->length;
474
 
     guint u, x;
 
520
     off_t samplesleft;
 
521
     off_t readpos;
 
522
     off_t readsamples;
 
523
     guint u;
 
524
     gint x;
475
525
     ChunkHandle *ch;
 
526
     off_t clipcount = 0;
 
527
 
 
528
     if(reverse) {
 
529
          samplesleft = samplepos;
 
530
     } else {
 
531
          samplesleft = chunk->length - samplepos;
 
532
     }
476
533
 
477
534
     if (convert) single_size = sizeof(sample_t);
478
535
     else single_size = chunk->format.samplesize;
482
539
     if (allchannels) proc_size = full_size;
483
540
     else proc_size = single_size;
484
541
 
 
542
     readsamples = sizeof(buf) / full_size;
 
543
     if(samplesleft < readsamples) {
 
544
          readsamples = samplesleft;
 
545
     }
485
546
 
486
547
     ch = chunk_open(chunk);
487
548
     if (ch == NULL) { g_free(c); return TRUE; }
488
549
     status_bar_begin_progress( bar, chunk->length, title);
489
550
 
490
551
     while (samplesleft > 0) {
491
 
          if (convert)         
492
 
               u = chunk_read_array_fp(ch,samplepos,sizeof(buf)/full_size,
493
 
                                       (sample_t *)buf,dither_mode)*full_size;
494
 
          else
495
 
               u = chunk_read_array(ch,samplepos,sizeof(buf),buf,dither_mode);
 
552
          if(reverse) {
 
553
               readpos = samplepos - readsamples;
 
554
          } else {
 
555
               readpos = samplepos;
 
556
          }
 
557
 
 
558
          if (convert) {
 
559
               u = chunk_read_array_fp(ch,readpos,
 
560
                                       readsamples,
 
561
                                       (sample_t *)buf,dither_mode,&clipcount);
 
562
               u = u * full_size;
 
563
          } else {
 
564
               u = chunk_read_array(ch,readpos,readsamples * full_size,
 
565
                                    buf,dither_mode,&clipcount);
 
566
          }
 
567
 
 
568
          g_assert((u / full_size) == readsamples);
 
569
 
496
570
          if (!u) {
497
571
               chunk_close(ch);
498
572
               g_free(c);
499
573
               status_bar_end_progress(bar);
500
574
               return TRUE;
501
575
          }
 
576
 
502
577
          d = buf;
503
 
          for (x=0; x<u; x+=proc_size) {
 
578
 
 
579
          if(reverse) {
 
580
               x = u - proc_size;
 
581
          } else {
 
582
               x = 0;
 
583
          }
 
584
 
 
585
          while((x >= 0) && (x < u)) {
504
586
               if (proc(d+x,proc_size,chunk)) {
505
587
                    chunk_close(ch);
506
588
                    g_free(c);
507
589
                    status_bar_end_progress(bar);
508
590
                    return TRUE;
509
591
               }
510
 
          }
511
 
          samplesleft -= u / full_size;
512
 
          samplepos += u / full_size;
 
592
               if(reverse) {
 
593
                    x -= proc_size;
 
594
               } else {
 
595
                    x += proc_size;
 
596
               }
 
597
          }
 
598
 
 
599
          samplesleft -= readsamples;
 
600
          if(reverse) {
 
601
               samplepos -= readsamples;
 
602
               if(samplepos < 0) {
 
603
                    readsamples = readsamples + samplepos;
 
604
                    samplepos = 0;
 
605
               }
 
606
          } else {
 
607
               samplepos += readsamples;
 
608
          }
 
609
          if(samplesleft < readsamples) {
 
610
               readsamples = samplesleft;
 
611
          }
513
612
          if (status_bar_progress(bar, u / full_size)) {
514
613
               chunk_close(ch);
515
614
               g_free(c);
520
619
     chunk_close(ch);
521
620
     g_free(c);
522
621
     status_bar_end_progress(bar);
 
622
     clipwarn(clipcount,FALSE);
523
623
     return FALSE;
524
624
}
525
625
 
526
 
static gboolean chunk_onechannel_proc(void *in, guint sample_size, 
527
 
                                      chunk_writeout_func out_func, 
528
 
                                      WriteoutID id, Dataformat *format,
529
 
                                      Dataformat *outformat)
530
 
{
531
 
     static int channel_count = 0;
532
 
     static sample_t mixup = 0.0;
533
 
     sample_t s = *((sample_t *)in);
534
 
     mixup += s;
535
 
     channel_count++;
536
 
     if (channel_count == format->channels) {
537
 
          s = mixup / (sample_t)channel_count;
538
 
          channel_count = 0;
539
 
          mixup = 0.0;
540
 
          return out_func(id,&s,sizeof(s));
541
 
     } else 
542
 
          return FALSE;
543
 
}
544
 
 
545
626
Chunk *chunk_onechannel(Chunk *chunk, int dither_mode, StatusBar *bar)
546
627
{
547
 
     Dataformat fmt;
548
 
     memcpy(&fmt,&(chunk->format),sizeof(Dataformat));
549
 
     fmt.channels = 1;
550
 
     fmt.samplebytes = fmt.samplesize;
551
 
     return chunk_filter_tofmt(chunk,chunk_onechannel_proc,NULL,
552
 
                               CHUNK_FILTER_ONE,TRUE,&fmt,dither_mode,bar,
553
 
                               NULL);
554
 
}
555
 
 
556
 
static gint channel_to_copy;
557
 
 
558
 
static gboolean chunk_copy_channel_proc(void *in, guint sample_size, 
559
 
                                        chunk_writeout_func out_func, 
560
 
                                        WriteoutID id,
561
 
                                        Dataformat *informat, 
562
 
                                        Dataformat *outformat)
563
 
{
564
 
     static gint channel_count=0;
565
 
     gint i;
566
 
     i = channel_count;
567
 
     channel_count ++;
568
 
     if (channel_count == informat->channels) channel_count = 0;
569
 
     if (out_func(id,in,sample_size)) return TRUE;
570
 
     if (channel_to_copy==i) return out_func(id,in,sample_size);
571
 
     else return FALSE;
572
 
}
573
 
 
574
 
static gboolean chunk_copy_channel_mono_proc(void *in, guint sample_size,
575
 
                                             chunk_writeout_func out_func, 
576
 
                                             WriteoutID id,
577
 
                                             Dataformat *informat, 
578
 
                                             Dataformat *outformat)
579
 
{
580
 
     return (out_func(id,in,sample_size) || out_func(id,in,sample_size));
 
628
     gboolean *map;
 
629
     int i;
 
630
     Chunk *r;
 
631
     map = g_malloc(chunk->format.channels * 1 * sizeof(gboolean));
 
632
     for (i=0; i<chunk->format.channels; i++)
 
633
          map[i] = TRUE;
 
634
     r = chunk_remap_channels(chunk,1,map,dither_mode,bar);
 
635
     g_free(map);
 
636
     return r;
581
637
}
582
638
 
583
639
Chunk *chunk_copy_channel(Chunk *chunk, gint channel, int dither_mode, 
584
640
                          StatusBar *bar)
585
641
{
586
 
     Chunk *c;
587
 
     Dataformat fmt;
588
 
     memcpy(&fmt,&(chunk->format),sizeof(Dataformat));
589
 
     fmt.channels ++;
590
 
     fmt.samplebytes = fmt.channels * fmt.samplesize;
591
 
     channel_to_copy = channel;
592
 
     if (chunk->format.channels == 1) 
593
 
          c = chunk_filter_tofmt(chunk,chunk_copy_channel_mono_proc,NULL,
594
 
                                 CHUNK_FILTER_ONE,FALSE,&fmt,dither_mode,bar,
595
 
                                 NULL);
596
 
     else 
597
 
          c = chunk_filter_tofmt(chunk,chunk_copy_channel_proc,NULL,
598
 
                                 CHUNK_FILTER_ONE,FALSE,&fmt,dither_mode, 
599
 
                                 bar,NULL);
600
 
     return c;
 
642
     Chunk *r;
 
643
     gboolean *map;
 
644
     int i;
 
645
 
 
646
     map = g_malloc0(chunk->format.channels * (chunk->format.channels+1) * 
 
647
                     sizeof(gboolean));
 
648
     for (i=0; i<chunk->format.channels; i++)
 
649
          map[i*(chunk->format.channels+1) + i] = TRUE;
 
650
     map[channel*(chunk->format.channels+1) + (chunk->format.channels)] = TRUE;
 
651
     r = chunk_remap_channels(chunk,chunk->format.channels+1,map,dither_mode,
 
652
                              bar);
 
653
     g_free(map);
 
654
     return r;
601
655
}
602
656
 
603
657
 
606
660
     #define BUFLEN 256
607
661
     off_t u,mixlen;
608
662
     guint i,chn,x1,x2,x;
609
 
     guint clipcount = 0;
 
663
     off_t clipcount = 0;
610
664
     sample_t buf1[BUFLEN],buf2[BUFLEN],buf3[BUFLEN];
611
665
     sample_t s,pmax;
612
666
     gchar *str;
639
693
 
640
694
     for (u=0; u<mixlen; u+=x) {
641
695
 
642
 
          x1 = chunk_read_array_fp(ch1,u,BUFLEN/chn,buf1,dither_mode);
643
 
          x2 = chunk_read_array_fp(ch2,u,BUFLEN/chn,buf2,dither_mode);
 
696
          x1 = chunk_read_array_fp(ch1,u,BUFLEN/chn,buf1,dither_mode,
 
697
                                   &clipcount);
 
698
          x2 = chunk_read_array_fp(ch2,u,BUFLEN/chn,buf2,dither_mode,
 
699
                                   &clipcount);
644
700
          if (x1 == 0 || x2 == 0) {
645
701
               tempfile_abort(tmp);
646
702
               chunk_close(ch1);
687
743
 
688
744
     /* Warn if clipping occured */
689
745
     if (clipcount > 0) {
 
746
          if (clipcount > 1000000000) clipcount = 1000000000;
690
747
          str = g_strdup_printf(_("The mixed result was clipped %d times."),
691
 
                                clipcount);
 
748
                                (int)clipcount);
692
749
          user_warning(str);
693
750
          g_free(str);
694
751
     }
706
763
     return d;
707
764
}
708
765
 
 
766
static struct {
 
767
     sample_t *buf;
 
768
     int bufsize;
 
769
     /* (outchannels x (inchannels+1))-matrix */
 
770
     /* Each row has a list of input channel numbers, ending with -1 */
 
771
     int *map; 
 
772
} chunk_remap_channels_data;
 
773
 
 
774
static gboolean chunk_remap_channels_mixmode_proc(void *in, 
 
775
                                                  guint sample_size,
 
776
                                                  chunk_writeout_func out_func,
 
777
                                                  WriteoutID id,
 
778
                                                  Dataformat *informat,
 
779
                                                  Dataformat *outformat)
 
780
{
 
781
     int samps,i,j,k,l;
 
782
     sample_t *iptr, *optr, s;
 
783
     samps = sample_size / informat->samplebytes;
 
784
 
 
785
     /* Make sure we have room in the buffer */
 
786
     if (samps * outformat->samplebytes > chunk_remap_channels_data.bufsize) {
 
787
          g_free(chunk_remap_channels_data.buf);
 
788
          chunk_remap_channels_data.buf = 
 
789
               g_malloc(samps*outformat->samplebytes);
 
790
          chunk_remap_channels_data.bufsize = samps*outformat->samplebytes;
 
791
     }
 
792
 
 
793
     /* Process data */
 
794
     iptr = (sample_t *)in;
 
795
     optr = chunk_remap_channels_data.buf;
 
796
 
 
797
     for (i=0; i<samps; i++) {
 
798
          for (j=0; j<outformat->channels; j++) {
 
799
               s = 0.0;
 
800
               for (k=(j*(informat->channels+1)); 1; k++) {
 
801
                    l = chunk_remap_channels_data.map[k];
 
802
                    if (l < 0) break;
 
803
                    s += iptr[l];
 
804
               }
 
805
               optr[j] = s;
 
806
          }
 
807
          iptr += informat->channels;
 
808
          optr += outformat->channels;
 
809
     }
 
810
 
 
811
     return out_func(id, chunk_remap_channels_data.buf, 
 
812
                     samps*outformat->samplebytes);     
 
813
}
 
814
 
 
815
static gboolean chunk_remap_channels_rawmode_proc(void *in, 
 
816
                                                  guint sample_size,
 
817
                                                  chunk_writeout_func out_func,
 
818
                                                  WriteoutID id,
 
819
                                                  Dataformat *informat,
 
820
                                                  Dataformat *outformat)
 
821
{
 
822
     int samps,ssize=informat->samplesize,i,j,k;
 
823
     char *iptr, *optr;
 
824
 
 
825
     /* Make sure we have room in buffer */
 
826
     samps = sample_size / informat->samplebytes;
 
827
     if (samps * outformat->samplebytes > chunk_remap_channels_data.bufsize) {
 
828
          g_free(chunk_remap_channels_data.buf);
 
829
          chunk_remap_channels_data.buf = 
 
830
               g_malloc(samps*outformat->samplebytes);
 
831
          chunk_remap_channels_data.bufsize = samps*outformat->samplebytes;
 
832
     }
 
833
 
 
834
     iptr = (char *)in;
 
835
     optr = (char *)chunk_remap_channels_data.buf;
 
836
 
 
837
     /* This could be optimized further (replace memcpy) */
 
838
 
 
839
     for (i=0; i<samps; i++) {
 
840
          for (j=0; j<outformat->channels; j++) {
 
841
               k = chunk_remap_channels_data.map[j*(informat->channels+1)];
 
842
               if (k >= 0)
 
843
                    memcpy(optr, iptr+k*ssize,ssize);
 
844
               else
 
845
                    memset(optr, 0, ssize);
 
846
               optr += ssize;
 
847
          }
 
848
          iptr += informat->samplebytes;
 
849
     }
 
850
 
 
851
     return out_func(id, chunk_remap_channels_data.buf, 
 
852
                     samps*outformat->samplebytes);
 
853
}
 
854
                                                  
 
855
Chunk *chunk_remap_channels(Chunk *chunk, int channels_out, gboolean *map, 
 
856
                            int dither_mode, StatusBar *bar)
 
857
{
 
858
     gboolean mixmode;
 
859
     int i,j,k;
 
860
     int channels_in = chunk->format.channels;
 
861
     Dataformat tofmt;
 
862
     Chunk *r;
 
863
     
 
864
     memcpy(&tofmt,&(chunk->format),sizeof(Dataformat));
 
865
     tofmt.channels = channels_out;
 
866
     tofmt.samplebytes = tofmt.channels * tofmt.samplesize;
 
867
 
 
868
     chunk_remap_channels_data.buf = NULL;
 
869
     chunk_remap_channels_data.bufsize = 0;
 
870
 
 
871
     /* Generate the map */
 
872
     mixmode = FALSE;
 
873
     chunk_remap_channels_data.map = g_malloc((channels_in+1)*channels_out*
 
874
                                              sizeof(int));
 
875
     for (i=0; i<channels_out; i++) {
 
876
          k = 0;
 
877
          for (j=0; j<channels_in; j++) 
 
878
               if (map[j*channels_out + i])
 
879
                    chunk_remap_channels_data.map[i*(channels_in+1)+(k++)] = j;
 
880
          chunk_remap_channels_data.map[i*(channels_in+1) + k] = -1;
 
881
          if (k > 1) mixmode = TRUE;
 
882
     }
 
883
 
 
884
     if (mixmode) {
 
885
          r = chunk_filter_tofmt(chunk,chunk_remap_channels_mixmode_proc,
 
886
                                 NULL,CHUNK_FILTER_MANY,TRUE,&tofmt,
 
887
                                 dither_mode,bar,_("Mixing channels"));
 
888
     } else {
 
889
          r = chunk_filter_tofmt(chunk,chunk_remap_channels_rawmode_proc,
 
890
                                 NULL,CHUNK_FILTER_MANY,FALSE,&tofmt,
 
891
                                 dither_mode,bar,_("Mapping channels"));
 
892
          
 
893
     }
 
894
     
 
895
     g_free(chunk_remap_channels_data.buf);
 
896
     g_free(chunk_remap_channels_data.map);
 
897
     return r;
 
898
}
709
899
 
710
900
void chunk_foreach(GFunc func, gpointer user_data)
711
901
{
796
986
}
797
987
 
798
988
guint chunk_read_array(ChunkHandle *handle, off_t sampleno, 
799
 
                       guint size, void *buffer, int dither_mode)
 
989
                       guint size, void *buffer, int dither_mode, 
 
990
                       off_t *clipcount)
800
991
{
801
992
     GList *l;     
802
993
     DataPart *dp;
813
1004
               /* Read data. */
814
1005
               i = datasource_read_array(dp->ds,
815
1006
                                         dp->position + sampleno,
816
 
                                         j,buffer,dither_mode);
 
1007
                                         j,buffer,dither_mode,clipcount);
817
1008
               if (i == 0) return 0;
818
1009
               r+=i;
819
1010
               sampleno = 0;
827
1018
}
828
1019
 
829
1020
guint chunk_read_array_fp(ChunkHandle *handle, off_t sampleno, 
830
 
                          guint samples, sample_t *buffer, int dither_mode)
 
1021
                          guint samples, sample_t *buffer, int dither_mode,
 
1022
                          off_t *clipcount)
831
1023
{
832
1024
     GList *l;     
833
1025
     DataPart *dp;
844
1036
                    j = samples;
845
1037
               i = datasource_read_array_fp(dp->ds,
846
1038
                                            dp->position+sampleno,
847
 
                                            j,buffer,dither_mode);
 
1039
                                            j,buffer,dither_mode,clipcount);
848
1040
               g_assert(i <= samples);
849
1041
               g_assert(i <= dp->length - sampleno);
850
1042
               if (i==0) return 0;
1014
1206
     GList *nl=NULL,*l;
1015
1207
     DataPart *dp;
1016
1208
     guint i;
 
1209
     g_assert(dataformat_equal(&(chunk->format),&(new->format)));
1017
1210
     for (l=new->parts; l!=NULL; l=l->next)
1018
1211
          datapart_list_copy(l,&nl);
1019
1212
     c = chunk_remove_part(chunk,start,length);
1067
1260
     s = (sample_t)fabs((double)(*((sample_t *)sample)));
1068
1261
     if (s > chunk_peak_level_max) {
1069
1262
          chunk_peak_level_max = s;
1070
 
          if (s == 1.0) return TRUE;
 
1263
          if (s == 1.0 && chunk->format.type == DATAFORMAT_PCM) return TRUE;
1071
1264
     }
1072
1265
     return FALSE;
1073
1266
}
1076
1269
{
1077
1270
     chunk_peak_level_max = 0.0;
1078
1271
     if (chunk_parse(c,chunk_peak_level_proc,FALSE,TRUE,DITHER_NONE,bar,
1079
 
                     _("Calculating peak level"))) return -1.0;
 
1272
                     _("Calculating peak level"),0,FALSE)) return -1.0;
1080
1273
     return chunk_peak_level_max;
1081
1274
}
1082
1275
 
 
1276
/* BEGIN zero-crossing search added by Forest Bond */
 
1277
 
 
1278
static off_t chunk_zero_crossing_seen_samples;
 
1279
static sample_t *chunk_zero_crossing_saved_sample = NULL;
 
1280
 
 
1281
static gboolean chunk_signal_crossed_zero(sample_t prev, sample_t current)
 
1282
{
 
1283
     if((current >= 0.0) && (prev <= 0.0)) {
 
1284
          return TRUE;
 
1285
     } else if((current <= 0.0) && (prev >= 0.0)) {
 
1286
          return TRUE;
 
1287
     }
 
1288
     return FALSE;
 
1289
}
 
1290
 
 
1291
static void chunk_zero_crossing_init(gint sample_size) {
 
1292
     if(chunk_zero_crossing_saved_sample != NULL) {
 
1293
          g_free(chunk_zero_crossing_saved_sample);
 
1294
          chunk_zero_crossing_saved_sample = NULL;
 
1295
     }
 
1296
     chunk_zero_crossing_saved_sample = g_malloc(sample_size);
 
1297
}
 
1298
 
 
1299
static void chunk_zero_crossing_cleanup() {
 
1300
     if(chunk_zero_crossing_saved_sample != NULL) {
 
1301
          g_free(chunk_zero_crossing_saved_sample);
 
1302
          chunk_zero_crossing_saved_sample = NULL;
 
1303
     }
 
1304
}
 
1305
 
 
1306
static void chunk_zero_crossing_save_sample(sample_t *sample,
 
1307
  gint sample_size) {
 
1308
     memcpy(chunk_zero_crossing_saved_sample, sample, sample_size);
 
1309
}
 
1310
 
 
1311
static gboolean chunk_zero_crossing_any_proc(void *sample, gint sample_size, 
 
1312
                                      Chunk *chunk)
 
1313
{
 
1314
     sample_t *start = (sample_t *)sample;
 
1315
     sample_t *end = start + (sample_size/sizeof(sample_t));
 
1316
     sample_t *current = start;
 
1317
     sample_t *prev = chunk_zero_crossing_saved_sample;
 
1318
 
 
1319
     if(chunk_zero_crossing_seen_samples < 1) {
 
1320
          chunk_zero_crossing_init(sample_size);
 
1321
          chunk_zero_crossing_save_sample(start, sample_size);
 
1322
          chunk_zero_crossing_seen_samples++;
 
1323
          return FALSE;
 
1324
     }
 
1325
 
 
1326
     while(current < end) {
 
1327
          if(chunk_signal_crossed_zero(*prev, *current)) {
 
1328
               return TRUE;
 
1329
          }
 
1330
          current++;
 
1331
          prev++;
 
1332
     }
 
1333
 
 
1334
     chunk_zero_crossing_save_sample(start, sample_size);
 
1335
     chunk_zero_crossing_seen_samples++;
 
1336
     return FALSE;
 
1337
}
 
1338
 
 
1339
off_t chunk_zero_crossing_any_forward(Chunk *c, StatusBar *bar,off_t samplepos)
 
1340
{
 
1341
     chunk_zero_crossing_seen_samples = 0;
 
1342
     chunk_parse(c,chunk_zero_crossing_any_proc,TRUE,TRUE,DITHER_NONE,bar,
 
1343
                     _("Finding zero-crossing"), samplepos, FALSE);
 
1344
 
 
1345
     chunk_zero_crossing_cleanup();
 
1346
     return samplepos + chunk_zero_crossing_seen_samples;
 
1347
}
 
1348
 
 
1349
off_t chunk_zero_crossing_any_reverse(Chunk *c, StatusBar *bar,off_t samplepos)
 
1350
{
 
1351
     chunk_zero_crossing_seen_samples = 0;
 
1352
     chunk_parse(c,chunk_zero_crossing_any_proc,TRUE,TRUE,DITHER_NONE,bar,
 
1353
                     _("Finding zero-crossing"), samplepos, TRUE);
 
1354
 
 
1355
     chunk_zero_crossing_cleanup();
 
1356
     return samplepos - chunk_zero_crossing_seen_samples;
 
1357
}
 
1358
 
 
1359
static gboolean chunk_zero_crossing_all_proc(void *sample, gint sample_size, 
 
1360
                                      Chunk *chunk)
 
1361
{
 
1362
     sample_t *start = (sample_t *)sample;
 
1363
     sample_t *end = start + (sample_size/sizeof(sample_t));
 
1364
     sample_t *current = start;
 
1365
     sample_t *prev = chunk_zero_crossing_saved_sample;
 
1366
 
 
1367
     if(chunk_zero_crossing_seen_samples < 1) {
 
1368
          chunk_zero_crossing_init(sample_size);
 
1369
          chunk_zero_crossing_save_sample(start, sample_size);
 
1370
          chunk_zero_crossing_seen_samples++;
 
1371
          return FALSE;
 
1372
     }
 
1373
 
 
1374
     while(current < end) {
 
1375
 
 
1376
          if(! chunk_signal_crossed_zero(*prev, *current)) {
 
1377
               chunk_zero_crossing_save_sample(start, sample_size);
 
1378
               chunk_zero_crossing_seen_samples++;
 
1379
               return FALSE;
 
1380
          }
 
1381
          current++;
 
1382
          prev++;
 
1383
     }
 
1384
     return TRUE;
 
1385
}
 
1386
 
 
1387
off_t chunk_zero_crossing_all_forward(Chunk *c, StatusBar *bar,off_t samplepos)
 
1388
{
 
1389
     chunk_zero_crossing_seen_samples = 0;
 
1390
     chunk_parse(c,chunk_zero_crossing_all_proc,TRUE,TRUE,DITHER_NONE,bar,
 
1391
                     _("Finding zero-crossing"), samplepos, FALSE);
 
1392
 
 
1393
     chunk_zero_crossing_cleanup();
 
1394
     return samplepos + chunk_zero_crossing_seen_samples;
 
1395
}
 
1396
 
 
1397
off_t chunk_zero_crossing_all_reverse(Chunk *c, StatusBar *bar,off_t samplepos)
 
1398
{
 
1399
     chunk_zero_crossing_seen_samples = 0;
 
1400
     chunk_parse(c,chunk_zero_crossing_all_proc,TRUE,TRUE,DITHER_NONE,bar,
 
1401
                     _("Finding zero-crossing"), samplepos, TRUE);
 
1402
 
 
1403
     chunk_zero_crossing_cleanup();
 
1404
 
 
1405
     return samplepos - chunk_zero_crossing_seen_samples;
 
1406
}
 
1407
 
 
1408
/* END zero-crossing search */
 
1409
 
1083
1410
static sample_t chunk_amplify_factor;
1084
1411
 
1085
1412
static gboolean chunk_amplify_proc(void *in, guint sample_size,
1136
1463
                         dither_mode, bar, _("Amplifying"));
1137
1464
}
1138
1465
 
1139
 
Chunk *chunk_interpolate_endpoints(Chunk *chunk, int dither_mode, 
1140
 
                                   StatusBar *bar)
 
1466
Chunk *chunk_new_with_ramp(Dataformat *format, off_t length, 
 
1467
                           sample_t *startvals, sample_t *endvals, 
 
1468
                           int dither_mode, StatusBar *bar)
1141
1469
{
1142
1470
#define BUF_LENGTH 512
1143
 
     sample_t startval[8],diffval[8];
1144
 
     sample_t *sbuf;
1145
 
     off_t ctr=0,length=chunk->length;
1146
 
     guint bufctr;
1147
 
     guint i;
 
1471
     int i,k;
 
1472
     sample_t diffval[8], *sbuf;
1148
1473
     sample_t slength = (sample_t)length;
1149
 
     guint k,channels=chunk->format.channels;
1150
 
     Dataformat fmt;
1151
 
     ChunkHandle *ch;
1152
1474
     TempFile tf;
 
1475
     off_t ctr = 0;
 
1476
     int channels = format->channels;
 
1477
     int bufctr;
 
1478
     Dataformat fmt;
1153
1479
     Chunk *r,*q;
1154
 
     /* get the endpoint values */
1155
 
     ch = chunk_open(chunk);
1156
 
     if (ch == NULL) return NULL;
1157
 
     if (chunk_read_fp(ch,0,startval,dither_mode) || 
1158
 
         chunk_read_fp(ch,length-1,diffval,dither_mode)) { 
1159
 
          chunk_close(ch);
1160
 
          return NULL;
1161
 
     }
1162
 
     chunk_close(ch);
1163
 
     for (k=0;k<channels;k++) {
1164
 
          diffval[k]-=startval[k];
1165
 
          /* printf("%f %f\n",startval[k],diffval[k]); */
1166
 
     }
1167
 
     /* Prepare processing */
 
1480
 
 
1481
     g_assert(channels <= 8);
 
1482
 
 
1483
     for (i=0; i<channels; i++)
 
1484
          diffval[i] = endvals[i] - startvals[i];
 
1485
     
1168
1486
     memcpy(&fmt,&dataformat_sample_t,sizeof(Dataformat));
1169
1487
     fmt.channels = channels;
1170
 
     fmt.samplerate = chunk->format.samplerate;
 
1488
     fmt.samplerate = format->samplerate;
1171
1489
     fmt.samplebytes = fmt.channels * fmt.samplesize;
1172
1490
     tf = tempfile_init(&fmt,FALSE);
1173
1491
     if (tf == NULL) return NULL;
1174
 
     status_bar_begin_progress(bar,chunk->length,NULL);
 
1492
 
 
1493
     status_bar_begin_progress(bar,length,NULL);
1175
1494
     sbuf = g_malloc(BUF_LENGTH*sizeof(sample_t));
 
1495
 
1176
1496
     /* Output data */
1177
1497
     while (ctr < length) {
1178
1498
          bufctr = BUF_LENGTH / channels;
1179
1499
          if ((length-ctr) < (off_t)bufctr) bufctr = (guint)(length-ctr);
1180
1500
          for (i=0; i<bufctr*channels; i+=channels,ctr++)
1181
1501
               for (k=0; k<channels; k++)
1182
 
                    sbuf[i+k] = startval[k] + 
 
1502
                    sbuf[i+k] = startvals[k] + 
1183
1503
                         diffval[k]*(((sample_t)ctr)/slength);
1184
1504
          if (tempfile_write(tf,sbuf,bufctr*channels*sizeof(sample_t)) ||
1185
1505
              status_bar_progress(bar,bufctr)) {
1193
1513
     g_free(sbuf);
1194
1514
     r = tempfile_finished(tf);
1195
1515
     status_bar_end_progress(bar);
1196
 
     if (r!=NULL && !dataformat_equal(&(r->format),&(chunk->format))) {
1197
 
       q = chunk_convert_sampletype(r,&(chunk->format));
 
1516
     if (r!=NULL && !dataformat_equal(&(r->format),format)) {
 
1517
       q = chunk_convert_sampletype(r,format);
1198
1518
       gtk_object_sink(GTK_OBJECT(r));
1199
1519
       return q;
1200
1520
     } else 
1201
1521
       return r;
1202
 
          
 
1522
     
1203
1523
#undef BUF_LENGTH
1204
1524
}
1205
1525
 
 
1526
Chunk *chunk_interpolate_endpoints(Chunk *chunk, gboolean falldown_mode, 
 
1527
                                   int dither_mode, StatusBar *bar)
 
1528
{
 
1529
     int i;
 
1530
     Chunk *start,*mid,*end,*c,*d;
 
1531
     ChunkHandle *ch;     
 
1532
 
 
1533
     sample_t startval[8],endval[8],zeroval[8];
 
1534
     off_t length = chunk->length;
 
1535
 
 
1536
     /* get the endpoint values */
 
1537
     ch = chunk_open(chunk);
 
1538
     if (ch == NULL) return NULL;
 
1539
     if (chunk_read_fp(ch,0,startval,dither_mode) || 
 
1540
         chunk_read_fp(ch,length-1,endval,dither_mode)) { 
 
1541
          chunk_close(ch);
 
1542
          return NULL;
 
1543
     }
 
1544
     chunk_close(ch);
 
1545
     memset(zeroval,0,sizeof(zeroval));
 
1546
 
 
1547
     /* Length of 0.1 s in samples */
 
1548
     i = chunk->format.samplerate / 10;
 
1549
     if (i < 1) i=1;
 
1550
 
 
1551
     if (!falldown_mode || chunk->length <= 2*i) {
 
1552
          return chunk_new_with_ramp(&(chunk->format),chunk->length,startval,
 
1553
                                     endval,dither_mode,bar);
 
1554
     } else {
 
1555
          start = chunk_new_with_ramp(&(chunk->format),i,startval,zeroval,
 
1556
                                      dither_mode,bar);
 
1557
          if (start == NULL) return NULL;
 
1558
          end = chunk_new_with_ramp(&(chunk->format),i,zeroval,endval,
 
1559
                                    dither_mode,bar);
 
1560
          if (end == NULL) {
 
1561
               gtk_object_sink(GTK_OBJECT(start));
 
1562
               return NULL;
 
1563
          }
 
1564
          mid = chunk_new_empty(&(chunk->format),chunk->length-2*i);
 
1565
          g_assert(mid != NULL);
 
1566
          
 
1567
          c = chunk_append(start,mid);
 
1568
          d = chunk_append(c,end);
 
1569
 
 
1570
          gtk_object_sink(GTK_OBJECT(start));
 
1571
          gtk_object_sink(GTK_OBJECT(mid));
 
1572
          gtk_object_sink(GTK_OBJECT(end));
 
1573
          gtk_object_sink(GTK_OBJECT(c));
 
1574
          return d;
 
1575
          
 
1576
     }
 
1577
}
 
1578
 
1206
1579
Chunk *chunk_byteswap(Chunk *chunk)
1207
1580
{
 
1581
     Chunk *c,*d;
1208
1582
     Dataformat fmt;
1209
1583
     memcpy(&fmt,&(chunk->format),sizeof(Dataformat));
1210
1584
     fmt.bigendian = !fmt.bigendian;
1211
 
     return chunk_clone_df(chunk,&fmt);
 
1585
     c = chunk_clone_df(chunk,&fmt);
 
1586
     d = chunk_convert(c,&(chunk->format),DITHER_UNSPEC,NULL);
 
1587
     gtk_object_sink(GTK_OBJECT(c)); 
 
1588
     return d;
1212
1589
}
1213
1590
 
1214
1591
static gboolean chunk_convert_channels_down_proc(void *in, guint sample_size,
1313
1690
     if (c != NULL) gtk_object_sink(GTK_OBJECT(c));
1314
1691
     return d;
1315
1692
}
 
1693
 
 
1694
gboolean clipwarn(off_t clipcount, gboolean maycancel)
 
1695
{
 
1696
     gboolean b = FALSE;
 
1697
     gchar *c;
 
1698
     if (clipcount > 0) {
 
1699
          if (clipcount > 1000000000)
 
1700
               clipcount = 1000000000;
 
1701
          c = g_strdup_printf(_("The input was clipped %d times during "
 
1702
                                "processing."),(int)clipcount);
 
1703
          if (maycancel)
 
1704
               b = (user_message(c,UM_OKCANCEL) != MR_OK);
 
1705
          else
 
1706
               user_warning(c);
 
1707
          
 
1708
          g_free(c);
 
1709
     }
 
1710
 
 
1711
     return b;
 
1712
}