35 #if CONFIG_LIBFREETYPE
37 #include FT_FREETYPE_H
45 #define VIDEO_WIDTH 1920
46 #define VIDEO_HEIGHT 1080
47 #define FONT_HEIGHT 32
48 #define SPECTOGRAM_HEIGHT ((VIDEO_HEIGHT-FONT_HEIGHT)/2)
49 #define SPECTOGRAM_START (VIDEO_HEIGHT-SPECTOGRAM_HEIGHT)
50 #define BASE_FREQ 20.051392800492
51 #define COEFF_CLAMP 1.0e-4
87 #define OFFSET(x) offsetof(ShowCQTContext, x)
88 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
131 static const int samplerates[] = { 44100, 48000, -1 };
158 #if CONFIG_LIBFREETYPE
161 static const char str[] =
"EF G A BC D ";
163 FT_Library lib = NULL;
165 int video_scale = s->
fullhd ? 2 : 1;
168 int font_width = 8 * video_scale;
169 int font_repeat = font_width * 12;
170 int linear_hori_advance = font_width * 65536;
171 int non_monospace_warning = 0;
179 if (FT_Init_FreeType(&lib))
182 if (FT_New_Face(lib, s->
fontfile, 0, &face))
185 if (FT_Set_Char_Size(face, 16*64, 0, 0, 0))
188 if (FT_Load_Char(face,
'A', FT_LOAD_RENDER))
191 if (FT_Set_Char_Size(face, 16*64 * linear_hori_advance / face->glyph->linearHoriAdvance, 0, 0, 0))
198 memset(s->
font_alpha, 0, font_height * video_width);
200 for (x = 0; x < 12; x++) {
201 int sx, sy, rx, bx, by, dx, dy;
206 if (FT_Load_Char(face, str[x], FT_LOAD_RENDER))
209 if (face->glyph->advance.x != font_width*64 && !non_monospace_warning) {
211 non_monospace_warning = 1;
214 sy = font_height - 4*video_scale - face->glyph->bitmap_top;
215 for (rx = 0; rx < 10; rx++) {
216 sx = rx * font_repeat + x * font_width + face->glyph->bitmap_left;
217 for (by = 0; by < face->glyph->bitmap.rows; by++) {
221 if (dy >= font_height)
224 for (bx = 0; bx < face->glyph->bitmap.width; bx++) {
228 if (dx >= video_width)
230 s->
font_alpha[dy*video_width+dx] = face->glyph->bitmap.buffer[by*face->glyph->bitmap.width+bx];
237 FT_Done_FreeType(lib);
243 FT_Done_FreeType(lib);
262 int fft_len, k, x,
y;
265 double max_len = rate * (double) s->
timeclamp;
267 int video_scale = s->
fullhd ? 2 : 1;
290 for (x = 0; x < video_width; x++) {
291 if (x >= (12*3+8)*8*video_scale && x < (12*4+8)*8*video_scale) {
292 float fx = (x-(12*3+8)*8*video_scale) * (2.0f/(192.0f*video_scale));
300 #if CONFIG_LIBFREETYPE
301 load_freetype_font(ctx);
311 int hlen = fft_len >> 1;
315 double tlen = rate * (24.0 * 16.0) /freq;
320 double a0 = 0.355768;
321 double a1 = 0.487396/
a0;
322 double a2 = 0.144232/
a0;
323 double a3 = 0.012604/
a0;
324 double sv_step, cv_step, sv, cv;
325 double sw_step, cw_step, sw, cw, w;
327 tlen = tlen * max_len / (tlen + max_len);
332 sv_step = sv = sin(2.0*
M_PI*freq*(1.0/rate));
333 cv_step = cv = cos(2.0*
M_PI*freq*(1.0/rate));
335 sw_step = sw = sin(2.0*
M_PI*(1.0/tlen));
336 cw_step = cw = cos(2.0*
M_PI*(1.0/tlen));
337 for (x = 1; x < 0.5 * tlen; x++) {
338 double cv_tmp, cw_tmp;
339 double cw2, cw3, sw2;
341 cw2 = cw * cw - sw * sw;
342 sw2 = cw * sw + sw * cw;
343 cw3 = cw * cw2 - sw * sw2;
344 w = (1.0 + a1 * cw + a2 * cw2 + a3 * cw3) * (1.0/tlen) * s->
volume * (1.0/fft_len);
350 cv_tmp = cv * cv_step - sv * sv_step;
351 sv = sv * cv_step + cv * sv_step;
353 cw_tmp = cw * cw_step - sw * sw_step;
354 sw = sw * cw_step + cw * sw_step;
357 for (; x < hlen; x++) {
366 for (x = 0; x < fft_len; x++) {
372 for (x = 0; x < fft_len; x++)
375 for (x = 0; x < fft_len; x++) {
390 av_log(ctx,
AV_LOG_INFO,
"Elapsed time %.6f s (fft_len=%u, num_coeffs=%u)\n", 1e-6 * (end_time-start_time), fft_len, num_coeffs);
392 outlink->
w = video_width;
393 outlink->
h = video_height;
425 int video_scale = s->
fullhd ? 2 : 1;
441 for (x = 1; x <= fft_len >> 1; x++) {
458 float g = 1.0f / s->
gamma;
471 result[x][0] = l.
re * l.
re + l.
im * l.
im;
472 result[x][2] = r.
re * r.
re + r.
im * r.
im;
473 result[x][1] = 0.5f * (result[x][0] + result[x][2]);
474 result[x][3] = result[x][1];
475 result[x][0] = 255.0f *
powf(
FFMIN(1.0f,result[x][0]), g);
476 result[x][1] = 255.0f *
powf(
FFMIN(1.0f,result[x][1]), g);
477 result[x][2] = 255.0f *
powf(
FFMIN(1.0f,result[x][2]), g);
481 for (x = 0; x < video_width; x++) {
482 result[x][0] = 0.5f * (result[2*x][0] + result[2*x+1][0]);
483 result[x][1] = 0.5f * (result[2*x][1] + result[2*x+1][1]);
484 result[x][2] = 0.5f * (result[2*x][2] + result[2*x+1][2]);
485 result[x][3] = 0.5f * (result[2*x][3] + result[2*x+1][3]);
489 for (x = 0; x < video_width; x++) {
498 float rcp_result[VIDEO_WIDTH];
499 int total_length = linesize * spectogram_height;
502 for (x = 0; x < video_width; x++)
503 rcp_result[x] = 1.0f / (result[x][3]+0.0001f);
506 for (y = 0; y < spectogram_height; y++) {
507 float height = (spectogram_height -
y) * (1.0f/spectogram_height);
508 uint8_t *lineptr = data + y * linesize;
509 for (x = 0; x < video_width; x++) {
511 if (result[x][3] <= height) {
516 mul = (result[x][3] -
height) * rcp_result[x];
517 *lineptr++ = mul * result[x][0] + 0.5f;
518 *lineptr++ = mul * result[x][1] + 0.5f;
519 *lineptr++ = mul * result[x][2] + 0.5f;
526 for (y = 0; y < font_height; y++) {
527 uint8_t *lineptr = data + (spectogram_height +
y) * linesize;
529 for (x = 0; x < video_width; x++) {
532 lineptr[3*x] = (spectogram_src[3*x] * (255-
alpha) + (255-color) * alpha + 255) >> 8;
533 lineptr[3*x+1] = (spectogram_src[3*x+1] * (255-
alpha) + 255) >> 8;
534 lineptr[3*x+2] = (spectogram_src[3*x+2] * (255-
alpha) + color * alpha + 255) >> 8;
538 for (y = 0; y < font_height; y++) {
539 uint8_t *lineptr = data + (spectogram_height +
y) * linesize;
542 for (x = 0; x < video_width; x += video_width/10) {
544 static const char str[] =
"EF G A BC D ";
545 uint8_t *startptr = data + spectogram_height * linesize + x * 3;
546 for (u = 0; str[
u]; u++) {
548 for (v = 0; v < 16; v++) {
549 uint8_t *p = startptr + v * linesize * video_scale + 8 * 3 * u * video_scale;
550 int ux = x + 8 * u * video_scale;
552 for (mask = 0x80;
mask; mask >>= 1) {
557 if (video_scale == 2) {
559 p[linesize+1] = p[1];
560 p[linesize+2] = p[2];
561 p[3] = p[linesize+3] = 255 - s->
font_color[ux+1];
562 p[4] = p[linesize+4] = 0;
566 p += 3 * video_scale;
575 data += spectogram_start * linesize;
578 data += total_length - back_length;
608 for (x = 0; x < (fft_len-step); x++)
616 audio_data = (
float*) insamples->
data[0];
633 for (m = 0; m < fft_len-step; m++)
640 for (m = 0; m < remaining; m++) {
689 .description =
NULL_IF_CONFIG_SMALL(
"Convert input audio to a CQT (Constant Q Transform) spectrum video output."),
695 .priv_class = &showcqt_class,