349
355
Dataformat *tofmt, int dither_mode,
350
356
StatusBar *bar, gchar *title)
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)
365
* These modes are possible:
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)
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)
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)
352
388
guint proc_size,single_size,full_size;
354
390
off_t samplepos=0, samplesleft=chunk->length;
482
539
if (allchannels) proc_size = full_size;
483
540
else proc_size = single_size;
542
readsamples = sizeof(buf) / full_size;
543
if(samplesleft < readsamples) {
544
readsamples = samplesleft;
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);
490
551
while (samplesleft > 0) {
492
u = chunk_read_array_fp(ch,samplepos,sizeof(buf)/full_size,
493
(sample_t *)buf,dither_mode)*full_size;
495
u = chunk_read_array(ch,samplepos,sizeof(buf),buf,dither_mode);
553
readpos = samplepos - readsamples;
559
u = chunk_read_array_fp(ch,readpos,
561
(sample_t *)buf,dither_mode,&clipcount);
564
u = chunk_read_array(ch,readpos,readsamples * full_size,
565
buf,dither_mode,&clipcount);
568
g_assert((u / full_size) == readsamples);
499
573
status_bar_end_progress(bar);
503
for (x=0; x<u; x+=proc_size) {
585
while((x >= 0) && (x < u)) {
504
586
if (proc(d+x,proc_size,chunk)) {
507
589
status_bar_end_progress(bar);
511
samplesleft -= u / full_size;
512
samplepos += u / full_size;
599
samplesleft -= readsamples;
601
samplepos -= readsamples;
603
readsamples = readsamples + samplepos;
607
samplepos += readsamples;
609
if(samplesleft < readsamples) {
610
readsamples = samplesleft;
513
612
if (status_bar_progress(bar, u / full_size)) {
522
621
status_bar_end_progress(bar);
622
clipwarn(clipcount,FALSE);
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)
531
static int channel_count = 0;
532
static sample_t mixup = 0.0;
533
sample_t s = *((sample_t *)in);
536
if (channel_count == format->channels) {
537
s = mixup / (sample_t)channel_count;
540
return out_func(id,&s,sizeof(s));
545
626
Chunk *chunk_onechannel(Chunk *chunk, int dither_mode, StatusBar *bar)
548
memcpy(&fmt,&(chunk->format),sizeof(Dataformat));
550
fmt.samplebytes = fmt.samplesize;
551
return chunk_filter_tofmt(chunk,chunk_onechannel_proc,NULL,
552
CHUNK_FILTER_ONE,TRUE,&fmt,dither_mode,bar,
556
static gint channel_to_copy;
558
static gboolean chunk_copy_channel_proc(void *in, guint sample_size,
559
chunk_writeout_func out_func,
561
Dataformat *informat,
562
Dataformat *outformat)
564
static gint channel_count=0;
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);
574
static gboolean chunk_copy_channel_mono_proc(void *in, guint sample_size,
575
chunk_writeout_func out_func,
577
Dataformat *informat,
578
Dataformat *outformat)
580
return (out_func(id,in,sample_size) || out_func(id,in,sample_size));
631
map = g_malloc(chunk->format.channels * 1 * sizeof(gboolean));
632
for (i=0; i<chunk->format.channels; i++)
634
r = chunk_remap_channels(chunk,1,map,dither_mode,bar);
583
639
Chunk *chunk_copy_channel(Chunk *chunk, gint channel, int dither_mode,
588
memcpy(&fmt,&(chunk->format),sizeof(Dataformat));
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,
597
c = chunk_filter_tofmt(chunk,chunk_copy_channel_proc,NULL,
598
CHUNK_FILTER_ONE,FALSE,&fmt,dither_mode,
646
map = g_malloc0(chunk->format.channels * (chunk->format.channels+1) *
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,
769
/* (outchannels x (inchannels+1))-matrix */
770
/* Each row has a list of input channel numbers, ending with -1 */
772
} chunk_remap_channels_data;
774
static gboolean chunk_remap_channels_mixmode_proc(void *in,
776
chunk_writeout_func out_func,
778
Dataformat *informat,
779
Dataformat *outformat)
782
sample_t *iptr, *optr, s;
783
samps = sample_size / informat->samplebytes;
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;
794
iptr = (sample_t *)in;
795
optr = chunk_remap_channels_data.buf;
797
for (i=0; i<samps; i++) {
798
for (j=0; j<outformat->channels; j++) {
800
for (k=(j*(informat->channels+1)); 1; k++) {
801
l = chunk_remap_channels_data.map[k];
807
iptr += informat->channels;
808
optr += outformat->channels;
811
return out_func(id, chunk_remap_channels_data.buf,
812
samps*outformat->samplebytes);
815
static gboolean chunk_remap_channels_rawmode_proc(void *in,
817
chunk_writeout_func out_func,
819
Dataformat *informat,
820
Dataformat *outformat)
822
int samps,ssize=informat->samplesize,i,j,k;
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;
835
optr = (char *)chunk_remap_channels_data.buf;
837
/* This could be optimized further (replace memcpy) */
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)];
843
memcpy(optr, iptr+k*ssize,ssize);
845
memset(optr, 0, ssize);
848
iptr += informat->samplebytes;
851
return out_func(id, chunk_remap_channels_data.buf,
852
samps*outformat->samplebytes);
855
Chunk *chunk_remap_channels(Chunk *chunk, int channels_out, gboolean *map,
856
int dither_mode, StatusBar *bar)
860
int channels_in = chunk->format.channels;
864
memcpy(&tofmt,&(chunk->format),sizeof(Dataformat));
865
tofmt.channels = channels_out;
866
tofmt.samplebytes = tofmt.channels * tofmt.samplesize;
868
chunk_remap_channels_data.buf = NULL;
869
chunk_remap_channels_data.bufsize = 0;
871
/* Generate the map */
873
chunk_remap_channels_data.map = g_malloc((channels_in+1)*channels_out*
875
for (i=0; i<channels_out; i++) {
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;
885
r = chunk_filter_tofmt(chunk,chunk_remap_channels_mixmode_proc,
886
NULL,CHUNK_FILTER_MANY,TRUE,&tofmt,
887
dither_mode,bar,_("Mixing channels"));
889
r = chunk_filter_tofmt(chunk,chunk_remap_channels_rawmode_proc,
890
NULL,CHUNK_FILTER_MANY,FALSE,&tofmt,
891
dither_mode,bar,_("Mapping channels"));
895
g_free(chunk_remap_channels_data.buf);
896
g_free(chunk_remap_channels_data.map);
710
900
void chunk_foreach(GFunc func, gpointer user_data)
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;
1276
/* BEGIN zero-crossing search added by Forest Bond */
1278
static off_t chunk_zero_crossing_seen_samples;
1279
static sample_t *chunk_zero_crossing_saved_sample = NULL;
1281
static gboolean chunk_signal_crossed_zero(sample_t prev, sample_t current)
1283
if((current >= 0.0) && (prev <= 0.0)) {
1285
} else if((current <= 0.0) && (prev >= 0.0)) {
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;
1296
chunk_zero_crossing_saved_sample = g_malloc(sample_size);
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;
1306
static void chunk_zero_crossing_save_sample(sample_t *sample,
1308
memcpy(chunk_zero_crossing_saved_sample, sample, sample_size);
1311
static gboolean chunk_zero_crossing_any_proc(void *sample, gint sample_size,
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;
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++;
1326
while(current < end) {
1327
if(chunk_signal_crossed_zero(*prev, *current)) {
1334
chunk_zero_crossing_save_sample(start, sample_size);
1335
chunk_zero_crossing_seen_samples++;
1339
off_t chunk_zero_crossing_any_forward(Chunk *c, StatusBar *bar,off_t samplepos)
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);
1345
chunk_zero_crossing_cleanup();
1346
return samplepos + chunk_zero_crossing_seen_samples;
1349
off_t chunk_zero_crossing_any_reverse(Chunk *c, StatusBar *bar,off_t samplepos)
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);
1355
chunk_zero_crossing_cleanup();
1356
return samplepos - chunk_zero_crossing_seen_samples;
1359
static gboolean chunk_zero_crossing_all_proc(void *sample, gint sample_size,
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;
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++;
1374
while(current < end) {
1376
if(! chunk_signal_crossed_zero(*prev, *current)) {
1377
chunk_zero_crossing_save_sample(start, sample_size);
1378
chunk_zero_crossing_seen_samples++;
1387
off_t chunk_zero_crossing_all_forward(Chunk *c, StatusBar *bar,off_t samplepos)
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);
1393
chunk_zero_crossing_cleanup();
1394
return samplepos + chunk_zero_crossing_seen_samples;
1397
off_t chunk_zero_crossing_all_reverse(Chunk *c, StatusBar *bar,off_t samplepos)
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);
1403
chunk_zero_crossing_cleanup();
1405
return samplepos - chunk_zero_crossing_seen_samples;
1408
/* END zero-crossing search */
1083
1410
static sample_t chunk_amplify_factor;
1085
1412
static gboolean chunk_amplify_proc(void *in, guint sample_size,
1136
1463
dither_mode, bar, _("Amplifying"));
1139
Chunk *chunk_interpolate_endpoints(Chunk *chunk, int dither_mode,
1466
Chunk *chunk_new_with_ramp(Dataformat *format, off_t length,
1467
sample_t *startvals, sample_t *endvals,
1468
int dither_mode, StatusBar *bar)
1142
1470
#define BUF_LENGTH 512
1143
sample_t startval[8],diffval[8];
1145
off_t ctr=0,length=chunk->length;
1472
sample_t diffval[8], *sbuf;
1148
1473
sample_t slength = (sample_t)length;
1149
guint k,channels=chunk->format.channels;
1476
int channels = format->channels;
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)) {
1163
for (k=0;k<channels;k++) {
1164
diffval[k]-=startval[k];
1165
/* printf("%f %f\n",startval[k],diffval[k]); */
1167
/* Prepare processing */
1481
g_assert(channels <= 8);
1483
for (i=0; i<channels; i++)
1484
diffval[i] = endvals[i] - startvals[i];
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);
1493
status_bar_begin_progress(bar,length,NULL);
1175
1494
sbuf = g_malloc(BUF_LENGTH*sizeof(sample_t));
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)) {
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));
1203
1523
#undef BUF_LENGTH
1526
Chunk *chunk_interpolate_endpoints(Chunk *chunk, gboolean falldown_mode,
1527
int dither_mode, StatusBar *bar)
1530
Chunk *start,*mid,*end,*c,*d;
1533
sample_t startval[8],endval[8],zeroval[8];
1534
off_t length = chunk->length;
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)) {
1545
memset(zeroval,0,sizeof(zeroval));
1547
/* Length of 0.1 s in samples */
1548
i = chunk->format.samplerate / 10;
1551
if (!falldown_mode || chunk->length <= 2*i) {
1552
return chunk_new_with_ramp(&(chunk->format),chunk->length,startval,
1553
endval,dither_mode,bar);
1555
start = chunk_new_with_ramp(&(chunk->format),i,startval,zeroval,
1557
if (start == NULL) return NULL;
1558
end = chunk_new_with_ramp(&(chunk->format),i,zeroval,endval,
1561
gtk_object_sink(GTK_OBJECT(start));
1564
mid = chunk_new_empty(&(chunk->format),chunk->length-2*i);
1565
g_assert(mid != NULL);
1567
c = chunk_append(start,mid);
1568
d = chunk_append(c,end);
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));
1206
1579
Chunk *chunk_byteswap(Chunk *chunk)
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));
1214
1591
static gboolean chunk_convert_channels_down_proc(void *in, guint sample_size,