2. Dealing with multi-channels audio file
[1]:
import pprint
import matplotlib.pyplot as plt
import cutcutcodec
2.1. All supported audio layouts
2.1.1. Layouts and channels signification and convention
[2]:
# all supported layout by cutcutcodec
pprint.pprint(cutcutcodec.classes.layout.AllLayouts().layouts, compact=True)
{'2.1': ('fl', 'fr', 'lfe'),
'22.2': ('fl', 'fr', 'fc', 'lfe', 'bl', 'br', 'flc', 'frc', 'bc', 'sl', 'sr',
'tc', 'tfl', 'tfc', 'tfr', 'tbl', 'tbc', 'tbr', 'lfe2', 'tsl', 'tsr',
'bfc', 'bfl', 'bfr'),
'3.0': ('fl', 'fr', 'fc'),
'3.0(back)': ('fl', 'fr', 'bc'),
'3.1': ('fl', 'fr', 'fc', 'lfe'),
'3.1.2': ('fl', 'fr', 'fc', 'lfe', 'tfl', 'tfr'),
'4.0': ('fl', 'fr', 'fc', 'bc'),
'4.1': ('fl', 'fr', 'fc', 'lfe', 'bc'),
'5.0': ('fl', 'fr', 'fc', 'bl', 'br'),
'5.0(side)': ('fl', 'fr', 'fc', 'sl', 'sr'),
'5.1': ('fl', 'fr', 'fc', 'lfe', 'bl', 'br'),
'5.1(side)': ('fl', 'fr', 'fc', 'lfe', 'sl', 'sr'),
'5.1.2': ('fl', 'fr', 'fc', 'lfe', 'sl', 'sr', 'tfl', 'tfr'),
'5.1.2(back)': ('fl', 'fr', 'fc', 'lfe', 'bl', 'br', 'tfl', 'tfr'),
'5.1.4': ('fl', 'fr', 'fc', 'lfe', 'sl', 'sr', 'tfl', 'tfr', 'tbl', 'tbr'),
'6.0': ('fl', 'fr', 'fc', 'bc', 'sl', 'sr'),
'6.0(front)': ('fl', 'fr', 'flc', 'frc', 'sl', 'sr'),
'6.1': ('fl', 'fr', 'fc', 'lfe', 'bc', 'sl', 'sr'),
'6.1(back)': ('fl', 'fr', 'fc', 'lfe', 'bl', 'br', 'bc'),
'6.1(front)': ('fl', 'fr', 'lfe', 'flc', 'frc', 'sl', 'sr'),
'7.0': ('fl', 'fr', 'fc', 'bl', 'br', 'sl', 'sr'),
'7.0(front)': ('fl', 'fr', 'fc', 'flc', 'frc', 'sl', 'sr'),
'7.1': ('fl', 'fr', 'fc', 'lfe', 'bl', 'br', 'sl', 'sr'),
'7.1(wide)': ('fl', 'fr', 'fc', 'lfe', 'bl', 'br', 'flc', 'frc'),
'7.1(wide-side)': ('fl', 'fr', 'fc', 'lfe', 'flc', 'frc', 'sl', 'sr'),
'7.1.2': ('fl', 'fr', 'fc', 'lfe', 'bl', 'br', 'sl', 'sr', 'tfl', 'tfr'),
'7.1.4': ('fl', 'fr', 'fc', 'lfe', 'bl', 'br', 'sl', 'sr', 'tfl', 'tfr', 'tbl',
'tbr'),
'7.2.3': ('fl', 'fr', 'fc', 'lfe', 'bl', 'br', 'sl', 'sr', 'tfl', 'tfr', 'tbc',
'lfe2'),
'9.1.4': ('fl', 'fr', 'fc', 'lfe', 'bl', 'br', 'flc', 'frc', 'sl', 'sr', 'tfl',
'tfr', 'tbl', 'tbr'),
'9.1.6': ('fl', 'fr', 'fc', 'lfe', 'bl', 'br', 'flc', 'frc', 'sl', 'sr', 'tfl',
'tfr', 'tbl', 'tbr', 'tsl', 'tsr'),
'binaural': ('bil', 'bir'),
'cube': ('fl', 'fr', 'bl', 'br', 'tfl', 'tfr', 'tbl', 'tbr'),
'downmix': ('dl', 'dr'),
'hexadecagonal': ('fl', 'fr', 'fc', 'bl', 'br', 'bc', 'sl', 'sr', 'tfl', 'tfc',
'tfr', 'tbl', 'tbc', 'tbr', 'wl', 'wr'),
'hexagonal': ('fl', 'fr', 'fc', 'bl', 'br', 'bc'),
'mono': ('fc',),
'octagonal': ('fl', 'fr', 'fc', 'bl', 'br', 'bc', 'sl', 'sr'),
'quad': ('fl', 'fr', 'bl', 'br'),
'quad(side)': ('fl', 'fr', 'sl', 'sr'),
'stereo': ('fl', 'fr')}
[3]:
# the significance of each channel abreviation
pprint.pprint(cutcutcodec.classes.layout.AllLayouts().individuals)
{'bc': 'back center',
'bfc': 'bottom front center',
'bfl': 'bottom front left',
'bfr': 'bottom front right',
'bil': 'binaural left',
'bir': 'binaural right',
'bl': 'back left',
'br': 'back right',
'dl': 'downmix left',
'dr': 'downmix right',
'fc': 'front center',
'fl': 'front left',
'flc': 'front left-of-center',
'fr': 'front right',
'frc': 'front right-of-center',
'lfe': 'low frequency',
'lfe2': 'low frequency 2',
'sdl': 'surround direct left',
'sdr': 'surround direct right',
'sl': 'side left',
'sr': 'side right',
'ssl': 'side surround left',
'ssr': 'side surround right',
'tbc': 'top back center',
'tbl': 'top back left',
'tbr': 'top back right',
'tc': 'top center',
'tfc': 'top front center',
'tfl': 'top front left',
'tfr': 'top front right',
'tsl': 'top side left',
'tsr': 'top side right',
'ttl': 'top surround left',
'ttr': 'top surround right',
'wl': 'wide left',
'wr': 'wide right'}
2.1.2. Audio layout and codec compatibility
[4]:
from cutcutcodec.core.compilation.export.compatibility import Compatibilities
pprint.pprint(Compatibilities().codecs_audio(layout="5.1"), compact=True)
Testing encoder/muxer: 100%|███████████████████████████| 12775/12775 [00:10<00:00, 1234.37comb/s]
{'aac': [('aac', '3g2'), ('aac', '3gp'), ('aac', 'adts'), ('aac', 'asf'),
('aac', 'avi'), ('aac', 'f4v'), ('aac', 'flv'), ('aac', 'ipod'),
('aac', 'ismv'), ('aac', 'matroska'), ('aac', 'mov'), ('aac', 'mp4'),
('aac', 'mpegts'), ('aac', 'nut'), ('aac', 'rm'), ('aac', 'w64'),
('aac', 'wav'), ('aac', 'wtv')],
'aac_latm': [('aac', 'latm')],
'alac': [('alac', 'caf'), ('alac', 'ipod'), ('alac', 'ismv'),
('alac', 'matroska'), ('alac', 'mov'), ('alac', 'mp4')],
'vorbis': [('libvorbis', 'asf'), ('libvorbis', 'avi'), ('libvorbis', 'ismv'),
('libvorbis', 'matroska'), ('libvorbis', 'mp4'),
('libvorbis', 'nut'), ('libvorbis', 'oga'), ('libvorbis', 'ogg'),
('libvorbis', 'ogv'), ('libvorbis', 'opus'), ('libvorbis', 'spx'),
('libvorbis', 'w64'), ('libvorbis', 'wav'), ('libvorbis', 'webm'),
('libvorbis', 'wtv')],
'wavpack': [('wavpack', 'matroska'), ('wavpack', 'nut'), ('wavpack', 'wv')]}
2.2. Create multi-channel streams
[5]:
signal_stereo = cutcutcodec.generation.GeneratorAudioEquation(
"sin(2*pi*220*t)*sin(2*pi*1*t)**2", "sin(2*pi*220*t)*cos(2*pi*1*t)**2"
)
signal_3_1 = cutcutcodec.generation.GeneratorAudioEquation(
"sin(2*pi*440*t)", # fl
"cos(2*pi*440*t)", # fr
"sin(2*pi*523*t)", # fc
"sin(2.pi*27.5*t)", # lfe
layout="3.1",
)
2.2.1. Combine the channels of the different streams
[6]:
mix = (signal_stereo | signal_3_1).apply_audio_equation( # mix the channels as a 5.1 layer ('fl', 'fr', 'fc', 'lfe', 'bl', 'br'),
"(fl_0+fl_1)/2", # fl
"(fl_0+fl_1)/2", # fr
"0.8*fc_1 + 0.1*fl_0 + 0.1*fr_0", # fc
"lfe_1", # lfe
"(fl_0+fl_1)/2", # bl
"(fr_0+fr_1)/2", # br
)
(mix_stream,) = mix.out_streams
[7]:
frame = mix_stream.snapshot(0, 44100, 1024) # time, sample rate, nbr samples
[8]:
plt.plot(frame.timestamps, frame.T)
plt.xlabel("time (s)")
plt.ylabel("amplitude")
plt.title(
f"{frame.layout.name} audio frame at {frame.rate} Hz "
f"containing {frame.samples} samples starting at time {frame.time} s"
)
plt.show()
2.3. Write a multichannels audio file
[9]:
mix_cut = mix.apply_audio_subclip(0, 10) # select the 10 first seconds
cutcutcodec.write(mix_cut.out_streams, "/tmp/audio_5.1.opus", streams_settings=[{"encodec": "libvorbis", "rate": 44100}])
Encoding audio_5.1.opus: 100%|██████████████████████████████████████| 10.00s/10.00s [00:00<00:00]