And do both left and right zero-padding for forward FFT.
Showing the changes to libavfilter (1 of 1 file). Show all
Unified · Split
| @@ -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); |