From patchwork Wed May 10 08:51:19 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul B Mahol X-Patchwork-Id: 41564 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:dca6:b0:f3:34fa:f187 with SMTP id ky38csp3677180pzb; Wed, 10 May 2023 01:52:05 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ4zsJFCCmSKIouy6pPeX/tv+K4LzxRv0Z1ncomCa8O3pVwhUhCwTh9tOsd3gdFH9kRfspBs X-Received: by 2002:aa7:cd68:0:b0:50b:c8eb:96a6 with SMTP id ca8-20020aa7cd68000000b0050bc8eb96a6mr14064507edb.31.1683708725323; Wed, 10 May 2023 01:52:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1683708725; cv=none; d=google.com; s=arc-20160816; b=Pi8tZw7n0BovWfw17uPc4BGO/q66cCd1K5B0we/9fCIZuh+AK8rJ30933QHg+cUhax JVAXeOfT3Qmo/P3B8fva1upKmIRnA2+8LohXS3dFMx/N4GsFZb2FP04/Y2Q18jbQRAE5 BhdnsnF4ZYCxDDjWbLArtj3LJsjGILPPACt9QcAaFMtE7CFsCMQ9xrEEFUz/ajs0+CP1 mEvbwtQ0ko/txLJcF+EN+LHktXYMVKt2+2vnDmybX2jgkhab8Et3t2EC7dOoV0xwlaBQ 3BI4U6VonUH1YdDxNAvoy54fwkTcvSXZwo2kmsujsneIODSitS2z9yZyZFI83JZLKh/7 dNJw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence:subject:to :message-id:date:from:mime-version:dkim-signature:delivered-to; bh=Ja4KjNYGu4qu2mgZxfqAG1UDJkZKqW9gjqx5RVu0NhU=; b=e8o97FtmAwUKiLnQVVDB6ca4bkLysOs0U0JHrgUkjuhSwtZJYVBS+XZm95QIsWGuqS esM3Nr+Fe+0556Tl0jY9DvlMOy2fng0q4+f8iWIuf1ZwxwNp3AkCemc2iEUQ+EIQiIu3 WErRGmBTRa8be5LogQ/FHY1vjBcxB0P4fOaOtGQib5/iutYJ/Pf3mT0fVhGr22Pugm4P EfZWpPRSmB0jLZo/yEBkqsY8WMBUFKxGw3g6i2wJq36gM5NtPRgIoXLg4WJboHWh8MII f5GfUWen1Rrg4DUH/VZJ1wsu4H4uwHjJ7l9Obgd39YIEhkXn+ifc1AK72Fbv+ob6vilF U/RA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20221208 header.b=M38yOm3D; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id v17-20020aa7cd51000000b0050d83ee816asi2546863edw.494.2023.05.10.01.52.04; Wed, 10 May 2023 01:52:05 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20221208 header.b=M38yOm3D; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 5B62068B5DA; Wed, 10 May 2023 11:52:00 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-vk1-f171.google.com (mail-vk1-f171.google.com [209.85.221.171]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id A6C4F68B5DA for ; Wed, 10 May 2023 11:51:52 +0300 (EEST) Received: by mail-vk1-f171.google.com with SMTP id 71dfb90a1353d-44ff2f8ec9dso4298816e0c.1 for ; Wed, 10 May 2023 01:51:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1683708711; x=1686300711; h=to:subject:message-id:date:from:mime-version:from:to:cc:subject :date:message-id:reply-to; bh=mvJfS2V1Tjc9YZjo36+ewiSlCB0LezF3L5XX4LKmbNE=; b=M38yOm3DZ3HjKYpjH+Yw+OVEb+XliwvTvd987+bKVbN9YeOZV25MZrQtHL6MsH6VXq qLE9d9UuiWqnQG2b2vx1szmyfJLRcnaeJf2TCS5GjO8utDKovWTT8j5pd6/HB8LFI6/c fDC3s9m2DTS67yP9ybR0943X56RP5IRAPtoS95310R5WAkCoHkPN1v9TXotx64OX5/RU aCTLDoe+4nGdvxIxHpxYfSDvR/hrd9pcEE+6vRY1NLfrykuO/6HLotZNgCCpTqgCkaxg QZjF8yYRZr/W58cowWnJHgDyDE6qvlKZGmO51ND2fyLAvvGPm/+1IiCf8dEqj7bbQ2o8 jrLQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1683708711; x=1686300711; h=to:subject:message-id:date:from:mime-version:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=mvJfS2V1Tjc9YZjo36+ewiSlCB0LezF3L5XX4LKmbNE=; b=ZeB0vcV8j0DHGSsIU9vw1e9CUT+iMHzd+vsPqkpwWpO50S6eP0V/3d0tTsOehzdWso F8/9QK/IyZo5SIEHNDP7ptD79p7XSILS+p/1LYd9cp/U7bkqRAgFQe9YnrXmrLOi9/Fi O54AKy+0fgOwQj23by+Xfw95CHnYOxs7CWE5Pj3tFLLv1T2x3MF2L2EC5RvuXoiuby0X l32XFSTfiA5h/GX6A0mRot2xHbg09ovy7zfPiiD6aL6+anYuv/GhJkgyFHAhdTagAIxC Np3prXb7ljxwiBoqs4rpKWdsSzmcxsYS1a36PviCDxLugnFVmvzqdY8LSHxAU+GHLeIs IbXw== X-Gm-Message-State: AC+VfDxXzkz5vSvuN/5EqsJm/iWkk3LeYPEGoOSQz6r//5HWOwGQ6BOs dtnmEY6aQVtCBeYQ/JPrXST+4y3KAW9AULdGi9L/LhBR X-Received: by 2002:a1f:4684:0:b0:440:448c:27a0 with SMTP id t126-20020a1f4684000000b00440448c27a0mr4802299vka.8.1683708711090; Wed, 10 May 2023 01:51:51 -0700 (PDT) MIME-Version: 1.0 From: Paul B Mahol Date: Wed, 10 May 2023 10:51:19 +0200 Message-ID: To: FFmpeg development discussions and patches X-Content-Filtered-By: Mailman/MimeDel 2.1.29 Subject: [FFmpeg-devel] [PATCH] avcodec/avformat cleanup of pseudo stuff X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: /LCUy8J1CkGC Patches attached. If there is enough interest I'm willing to make proper audio filter source with more features and more formats support. From 60784c5360081543ec5a72d806a62b2f6c332dc8 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 10 May 2023 10:41:00 +0200 Subject: [PATCH 1/2] avcodec: remove obscure pseudo synth "decoder" Proper place for synths is in libavfilter. Signed-off-by: Paul B Mahol --- doc/decoders.texi | 8 - libavcodec/Makefile | 1 - libavcodec/allcodecs.c | 1 - libavcodec/codec_desc.c | 2 + libavcodec/codec_id.h | 2 + libavcodec/ffwavesynth.c | 473 ------------------------------------- libavcodec/version_major.h | 1 + 7 files changed, 5 insertions(+), 483 deletions(-) delete mode 100644 libavcodec/ffwavesynth.c diff --git a/doc/decoders.texi b/doc/decoders.texi index 09b8314dd2..1ecd8fe85b 100644 --- a/doc/decoders.texi +++ b/doc/decoders.texi @@ -240,14 +240,6 @@ correctly by using lavc's old buggy lpc logic for decoding. @end table -@section ffwavesynth - -Internal wave synthesizer. - -This decoder generates wave patterns according to predefined sequences. Its -use is purely internal and the format of the data it accepts is not publicly -documented. - @section libcelt libcelt decoder wrapper. diff --git a/libavcodec/Makefile b/libavcodec/Makefile index b0971ce833..1dec091b21 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -356,7 +356,6 @@ OBJS-$(CONFIG_EXR_ENCODER) += exrenc.o float2half.o OBJS-$(CONFIG_FASTAUDIO_DECODER) += fastaudio.o OBJS-$(CONFIG_FFV1_DECODER) += ffv1dec.o ffv1.o OBJS-$(CONFIG_FFV1_ENCODER) += ffv1enc.o ffv1.o -OBJS-$(CONFIG_FFWAVESYNTH_DECODER) += ffwavesynth.o OBJS-$(CONFIG_FIC_DECODER) += fic.o OBJS-$(CONFIG_FITS_DECODER) += fitsdec.o fits.o OBJS-$(CONFIG_FITS_ENCODER) += fitsenc.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 8eeed34e57..67b9a95e14 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -470,7 +470,6 @@ extern const FFCodec ff_eac3_encoder; extern const FFCodec ff_eac3_decoder; extern const FFCodec ff_evrc_decoder; extern const FFCodec ff_fastaudio_decoder; -extern const FFCodec ff_ffwavesynth_decoder; extern const FFCodec ff_flac_encoder; extern const FFCodec ff_flac_decoder; extern const FFCodec ff_ftr_decoder; diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index d40977d6b3..b86483871b 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -3131,6 +3131,7 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("codec2 (very low bitrate speech codec)"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, +#if FF_API_FFWAVESYNTH_CODECID { .id = AV_CODEC_ID_FFWAVESYNTH, .type = AVMEDIA_TYPE_AUDIO, @@ -3138,6 +3139,7 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Wave synthesis pseudo-codec"), .props = AV_CODEC_PROP_INTRA_ONLY, }, +#if FF_API_FFWAVESYNTH_CODECID { .id = AV_CODEC_ID_SONIC, .type = AVMEDIA_TYPE_AUDIO, diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h index 70800ec20b..299889c15b 100644 --- a/libavcodec/codec_id.h +++ b/libavcodec/codec_id.h @@ -504,7 +504,9 @@ enum AVCodecID { AV_CODEC_ID_ON2AVC, AV_CODEC_ID_DSS_SP, AV_CODEC_ID_CODEC2, +#if FF_API_WAVESYNTH_CODECID AV_CODEC_ID_FFWAVESYNTH, +#endif AV_CODEC_ID_SONIC, AV_CODEC_ID_SONIC_LS, AV_CODEC_ID_EVRC, diff --git a/libavcodec/ffwavesynth.c b/libavcodec/ffwavesynth.c deleted file mode 100644 index b932326fd0..0000000000 --- a/libavcodec/ffwavesynth.c +++ /dev/null @@ -1,473 +0,0 @@ -/* - * Wavesynth pseudo-codec - * Copyright (c) 2011 Nicolas George - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "libavutil/intreadwrite.h" -#include "libavutil/log.h" -#include "avcodec.h" -#include "codec_internal.h" -#include "decode.h" - - -#define SIN_BITS 14 -#define WS_MAX_CHANNELS 32 -#define INF_TS 0x7FFFFFFFFFFFFFFF - -#define PINK_UNIT 128 - -/* - Format of the extradata and packets - - THIS INFORMATION IS NOT PART OF THE PUBLIC API OR ABI. - IT CAN CHANGE WITHOUT NOTIFICATION. - - All numbers are in little endian. - - The codec extradata define a set of intervals with uniform content. - Overlapping intervals are added together. - - extradata: - uint32 number of intervals - ... intervals - - interval: - int64 start timestamp; time_base must be 1/sample_rate; - start timestamps must be in ascending order - int64 end timestamp - uint32 type - uint32 channels mask - ... additional information, depends on type - - sine interval (type fourcc "SINE"): - int32 start frequency, in 1/(1<<16) Hz - int32 end frequency - int32 start amplitude, 1<<16 is the full amplitude - int32 end amplitude - uint32 start phase, 0 is sin(0), 0x20000000 is sin(pi/2), etc.; - n | (1<<31) means to match the phase of previous channel #n - - pink noise interval (type fourcc "NOIS"): - int32 start amplitude - int32 end amplitude - - The input packets encode the time and duration of the requested segment. - - packet: - int64 start timestamp - int32 duration - -*/ - -enum ws_interval_type { - WS_SINE = MKTAG('S','I','N','E'), - WS_NOISE = MKTAG('N','O','I','S'), -}; - -struct ws_interval { - int64_t ts_start, ts_end; - uint64_t phi0, dphi0, ddphi; - uint64_t amp0, damp; - uint64_t phi, dphi, amp; - uint32_t channels; - enum ws_interval_type type; - int next; -}; - -struct wavesynth_context { - int64_t cur_ts; - int64_t next_ts; - int32_t *sin; - struct ws_interval *inter; - uint32_t dither_state; - uint32_t pink_state; - int32_t pink_pool[PINK_UNIT]; - unsigned pink_need, pink_pos; - int nb_inter; - int cur_inter; - int next_inter; -}; - -#define LCG_A 1284865837 -#define LCG_C 4150755663 -#define LCG_AI 849225893 /* A*AI = 1 [mod 1<<32] */ - -static uint32_t lcg_next(uint32_t *s) -{ - *s = *s * LCG_A + LCG_C; - return *s; -} - -static void lcg_seek(uint32_t *s, uint32_t dt) -{ - uint32_t a, c, t = *s; - - a = LCG_A; - c = LCG_C; - while (dt) { - if (dt & 1) - t = a * t + c; - c *= a + 1; /* coefficients for a double step */ - a *= a; - dt >>= 1; - } - *s = t; -} - -/* Emulate pink noise by summing white noise at the sampling frequency, - * white noise at half the sampling frequency (each value taken twice), - * etc., with a total of 8 octaves. - * This is known as the Voss-McCartney algorithm. */ - -static void pink_fill(struct wavesynth_context *ws) -{ - int32_t vt[7] = { 0 }, v = 0; - int i, j; - - ws->pink_pos = 0; - if (!ws->pink_need) - return; - for (i = 0; i < PINK_UNIT; i++) { - for (j = 0; j < 7; j++) { - if ((i >> j) & 1) - break; - v -= vt[j]; - vt[j] = (int32_t)lcg_next(&ws->pink_state) >> 3; - v += vt[j]; - } - ws->pink_pool[i] = v + ((int32_t)lcg_next(&ws->pink_state) >> 3); - } - lcg_next(&ws->pink_state); /* so we use exactly 256 steps */ -} - -/** - * @return (1<<64) * a / b, without overflow, if a < b - */ -static uint64_t frac64(uint64_t a, uint64_t b) -{ - uint64_t r = 0; - int i; - - if (b < (uint64_t)1 << 32) { /* b small, use two 32-bits steps */ - a <<= 32; - return ((a / b) << 32) | ((a % b) << 32) / b; - } - if (b < (uint64_t)1 << 48) { /* b medium, use four 16-bits steps */ - for (i = 0; i < 4; i++) { - a <<= 16; - r = (r << 16) | (a / b); - a %= b; - } - return r; - } - for (i = 63; i >= 0; i--) { - if (a >= (uint64_t)1 << 63 || a << 1 >= b) { - r |= (uint64_t)1 << i; - a = (a << 1) - b; - } else { - a <<= 1; - } - } - return r; -} - -static uint64_t phi_at(struct ws_interval *in, int64_t ts) -{ - uint64_t dt = ts - (uint64_t)in->ts_start; - uint64_t dt2 = dt & 1 ? /* dt * (dt - 1) / 2 without overflow */ - dt * ((dt - 1) >> 1) : (dt >> 1) * (dt - 1); - return in->phi0 + dt * in->dphi0 + dt2 * in->ddphi; -} - -static void wavesynth_seek(struct wavesynth_context *ws, int64_t ts) -{ - int *last, i; - struct ws_interval *in; - - last = &ws->cur_inter; - for (i = 0; i < ws->nb_inter; i++) { - in = &ws->inter[i]; - if (ts < in->ts_start) - break; - if (ts >= in->ts_end) - continue; - *last = i; - last = &in->next; - in->phi = phi_at(in, ts); - in->dphi = in->dphi0 + (ts - in->ts_start) * in->ddphi; - in->amp = in->amp0 + (ts - in->ts_start) * in->damp; - } - ws->next_inter = i; - ws->next_ts = i < ws->nb_inter ? ws->inter[i].ts_start : INF_TS; - *last = -1; - lcg_seek(&ws->dither_state, (uint32_t)ts - (uint32_t)ws->cur_ts); - if (ws->pink_need) { - uint64_t pink_ts_cur = (ws->cur_ts + (uint64_t)PINK_UNIT - 1) & ~(PINK_UNIT - 1); - uint64_t pink_ts_next = ts & ~(PINK_UNIT - 1); - int pos = ts & (PINK_UNIT - 1); - lcg_seek(&ws->pink_state, (uint32_t)(pink_ts_next - pink_ts_cur) * 2); - if (pos) { - pink_fill(ws); - ws->pink_pos = pos; - } else { - ws->pink_pos = PINK_UNIT; - } - } - ws->cur_ts = ts; -} - -static int wavesynth_parse_extradata(AVCodecContext *avc) -{ - struct wavesynth_context *ws = avc->priv_data; - struct ws_interval *in; - uint8_t *edata, *edata_end; - int32_t f1, f2, a1, a2; - uint32_t phi; - int64_t dphi1, dphi2, dt, cur_ts = -0x8000000000000000; - int i; - - if (avc->extradata_size < 4) - return AVERROR(EINVAL); - edata = avc->extradata; - edata_end = edata + avc->extradata_size; - ws->nb_inter = AV_RL32(edata); - edata += 4; - if (ws->nb_inter < 0 || (edata_end - edata) / 24 < ws->nb_inter) - return AVERROR(EINVAL); - ws->inter = av_calloc(ws->nb_inter, sizeof(*ws->inter)); - if (!ws->inter) - return AVERROR(ENOMEM); - for (i = 0; i < ws->nb_inter; i++) { - in = &ws->inter[i]; - if (edata_end - edata < 24) - return AVERROR(EINVAL); - in->ts_start = AV_RL64(edata + 0); - in->ts_end = AV_RL64(edata + 8); - in->type = AV_RL32(edata + 16); - in->channels = AV_RL32(edata + 20); - edata += 24; - if (in->ts_start < cur_ts || - in->ts_end <= in->ts_start || - (uint64_t)in->ts_end - in->ts_start > INT64_MAX - ) - return AVERROR(EINVAL); - cur_ts = in->ts_start; - dt = in->ts_end - in->ts_start; - switch (in->type) { - case WS_SINE: - if (edata_end - edata < 20 || avc->sample_rate <= 0) - return AVERROR(EINVAL); - f1 = AV_RL32(edata + 0); - f2 = AV_RL32(edata + 4); - a1 = AV_RL32(edata + 8); - a2 = AV_RL32(edata + 12); - phi = AV_RL32(edata + 16); - edata += 20; - dphi1 = frac64(f1, (int64_t)avc->sample_rate << 16); - dphi2 = frac64(f2, (int64_t)avc->sample_rate << 16); - in->dphi0 = dphi1; - in->ddphi = (int64_t)(dphi2 - (uint64_t)dphi1) / dt; - if (phi & 0x80000000) { - phi &= ~0x80000000; - if (phi >= i) - return AVERROR(EINVAL); - in->phi0 = phi_at(&ws->inter[phi], in->ts_start); - } else { - in->phi0 = (uint64_t)phi << 33; - } - break; - case WS_NOISE: - if (edata_end - edata < 8) - return AVERROR(EINVAL); - a1 = AV_RL32(edata + 0); - a2 = AV_RL32(edata + 4); - edata += 8; - break; - default: - return AVERROR(EINVAL); - } - in->amp0 = (uint64_t)a1 << 32; - in->damp = (int64_t)(((uint64_t)a2 << 32) - ((uint64_t)a1 << 32)) / dt; - } - if (edata != edata_end) - return AVERROR(EINVAL); - return 0; -} - -static av_cold int wavesynth_init(AVCodecContext *avc) -{ - struct wavesynth_context *ws = avc->priv_data; - int i, r; - - if (avc->ch_layout.nb_channels > WS_MAX_CHANNELS) { - av_log(avc, AV_LOG_ERROR, - "This implementation is limited to %d channels.\n", - WS_MAX_CHANNELS); - return AVERROR(EINVAL); - } - r = wavesynth_parse_extradata(avc); - if (r < 0) { - av_log(avc, AV_LOG_ERROR, "Invalid intervals definitions.\n"); - return r; - } - ws->sin = av_malloc(sizeof(*ws->sin) << SIN_BITS); - if (!ws->sin) - return AVERROR(ENOMEM); - for (i = 0; i < 1 << SIN_BITS; i++) - ws->sin[i] = floor(32767 * sin(2 * M_PI * i / (1 << SIN_BITS))); - ws->dither_state = MKTAG('D','I','T','H'); - for (i = 0; i < ws->nb_inter; i++) - ws->pink_need += ws->inter[i].type == WS_NOISE; - ws->pink_state = MKTAG('P','I','N','K'); - ws->pink_pos = PINK_UNIT; - wavesynth_seek(ws, 0); - avc->sample_fmt = AV_SAMPLE_FMT_S16; - return 0; -} - -static void wavesynth_synth_sample(struct wavesynth_context *ws, int64_t ts, - int32_t *channels) -{ - int32_t amp, *cv; - unsigned val; - struct ws_interval *in; - int i, *last, pink; - uint32_t c, all_ch = 0; - - i = ws->cur_inter; - last = &ws->cur_inter; - if (ws->pink_pos == PINK_UNIT) - pink_fill(ws); - pink = ws->pink_pool[ws->pink_pos++] >> 16; - while (i >= 0) { - in = &ws->inter[i]; - i = in->next; - if (ts >= in->ts_end) { - *last = i; - continue; - } - last = &in->next; - amp = in->amp >> 32; - in->amp += in->damp; - switch (in->type) { - case WS_SINE: - val = amp * (unsigned)ws->sin[in->phi >> (64 - SIN_BITS)]; - in->phi += in->dphi; - in->dphi += in->ddphi; - break; - case WS_NOISE: - val = amp * (unsigned)pink; - break; - default: - val = 0; - } - all_ch |= in->channels; - for (c = in->channels, cv = channels; c; c >>= 1, cv++) - if (c & 1) - *cv += (unsigned)val; - } - val = (int32_t)lcg_next(&ws->dither_state) >> 16; - for (c = all_ch, cv = channels; c; c >>= 1, cv++) - if (c & 1) - *cv += val; -} - -static void wavesynth_enter_intervals(struct wavesynth_context *ws, int64_t ts) -{ - int *last, i; - struct ws_interval *in; - - last = &ws->cur_inter; - for (i = ws->cur_inter; i >= 0; i = ws->inter[i].next) - last = &ws->inter[i].next; - for (i = ws->next_inter; i < ws->nb_inter; i++) { - in = &ws->inter[i]; - if (ts < in->ts_start) - break; - if (ts >= in->ts_end) - continue; - *last = i; - last = &in->next; - in->phi = in->phi0; - in->dphi = in->dphi0; - in->amp = in->amp0; - } - ws->next_inter = i; - ws->next_ts = i < ws->nb_inter ? ws->inter[i].ts_start : INF_TS; - *last = -1; -} - -static int wavesynth_decode(AVCodecContext *avc, AVFrame *frame, - int *rgot_frame, AVPacket *packet) -{ - struct wavesynth_context *ws = avc->priv_data; - int64_t ts; - int duration; - int s, c, r; - int16_t *pcm; - int32_t channels[WS_MAX_CHANNELS]; - - *rgot_frame = 0; - if (packet->size != 12) - return AVERROR_INVALIDDATA; - ts = AV_RL64(packet->data); - if (ts != ws->cur_ts) - wavesynth_seek(ws, ts); - duration = AV_RL32(packet->data + 8); - if (duration <= 0) - return AVERROR(EINVAL); - frame->nb_samples = duration; - r = ff_get_buffer(avc, frame, 0); - if (r < 0) - return r; - pcm = (int16_t *)frame->data[0]; - for (s = 0; s < duration; s++, ts+=(uint64_t)1) { - memset(channels, 0, avc->ch_layout.nb_channels * sizeof(*channels)); - if (ts >= ws->next_ts) - wavesynth_enter_intervals(ws, ts); - wavesynth_synth_sample(ws, ts, channels); - for (c = 0; c < avc->ch_layout.nb_channels; c++) - *(pcm++) = channels[c] >> 16; - } - ws->cur_ts += (uint64_t)duration; - *rgot_frame = 1; - return packet->size; -} - -static av_cold int wavesynth_close(AVCodecContext *avc) -{ - struct wavesynth_context *ws = avc->priv_data; - - av_freep(&ws->sin); - av_freep(&ws->inter); - return 0; -} - -const FFCodec ff_ffwavesynth_decoder = { - .p.name = "wavesynth", - CODEC_LONG_NAME("Wave synthesis pseudo-codec"), - .p.type = AVMEDIA_TYPE_AUDIO, - .p.id = AV_CODEC_ID_FFWAVESYNTH, - .priv_data_size = sizeof(struct wavesynth_context), - .init = wavesynth_init, - .close = wavesynth_close, - FF_CODEC_DECODE_CB(wavesynth_decode), - .p.capabilities = AV_CODEC_CAP_DR1, - .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, -}; diff --git a/libavcodec/version_major.h b/libavcodec/version_major.h index 40db213499..b7af4518c9 100644 --- a/libavcodec/version_major.h +++ b/libavcodec/version_major.h @@ -41,6 +41,7 @@ #define FF_API_IDCT_NONE (LIBAVCODEC_VERSION_MAJOR < 61) #define FF_API_SVTAV1_OPTS (LIBAVCODEC_VERSION_MAJOR < 61) #define FF_API_AYUV_CODECID (LIBAVCODEC_VERSION_MAJOR < 61) +#define FF_API_FFWAVESYNTH_CODECID (LIBAVCODEC_VERSION_MAJOR < 61) #define FF_API_VT_OUTPUT_CALLBACK (LIBAVCODEC_VERSION_MAJOR < 61) #define FF_API_AVCODEC_CHROMA_POS (LIBAVCODEC_VERSION_MAJOR < 61) #define FF_API_VT_HWACCEL_CONTEXT (LIBAVCODEC_VERSION_MAJOR < 61) -- 2.39.1