History

avfilter/avf_showcwt: switch to overlap-save

And do both left and right zero-padding for forward FFT.

Paul B Mahol committed 3 years ago

Commit 32a22681 parent 830e5221 file · +33 −22Browse files

Unified · Split

libavfilter/avf_showcwt.c+33−22
@@ -90,6 +90,7 @@ typedef struct ShowCWTContext { · 89 unmodified lines
90 AVFrame *ifft_in;90 AVFrame *ifft_in;
91 AVFrame *ifft_out;91 AVFrame *ifft_out;
92 AVFrame *ch_out;92 AVFrame *ch_out;
93 AVFrame *over;
93 AVFrame *bh_out;94 AVFrame *bh_out;
94 int nb_threads;95 int nb_threads;
95 int nb_channels;96 int nb_channels;
@@ -177,6 +178,7 @@ static av_cold void uninit(AVFilterContext *ctx) · 81 unmodified lines
177 av_frame_free(&s->ifft_in);178 av_frame_free(&s->ifft_in);
178 av_frame_free(&s->ifft_out);179 av_frame_free(&s->ifft_out);
179 av_frame_free(&s->ch_out);180 av_frame_free(&s->ch_out);
181 av_frame_free(&s->over);
180 av_frame_free(&s->bh_out);182 av_frame_free(&s->bh_out);
181 183
182 if (s->fft) {184 if (s->fft) {
@@ -290,25 +292,27 @@ static int run_channel_cwt_prepare(AVFilterContext *ctx, void *arg, int jobnr, i · 107 unmodified lines
290 ShowCWTContext *s = ctx->priv;292 ShowCWTContext *s = ctx->priv;
291 const int hop_size = s->hop_size;293 const int hop_size = s->hop_size;
292 AVFrame *fin = arg;294 AVFrame *fin = arg;
293 AVComplexFloat *cache = (AVComplexFloat *)s->cache->extended_data[ch];295 float *cache = (float *)s->cache->extended_data[ch];
294 AVComplexFloat *src = (AVComplexFloat *)s->fft_in->extended_data[ch];296 AVComplexFloat *src = (AVComplexFloat *)s->fft_in->extended_data[ch];
295 AVComplexFloat *dst = (AVComplexFloat *)s->fft_out->extended_data[ch];297 AVComplexFloat *dst = (AVComplexFloat *)s->fft_out->extended_data[ch];
298 const int offset = (s->input_padding_size - hop_size) >> 1;
296 299
297 if (fin) {300 if (fin) {
298 const float *input = (const float *)fin->extended_data[ch];301 const float *input = (const float *)fin->extended_data[ch];
299 const int offset = s->input_padding_size - fin->nb_samples;302 const int offset = s->hop_size - fin->nb_samples;
300 303
301 memmove(cache, cache + fin->nb_samples, sizeof(*cache) * offset);304 memmove(cache, &cache[fin->nb_samples], offset * sizeof(float));
302 for (int n = 0; n < fin->nb_samples; n++) {305 memcpy(&cache[offset], input, fin->nb_samples * sizeof(float));
303 cache[offset + n].re = input[n];
304 cache[offset + n].im = 0.f;
305 }
306 }306 }
307 307
308 if (fin && s->hop_index + fin->nb_samples < hop_size)308 if (fin && s->hop_index + fin->nb_samples < hop_size)
309 return 0;309 return 0;
310 310
311 memcpy(src, cache, sizeof(*src) * s->input_padding_size);311 memset(src, 0, sizeof(float) * s->fft_in_size);
312 for (int n = 0; n < hop_size; n++) {
313 src[n+offset].re = cache[n];
314 src[n+offset].im = 0.f;
315 }
312 316
313 s->tx_fn(s->fft[jobnr], dst, src, sizeof(*src));317 s->tx_fn(s->fft[jobnr], dst, src, sizeof(*src));
314 318
@@ -582,20 +586,20 @@ static int run_channel_cwt(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo · 267 unmodified lines
582 AVComplexFloat *idst = (AVComplexFloat *)s->ifft_out->extended_data[jobnr];586 AVComplexFloat *idst = (AVComplexFloat *)s->ifft_out->extended_data[jobnr];
583 const int output_padding_size = s->output_padding_size;587 const int output_padding_size = s->output_padding_size;
584 const int ihop_size = s->ihop_size;588 const int ihop_size = s->ihop_size;
585 const int ioffset = (output_padding_size - ihop_size) >> 1;
586 const int count = s->frequency_band_count;589 const int count = s->frequency_band_count;
587 const int start = (count * jobnr) / nb_jobs;590 const int start = (count * jobnr) / nb_jobs;
588 const int end = (count * (jobnr+1)) / nb_jobs;591 const int end = (count * (jobnr+1)) / nb_jobs;
589 592
590 for (int y = start; y < end; y++) {593 for (int y = start; y < end; y++) {
591 AVComplexFloat *chout = ((AVComplexFloat *)s->ch_out->extended_data[ch]) + y * ihop_size;594 AVComplexFloat *chout = ((AVComplexFloat *)s->ch_out->extended_data[ch]) + y * ihop_size;
595 AVComplexFloat *over = ((AVComplexFloat *)s->over->extended_data[ch]) + y * ihop_size;
592 AVComplexFloat *dstx = (AVComplexFloat *)s->dst_x->extended_data[jobnr];596 AVComplexFloat *dstx = (AVComplexFloat *)s->dst_x->extended_data[jobnr];
593 AVComplexFloat *srcx = (AVComplexFloat *)s->src_x->extended_data[jobnr];597 AVComplexFloat *srcx = (AVComplexFloat *)s->src_x->extended_data[jobnr];
594 const AVComplexFloat *kernel = s->kernel[y];598 const AVComplexFloat *kernel = s->kernel[y];
595 const unsigned *index = (const unsigned *)s->index;599 const unsigned *index = (const unsigned *)s->index;
596 const int kernel_start = s->kernel_start[y];600 const int kernel_start = s->kernel_start[y];
597 const int kernel_stop = s->kernel_stop[y];601 const int kernel_stop = s->kernel_stop[y];
598 const int kernel_range = kernel_stop - kernel_start;602 const int kernel_range = kernel_stop - kernel_start + 1;
599 603
600 memcpy(srcx, fft_out + kernel_start, sizeof(*fft_out) * kernel_range);604 memcpy(srcx, fft_out + kernel_start, sizeof(*fft_out) * kernel_range);
601 605
@@ -612,7 +616,12 @@ static int run_channel_cwt(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo · 10 unmodified lines
612 616
613 s->itx_fn(s->ifft[jobnr], idst, isrc, sizeof(*isrc));617 s->itx_fn(s->ifft[jobnr], idst, isrc, sizeof(*isrc));
614 618
615 memcpy(chout, idst + ioffset, sizeof(*chout) * ihop_size);619 memcpy(chout, idst, sizeof(*chout) * ihop_size);
620 for (int n = 0; n < ihop_size; n++) {
621 chout[n].re += over[n].re;
622 chout[n].im += over[n].im;
623 }
624 memcpy(over, idst + ihop_size, sizeof(*over) * ihop_size);
616 }625 }
617 626
618 return 0;627 return 0;
@@ -742,12 +751,12 @@ static int config_output(AVFilterLink *outlink) · 123 unmodified lines
742 s->eof_pts = AV_NOPTS_VALUE;751 s->eof_pts = AV_NOPTS_VALUE;
743 s->nb_consumed_samples = FFMIN(65536, inlink->sample_rate);752 s->nb_consumed_samples = FFMIN(65536, inlink->sample_rate);
744 753
745 s->input_sample_count = s->nb_consumed_samples;754 s->input_sample_count = 1 << (32 - ff_clz(s->nb_consumed_samples));
746 s->input_padding_size = 1 << (32 - ff_clz(s->input_sample_count));755 s->input_padding_size = 1 << (32 - ff_clz(s->input_sample_count));
747 s->output_sample_count = FFMAX(1, av_rescale(s->input_sample_count, s->pps, inlink->sample_rate));756 s->output_sample_count = FFMAX(1, av_rescale(s->input_sample_count, s->pps, inlink->sample_rate));
748 s->output_padding_size = 1 << (32 - ff_clz(s->output_sample_count));757 s->output_padding_size = 1 << (32 - ff_clz(s->output_sample_count));
749 758
750 s->hop_size = s->input_padding_size >> 1;759 s->hop_size = s->input_sample_count;
751 s->ihop_size = s->output_padding_size >> 1;760 s->ihop_size = s->output_padding_size >> 1;
752 761
753 outlink->w = s->w;762 outlink->w = s->w;
@@ -757,7 +766,7 @@ static int config_output(AVFilterLink *outlink) · 3 unmodified lines
757 s->fft_in_size = FFALIGN(s->input_padding_size, av_cpu_max_align());766 s->fft_in_size = FFALIGN(s->input_padding_size, av_cpu_max_align());
758 s->fft_out_size = FFALIGN(s->input_padding_size, av_cpu_max_align());767 s->fft_out_size = FFALIGN(s->input_padding_size, av_cpu_max_align());
759 768
760 s->ifft_in_size = FFALIGN(s->output_padding_size, av_cpu_max_align());769 s->ifft_in_size = FFALIGN(s->output_padding_size, av_cpu_max_align());
761 s->ifft_out_size = FFALIGN(s->output_padding_size, av_cpu_max_align());770 s->ifft_out_size = FFALIGN(s->output_padding_size, av_cpu_max_align());
762 771
763 s->fft = av_calloc(s->nb_threads, sizeof(*s->fft));772 s->fft = av_calloc(s->nb_threads, sizeof(*s->fft));
@@ -788,15 +797,16 @@ static int config_output(AVFilterLink *outlink) · 24 unmodified lines
788 s->dst_x = av_frame_alloc();797 s->dst_x = av_frame_alloc();
789 s->src_x = av_frame_alloc();798 s->src_x = av_frame_alloc();
790 s->kernel = av_calloc(s->frequency_band_count, sizeof(*s->kernel));799 s->kernel = av_calloc(s->frequency_band_count, sizeof(*s->kernel));
791 s->cache = ff_get_audio_buffer(inlink, s->fft_in_size * 2);800 s->cache = ff_get_audio_buffer(inlink, s->hop_size);
792 s->ch_out = ff_get_audio_buffer(inlink, s->frequency_band_count * 2 * s->ihop_size);801 s->ch_out = ff_get_audio_buffer(inlink, s->frequency_band_count * 2 * s->ihop_size);
802 s->over = ff_get_audio_buffer(inlink, s->frequency_band_count * 2 * s->ihop_size);
793 s->bh_out = ff_get_audio_buffer(inlink, s->frequency_band_count);803 s->bh_out = ff_get_audio_buffer(inlink, s->frequency_band_count);
794 s->ifft_in = av_frame_alloc();804 s->ifft_in = av_frame_alloc();
795 s->ifft_out = av_frame_alloc();805 s->ifft_out = av_frame_alloc();
796 s->index = av_calloc(s->input_padding_size, sizeof(*s->index));806 s->index = av_calloc(s->input_padding_size, sizeof(*s->index));
797 s->kernel_start = av_calloc(s->frequency_band_count, sizeof(*s->kernel_start));807 s->kernel_start = av_calloc(s->frequency_band_count, sizeof(*s->kernel_start));
798 s->kernel_stop = av_calloc(s->frequency_band_count, sizeof(*s->kernel_stop));808 s->kernel_stop = av_calloc(s->frequency_band_count, sizeof(*s->kernel_stop));
799 if (!s->outpicref || !s->fft_in || !s->fft_out || !s->src_x || !s->dst_x ||809 if (!s->outpicref || !s->fft_in || !s->fft_out || !s->src_x || !s->dst_x || !s->over ||
800 !s->ifft_in || !s->ifft_out || !s->kernel_start || !s->kernel_stop || !s->ch_out ||810 !s->ifft_in || !s->ifft_out || !s->kernel_start || !s->kernel_stop || !s->ch_out ||
801 !s->frequency_band || !s->cache || !s->index || !s->bh_out || !s->kernel)811 !s->frequency_band || !s->cache || !s->index || !s->bh_out || !s->kernel)
802 return AVERROR(ENOMEM);812 return AVERROR(ENOMEM);
@@ -880,6 +890,9 @@ static int config_output(AVFilterLink *outlink) · 77 unmodified lines
880 s->frequency_band_count, maximum_frequency - minimum_frequency,890 s->frequency_band_count, maximum_frequency - minimum_frequency,
881 minimum_frequency, s->frequency_scale, s->deviation);891 minimum_frequency, s->frequency_scale, s->deviation);
882 892
893 av_log(ctx, AV_LOG_DEBUG, "factor: %f\n", factor);
894 av_log(ctx, AV_LOG_DEBUG, "hop_size: %d\n", s->hop_size);
895 av_log(ctx, AV_LOG_DEBUG, "ihop_size: %d\n", s->ihop_size);
883 av_log(ctx, AV_LOG_DEBUG, "input_sample_count: %d\n", s->input_sample_count);896 av_log(ctx, AV_LOG_DEBUG, "input_sample_count: %d\n", s->input_sample_count);
884 av_log(ctx, AV_LOG_DEBUG, "input_padding_size: %d\n", s->input_padding_size);897 av_log(ctx, AV_LOG_DEBUG, "input_padding_size: %d\n", s->input_padding_size);
885 av_log(ctx, AV_LOG_DEBUG, "output_sample_count: %d\n", s->output_sample_count);898 av_log(ctx, AV_LOG_DEBUG, "output_sample_count: %d\n", s->output_sample_count);
@@ -1065,15 +1078,16 @@ static int output_frame(AVFilterContext *ctx) · 179 unmodified lines
1065 1078
1066 if (s->slide != SLIDE_FRAME || s->new_frame == 1) {1079 if (s->slide != SLIDE_FRAME || s->new_frame == 1) {
1067 int64_t pts_offset = s->new_frame ? 0LL : av_rescale(s->ihop_index, s->hop_size, s->ihop_size);1080 int64_t pts_offset = s->new_frame ? 0LL : av_rescale(s->ihop_index, s->hop_size, s->ihop_size);
1081 const int offset = (s->input_padding_size - s->hop_size) >> 1;
1068 1082
1069 pts_offset = av_rescale_q(pts_offset - s->input_sample_count/2, av_make_q(1, inlink->sample_rate), inlink->time_base);1083 pts_offset = av_rescale_q(pts_offset - offset, av_make_q(1, inlink->sample_rate), inlink->time_base);
1070 s->outpicref->pts = av_rescale_q(s->in_pts + pts_offset, inlink->time_base, outlink->time_base);1084 s->outpicref->pts = av_rescale_q(s->in_pts + pts_offset, inlink->time_base, outlink->time_base);
1071 s->outpicref->duration = 1;1085 s->outpicref->duration = 1;
1072 }1086 }
1073 1087
1074 s->ihop_index++;1088 s->ihop_index++;
1075 if (s->ihop_index >= s->ihop_size)1089 if (s->ihop_index >= s->ihop_size)
1076 s->ihop_index = 0;1090 s->ihop_index = s->hop_index = 0;
1077 1091
1078 if (s->slide == SLIDE_FRAME && s->new_frame == 0)1092 if (s->slide == SLIDE_FRAME && s->new_frame == 0)
1079 return 1;1093 return 1;
@@ -1127,7 +1141,7 @@ static int activate(AVFilterContext *ctx) · 47 unmodified lines
1127 if (s->outpicref) {1141 if (s->outpicref) {
1128 AVFrame *fin = NULL;1142 AVFrame *fin = NULL;
1129 1143
1130 if (s->ihop_index == 0) {1144 if (s->hop_index < s->hop_size) {
1131 if (!s->eof) {1145 if (!s->eof) {
1132 ret = ff_inlink_consume_samples(inlink, 1, s->hop_size - s->hop_index, &fin);1146 ret = ff_inlink_consume_samples(inlink, 1, s->hop_size - s->hop_index, &fin);
1133 if (ret < 0)1147 if (ret < 0)
@@ -1149,9 +1163,6 @@ static int activate(AVFilterContext *ctx) · 15 unmodified lines
1149 }1163 }
1150 1164
1151 if (s->hop_index >= s->hop_size || s->ihop_index > 0) {1165 if (s->hop_index >= s->hop_size || s->ihop_index > 0) {
1152 if (s->hop_index)
1153 s->hop_index = 0;
1154
1155 for (int ch = 0; ch < s->nb_channels && s->ihop_index == 0; ch++) {1166 for (int ch = 0; ch < s->nb_channels && s->ihop_index == 0; ch++) {
1156 ff_filter_execute(ctx, run_channel_cwt, (void *)&ch, NULL,1167 ff_filter_execute(ctx, run_channel_cwt, (void *)&ch, NULL,
1157 s->nb_threads);1168 s->nb_threads);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t