aevalsrc¶
Watch on youtube.com- see also
This filter that produces sound is a bit more complex than sine
, but it is flexible using expressions.
If you just want to create a simple “sine wave”, of course sine
is easier:
#! /bin/sh
# 440Hz sine wave ("A4" in MIDI scale) for 4 secs.
ffplay -f lavfi 'sine=440:d=4'
#! /bin/sh
# same as above using with "aevalsrc"
ffplay -f lavfi 'aevalsrc=0.125 * sin(2 * PI * 440 * t):d=4'
#! /bin/sh
# C4 + E4 + G4
ffplay -f lavfi aevalsrc='
0.1 * (
sin(2 * PI * 261.6255653005986 * t) +
sin(2 * PI * 329.6275569128699 * t) +
sin(2 * PI * 391.9954359817493 * t)
):d=4'
#! /bin/sh
ffmpeg -y -filter_complex "
aevalsrc='0.1*(
sin(2*PI*t*261.62556530059862)
+ sin(2*PI*t*329.62755691286992)
+ sin(2*PI*t*391.99543598174927)
)':d=0.99[a00];
aevalsrc=0:d=0.0125[a01];
aevalsrc='0.1*(
sin(2*PI*t*261.62556530059862)
)':d=0.49[a02];
aevalsrc=0:d=0.0125[a03];
aevalsrc='0.1*(
sin(2*PI*t*329.62755691286992)
)':d=0.49[a04];
aevalsrc=0:d=0.0125[a05];
aevalsrc='0.1*(
sin(2*PI*t*391.99543598174927)
)':d=0.49[a06];
aevalsrc=0:d=0.0125[a07];
aevalsrc='0.1*(
sin(2*PI*t*329.62755691286992)
)':d=0.49[a08];
aevalsrc=0:d=0.0125[a09];
aevalsrc='0.1*(
sin(2*PI*t*261.62556530059862)
)':d=0.99[a10];
aevalsrc=0:d=0.0125[a11];
aevalsrc='0.1*(
sin(2*PI*t*277.18263097687208)
+ sin(2*PI*t*349.22823143300388)
+ sin(2*PI*t*415.30469757994513)
)':d=0.99[a12];
aevalsrc=0:d=0.0125[a13];
aevalsrc='0.1*(
sin(2*PI*t*277.18263097687208)
)':d=0.49[a14];
aevalsrc=0:d=0.0125[a15];
aevalsrc='0.1*(
sin(2*PI*t*349.22823143300388)
)':d=0.49[a16];
aevalsrc=0:d=0.0125[a17];
aevalsrc='0.1*(
sin(2*PI*t*415.30469757994513)
)':d=0.49[a18];
aevalsrc=0:d=0.0125[a19];
aevalsrc='0.1*(
sin(2*PI*t*349.22823143300388)
)':d=0.49[a20];
aevalsrc=0:d=0.0125[a21];
aevalsrc='0.1*(
sin(2*PI*t*277.18263097687208)
)':d=0.99[a22];
aevalsrc=0:d=0.0125[a23];
aevalsrc='0.1*(
sin(2*PI*t*293.66476791740757)
+ sin(2*PI*t*369.99442271163440)
+ sin(2*PI*t*440.00000000000000)
)':d=0.99[a24];
aevalsrc=0:d=0.0125[a25];
aevalsrc='0.1*(
sin(2*PI*t*293.66476791740757)
)':d=0.49[a26];
aevalsrc=0:d=0.0125[a27];
aevalsrc='0.1*(
sin(2*PI*t*369.99442271163440)
)':d=0.49[a28];
aevalsrc=0:d=0.0125[a29];
aevalsrc='0.1*(
sin(2*PI*t*440.00000000000000)
)':d=0.49[a30];
aevalsrc=0:d=0.0125[a31];
aevalsrc='0.1*(
sin(2*PI*t*369.99442271163440)
)':d=0.49[a32];
aevalsrc=0:d=0.0125[a33];
aevalsrc='0.1*(
sin(2*PI*t*293.66476791740757)
)':d=0.99[a34];
aevalsrc=0:d=0.0125[a35];
aevalsrc='0.1*(
sin(2*PI*t*311.12698372208092)
+ sin(2*PI*t*391.99543598174927)
+ sin(2*PI*t*466.16376151808993)
)':d=0.99[a36];
aevalsrc=0:d=0.0125[a37];
aevalsrc='0.1*(
sin(2*PI*t*311.12698372208092)
)':d=0.49[a38];
aevalsrc=0:d=0.0125[a39];
aevalsrc='0.1*(
sin(2*PI*t*391.99543598174927)
)':d=0.49[a40];
aevalsrc=0:d=0.0125[a41];
aevalsrc='0.1*(
sin(2*PI*t*466.16376151808993)
)':d=0.49[a42];
aevalsrc=0:d=0.0125[a43];
aevalsrc='0.1*(
sin(2*PI*t*391.99543598174927)
)':d=0.49[a44];
aevalsrc=0:d=0.0125[a45];
aevalsrc='0.1*(
sin(2*PI*t*311.12698372208092)
)':d=0.99[a46];
aevalsrc=0:d=0.0125[a47];
aevalsrc='0.1*(
sin(2*PI*t*329.62755691286992)
+ sin(2*PI*t*415.30469757994513)
+ sin(2*PI*t*493.88330125612413)
)':d=0.99[a48];
aevalsrc=0:d=0.0125[a49];
aevalsrc='0.1*(
sin(2*PI*t*329.62755691286992)
)':d=0.49[a50];
aevalsrc=0:d=0.0125[a51];
aevalsrc='0.1*(
sin(2*PI*t*415.30469757994513)
)':d=0.49[a52];
aevalsrc=0:d=0.0125[a53];
aevalsrc='0.1*(
sin(2*PI*t*493.88330125612413)
)':d=0.49[a54];
aevalsrc=0:d=0.0125[a55];
aevalsrc='0.1*(
sin(2*PI*t*415.30469757994513)
)':d=0.49[a56];
aevalsrc=0:d=0.0125[a57];
aevalsrc='0.1*(
sin(2*PI*t*329.62755691286992)
)':d=0.99[a58];
aevalsrc=0:d=0.0125[a59];
[a00][a01][a02][a03][a04][a05][a06][a07][a08][a09][a10][a11][a12][a13][a14]
[a15][a16][a17][a18][a19][a20][a21][a22][a23][a24][a25][a26][a27][a28][a29]
[a30][a31][a32][a33][a34][a35][a36][a37][a38][a39][a40][a41][a42][a43][a44]
[a45][a46][a47][a48][a49][a50][a51][a52][a53][a54][a55][a56][a57][a58][a59]
concat=n=60:v=0:a=1
" cegec.wav
Note the quotes. If you encounter an error like the following, you probably need quotes:
[me@host: ~]$ ffplay -f lavfi aevalsrc='0.1 * sin(2 * PI * t * (
> between(t, 0.000, 0.875) * 261.62556530 +
> between(t, 1.000, 1.875) * 261.62556530
> ))'
nan : 0.000 fd= 0 aq= 0KB vq= 0KB sq= 0B f=0/0
[Parsed_aevalsrc_0 @ 0000000001cde140] [Eval @ 00000000039df360] Missing ')' or too many args in 'between(t'
[lavfi @ 0000000001cdb0e0] Error initializing filter 'aevalsrc' with args '0.1 * sin(2 * PI * t * (
between(t'
aevalsrc=0.1 * sin(2 * PI * t * (
between(t, 0.000, 0.875) * 261.62556530 +
between(t, 1.000, 1.875) * 261.62556530
)): Invalid argument
[me@host: ~]$ # you need quotes
[me@host: ~]$ ffplay -f lavfi aevalsrc="'0.1 * sin(2 * PI * t * (
> between(t, 0.000, 0.875) * 261.62556530 +
> between(t, 1.000, 1.875) * 261.62556530 +
> between(t, 2.000, 2.875) * 391.99543598 +
> between(t, 3.000, 3.875) * 391.99543598 +
> between(t, 4.000, 4.875) * 440.00000000 +
> between(t, 5.000, 5.875) * 440.00000000 +
> between(t, 6.000, 7.875) * 391.99543598 +
> between(t, 8.000, 8.875) * 349.22823143 +
> between(t, 9.000, 9.875) * 349.22823143 +
> between(t, 10.000, 10.875) * 329.62755691 +
> between(t, 11.000, 11.875) * 329.62755691 +
> between(t, 12.000, 12.875) * 293.66476792 +
> between(t, 13.000, 13.875) * 293.66476792 +
> between(t, 14.000, 15.875) * 261.62556530
> ))'"
[me@host: ~]$ ffplay -f lavfi "aevalsrc='0.1 * sin(2 * PI * 440 * pow(t, 3))'"
[me@host: ~]$ ffplay -f lavfi "
> aevalsrc='0.2 * abs(1 - mod(t, 2)) * sin(2 * PI * 440 * t)'"
[me@host: ~]$ # visualize
[me@host: ~]$ ffplay -f lavfi "
> aevalsrc='0.2 * abs(1 - mod(t, 2)) * sin(2 * PI * 440 * t)'
> , asplit[out1], showvolume[out0]"
# -*- coding: utf-8 -*-
import subprocess
_lut = {'!': '-.-.--',
"'": '.----.',
'"': '.-..-.',
'$': '...-..-',
'&': '.-...',
'(': '-.--.',
')': '-.--.-',
'+': '.-.-.',
',': '--..--',
'-': '-....-',
'.': '.-.-.-',
'/': '-..-.',
'0': '-----',
'1': '.----',
'2': '..---',
'3': '...--',
'4': '....-',
'5': '.....',
'6': '-....',
'7': '--...',
'8': '---..',
'9': '----.',
':': '---...',
';': '-.-.-.',
'=': '-...-',
'?': '..--..',
'@': '.--.-.',
'A': '.-',
'B': '-...',
'C': '-.-.',
'D': '-..',
'E': '.',
'F': '..-.',
'G': '--.',
'H': '....',
'I': '..',
'J': '.---',
'K': '-.-',
'L': '.-..',
'M': '--',
'N': '-.',
'O': '---',
'P': '.--.',
'Q': '--.-',
'R': '.-.',
'S': '...',
'T': '-',
'U': '..-',
'V': '...-',
'W': '.--',
'X': '-..-',
'Y': '-.--',
'Z': '--..',
'_': '..--.-',
}
if hasattr("", "decode"):
_encode = lambda s: s.encode(sys.getfilesystemencoding())
else:
_encode = lambda s: s
def _play(message):
_onoff = []
_BREAK_CD = 0.075
_BREAK_CH = 0.500
_BREAK_P = 2.000
t = 0
for ch in message:
cd = _lut.get(ch.upper(), " ")
for c in cd:
if c == " ":
t += _BREAK_P
elif c == ".":
_LN = 0.25
_onoff.append("between(t, {}, {})".format(t, t + _LN))
t += _LN + _BREAK_CD
else:
_LN = 0.5
_onoff.append("between(t, {}, {})".format(t, t + _LN))
t += _LN + _BREAK_CD
t += _BREAK_CH
fc = "aevalsrc='0.1 * sin(2 * PI * t * 440 * ({}))':d={}".format(" + ".join(_onoff), t)
cmdl = [
"ffplay",
"-f", "lavfi",
fc,
"-autoexit"
]
subprocess.check_call(list(map(_encode, filter(None, cmdl))))
if __name__ == '__main__':
import sys
import argparse
ap = argparse.ArgumentParser()
ap.add_argument("message")
args = ap.parse_args()
_play(args.message)
This filter can create sounds for multiple channels at once:
#! /bin/sh
# left: A3 / right: A3 + 7.83Hz using with "sine"
ffplay -f lavfi "
sine=220.00:d=500[a1];
sine=227.83:d=500[a2];
[a1][a2]amerge=inputs=2"
#! /bin/sh
# same as above using with "aevalsrc"
ffplay -f lavfi "aevalsrc=
0.125 * sin(2 * PI * 220.00 * t) |
0.125 * sin(2 * PI * 227.83 * t):d=500"
#! /bin/sh
# visualize (showcqt)
ffplay -f lavfi "aevalsrc=
0.1 * sin(2 * PI * 220.00 * t) |
0.1 * sin(2 * PI * 227.83 * t):d=50,
asplit[out1],channelsplit[a1][a2];
[a1]showcqt=s=960x270,setsar=1[v1];
[a2]showcqt=s=960x270,setsar=1,vflip[v2];
[v1][v2]vstack[out0]"
#! /bin/sh
# visualize (showvolume), specifying the channel layout
ffplay -f lavfi "aevalsrc=
0.1 * sin(2 * PI * 220.00 * t) |
0.1 * sin(2 * PI * 227.83 * t):d=50:c=FL|FR,
asplit[out1],showvolume[out0]"
If the formula gets complicated, it is better to use another filter instead of trying to do it only with aevalsrc
.
#! /bin/sh
ffplay -f lavfi aevalsrc="'
0.3 * abs(1 - mod(t, 2)) * sin(2 * PI * 220.00 * t) |
0.3 * abs(1 - mod(t + 1, 2)) * sin(2 * PI * 227.83 * t)':d=500,
asplit[out1], showvolume[out0]"
#! /bin/sh
# almost same as above (using "volume" filter)
ffplay -f lavfi aevalsrc="'
abs(1 - mod(t, 2)) * sin(2 * PI * 220.00 * t) |
abs(1 - mod(t + 1, 2)) * sin(2 * PI * 227.83 * t)':d=500,
volume=0.3,
asplit[out1], showvolume[out0]"
#! /bin/sh
#
cat << __END__ > hearingc.ass
[Script Info]
PlayResX: 1920
PlayResY: 1080
WrapStyle: 1
[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, OutlineColour, BackColour, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: s1, mp,58,&H00F0F0F0,&H00FFF0F0,&H00D05050, 1,2,2, 7 ,30,30,30,0
[Fonts]
mp: meiryo.ttf
[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,00:00:00.00,00:00:08.00,s1,_,0,0,0,,{\pos(100,860)} 8000 Hz
Dialogue: 0,00:00:08.00,00:00:16.00,s1,_,0,0,0,,{\pos(100,860)} 10000 Hz
Dialogue: 0,00:00:16.00,00:00:24.00,s1,_,0,0,0,,{\pos(100,860)} 12000 Hz
Dialogue: 0,00:00:24.00,00:00:32.00,s1,_,0,0,0,,{\pos(100,860)} 13000 Hz
Dialogue: 0,00:00:32.00,00:00:40.00,s1,_,0,0,0,,{\pos(100,860)} 14000 Hz
Dialogue: 0,00:00:40.00,00:00:48.00,s1,_,0,0,0,,{\pos(100,860)} 15000 Hz
Dialogue: 0,00:00:48.00,00:00:56.00,s1,_,0,0,0,,{\pos(100,860)} 17000 Hz
Dialogue: 0,00:00:56.00,00:00:64.00,s1,_,0,0,0,,{\pos(100,860)} 19000 Hz
__END__
#
ffmpeg -y -filter_complex "
aevalsrc='
sin(2 * PI * (
between(t, 16 * 0, 16 * 1) * 8000
+ between(t, 16 * 2, 16 * 3) * 10000
+ between(t, 16 * 4, 16 * 5) * 12000
+ between(t, 16 * 6, 16 * 7) * 13000
+ between(t, 16 * 8, 16 * 9) * 14000
+ between(t, 16 * 10, 16 * 11) * 15000
+ between(t, 16 * 12, 16 * 13) * 17000
+ between(t, 16 * 14, 16 * 15) * 19000
) * t) |
sin(2 * PI * (
between(t, 16 * 1, 16 * 2) * 8000
+ between(t, 16 * 3, 16 * 4) * 10000
+ between(t, 16 * 5, 16 * 6) * 12000
+ between(t, 16 * 7, 16 * 8) * 13000
+ between(t, 16 * 9, 16 * 10) * 14000
+ between(t, 16 * 11, 16 * 12) * 15000
+ between(t, 16 * 13, 16 * 14) * 17000
+ between(t, 16 * 15, 16 * 16) * 19000
) * t):s=192000:c=FL|FR
'
,volume='if(lt(st(0, mod(t, 4)), 1.5), ld(0) / 1.5, if(lt(ld(0), 2.5), 1, (4 - ld(0)) / 1.5))':eval=frame
,atempo=2,atempo=2
,asplit=5[a][a1][a2][a3][a4];
[a1]showcqt=s=1920x1080,setsar=1[vcqt];
[a2]showvolume=w=1760,scale=1760:40,setsar=1,colorkey=black[vv];
[a3]showwaves=split_channels=1:mode=line:colors=red@0.8|green@0.9:s=1760x480,setsar=1[vs];
[a4]ahistogram=s=1760x500:dmode=separate:slide=scroll,setsar=1,colorkey=black[vh];
[vs][vv]overlay=x=0:y=(H-h)/2[v1];
[vcqt][v1]overlay=x=(W-w)/2:y=50[v2];
[v2][vh]overlay=x=(W-w)/2:y=560,subtitles=hearingc.ass[v]
" -map '[v]' -map '[a]' -t 70 hearingc.mkv
To use shell variables or functions is also good idea:
#! /bin/sh
function _ampl() {
echo "abs(1 - mod($1, 2))";
}
ffplay -f lavfi "aevalsrc='
0.3 * `_ampl t` * sin(2 * PI * 220.00 * t) |
0.3 * `_ampl '(t + 1)'` * sin(2 * PI * 227.83 * t)':d=500,
asplit[out1], showvolume[out0]"
- see also
making silence audio stream¶
Naturally, you can make silence by giving zero as the frequency.
In video combining or audio mixing, it is sometimes necessary to produce a silent audio stream.
In these cases, you can use aevalsrc
, sine
, apad
, or anullsrc
.
You may feel anullsrc
is useful, but because you can’t give it a duration, so you probably find aevalsrc
easier to use:
#! /bin/sh
ifn1=bb20.mp4 # 20 secs / 48000Hz
ifn2=bb30.mp4 # 30 secs / 48000Hz
#
ffmpeg -y -i ${ifn1} -i ${ifn2} -filter_complex "
sine=0:d=10:r=48000[L];
sine=0:d=10:r=48000[R];
[L][R]amerge[pad_a];
[0:a][pad_a]concat=n=2:a=1:v=0[a0];
[a0][1:a]amix=inputs=2,asplit[a][av];
[av]channelsplit[av1][av2];
[av1]showcqt=s=960x270,setsar=1[v1];
[av2]showcqt=s=960x270,setsar=1,vflip[v2];
[v1][v2]vstack[v]
" -map '[v]' -map '[a]' amixed0.mp4
#! /bin/sh
ifn1=bb20.mp4 # 20 secs / 48000Hz
ifn2=bb30.mp4 # 30 secs / 48000Hz
#
ffmpeg -y -i ${ifn1} -i ${ifn2} -filter_complex "
anullsrc=r=48000:cl=stereo,atrim=0:10[pad_a];
[0:a][pad_a]concat=n=2:a=1:v=0[a0];
[a0][1:a]amix=inputs=2,asplit[a][av];
[av]channelsplit[av1][av2];
[av1]showcqt=s=960x270,setsar=1[v1];
[av2]showcqt=s=960x270,setsar=1,vflip[v2];
[v1][v2]vstack[v]
" -map '[v]' -map '[a]' amixed1.mp4
#! /bin/sh
ifn1=bb20.mp4 # 20 secs / 48000Hz
ifn2=bb30.mp4 # 30 secs / 48000Hz
#
ffmpeg -y -i ${ifn1} -i ${ifn2} -filter_complex "
aevalsrc='0|0:s=48000:d=10'[pad_a];
[0:a][pad_a]concat=n=2:a=1:v=0[a0];
[a0][1:a]amix=inputs=2,asplit[a][av];
[av]channelsplit[av1][av2];
[av1]showcqt=s=960x270,setsar=1[v1];
[av2]showcqt=s=960x270,setsar=1,vflip[v2];
[v1][v2]vstack[v]
" -map '[v]' -map '[a]' amixed2.mp4
- see also